Altitude Module for eZ430-Chronos

Posted on December 7, 2017. Tagged as: eZ430-Chronos

Here is a little writeup of the steps taken to implement an altitude module eZ430-Chronos within openchronos-ng-elf. The challenge is that the MSP430 controller is a 16bit RISC controller, which has no floating point and no builtin multiply/divide instructions. In addition, the code size is limited to 32K

The TI eZ430-Chronos contains a pressure sensor. To calculate the altitude from current pressure according to International Standard Atmosphere (ISA) we can derive the following equations:

A number of input values are constant:

Putting the constants into the ISA formula, we get:

As reference this uses p0, the current pressure reduced to mean sea level using the International Standard Atmosphere. In aviation that’s called QNH and can be looked up online for the closest airport.

Straigt-forward Implementation Using libm

Implementing the altitude function using pow() from libm, large chunks of libm get linked, resulting in a code size of about 16.8K. That is a lot, considering the controller in the eZ430-Chronos has only 32K of flash memory. So a better implementation is needed.

Implementing xy with Binomial Series

Next idea was to replace the exponentiation part of the formula with a binomial series, which doesn’t require to link libm anymore. That leaves only multiplications and additions after pre-computing the constants:

For low altitudes (p ~ QNH, x ~ 1) the series converges pretty quickly. As termination criterium for the series the step size seems to work ok. The resulting altitude module code size is reduced to about 8K.

Lookup Table with Interpolation

The next optimization step was to use a lookup table with interpolation. This allows to avoid floating point math entirely. The function to replace with a lookup table looks like this:

Altitude Plot, p0 = QNH, p1 = current pressure, z = altitude
Altitude Plot, p0 = QNH, p1 = current pressure, z = altitude

The lookup table has been generated with a ruby script, that also determines the maximum error in a brute force way by feeding all possible input values into the lookup table and comparing with the exact altitude.

To get an error of max 5 ft with a QNH between 900 and 1100 and a pressure between 500 hPa and 1100 hPA a table size of 1342 bytes is sufficient. Since the lookup table generator places nodes directly onto the exact function values, we could optimize a bit by moving the points slightly off the exact value to minimize the error squares.

The resulting code including lookup table is reduced to about 3.6K. The code can be found on GitHub.

Results

The following table compares code size of various alternatives with the firmware without altitude module compiled in (baseline).

---------------------------------------------------
Module            rodata    text     sum   relative
---------------  -------  ------  ------  ---------
baseline             356   13056   13412          0
lookup table        1738   15399   17137       3725
binomial series      716   20918   21634       8222
libm                 722   29894   30616      17204
---------------  -------  ------  ------  ---------