MicroPeak USB Interface now available.
Altus Metrum is pleased to announce the immediate availability of the MicroPeak USB interface.
Connects the MicroPeak altimeter to USB.
Records 48 seconds of flight
Barometric pressure values recorded about 5 times per second.
Save, graph and export pressure, height, speed and acceleration data.
Supports Linux, Mac OS X and Windows. The software is available on the MicroPeak web page.
Learn more at http://www.altusmetrum.org/MicroPeakUSB
Buy these for $35 at the gag.com web store for Altus Metrum products. Or get one bundled with a MicroPeak and save $10.
MicroPeak USB Interface
MicroPeak and the MicroPeak USB Interface
MicroPeak is fun to use all by itself, providing a quick way to know how high your rocket has flown. But, for those people itching for more data, MicroPeakUSB offers a way to download raw flight data and analyze that on your computer.
MicroPeakUSB doesn’t require any changes to the MicroPeak hardware—new MicroPeak firmware transmits the entire flight log through the on-board LED to a phototransistor on the MicroPeakUSB Interface and then to the USB port on your computer.
Existing MicroPeak owners can contact us for a special deal on the MicroPeak USB interface and upgrading the MicroPeak firmware.
MicroPeak Serial Interface — Flight Logging for MicroPeak
MicroPeak was original designed as a simple peak-recording altimeter. It displays the maximum height of the last flight by blinking out numbers on the LED.
Peak recording is fun and easy, but you need a log across apogee to check for unexpected bumps in baro data caused by ejection events. NAR also requires a flight log for altitude records. So, we wondered what could be done with the existing MicroPeak hardware to turn it into a flight logging altimeter.
Logging the data
The 8-bit ATtiny85 used in MicroPeak has 8kB of flash to store the executable code, but it also has 512B (yes, B as in “bytes”) of eeprom storage for configuration data. Unlike the code flash, the little eeprom can be rewritten 100,000 times, so it should last for a lifetime of rocketry.
The original MicroPeak firmware already used that to store the average ground pressure and minimum pressure (in Pascals) seen during flight; those are used to compute the maximum height that is shown on the LED. If we store just the two low-order bytes of the pressure data, we’d have room left for 251 data points. That means capturing data at least every 32kPa, which is about 3km at sea level.
251 points isn’t a whole lot of storage, but we really only need to capture the ascent and arc across apogee, which generally occurs within the first few seconds of flight.
MicroPeak samples air pressure once every 96ms, if we record half of those samples, we’ll have data every 192ms. 251 samples every 192ms captures 48 seconds of flight. A flight longer than that will just see the first 48 seconds. Of course, if apogee occurs after that limit, MicroPeak will still correctly record that value, it just won’t have a continuous log.
Downloading the data
Having MicroPeak record data to the internal eeprom is pretty easy, but it’s not a lot of use if you can’t get the data into your computer. However, there aren’t a whole lot of interfaces avaialble on MicroPeak. We’ve only got:
The 6-pin AVR programming header. This is how we load firmware onto MicroPeak during manufacturing. It’s not locked (of course), and the hardware supports reading and writing of flash, ram and eeprom.
The LED. We already use this to display the maximum height of the previous flight, can we blink it faster and then get the computer to read it out?
First implementation
I changed the MicroPeak firmware to capture data to eeprom and made a ‘test flight’ using my calibrated barometric chamber (a large syringe). I was able to read out the flight data using the AVR programming pins and got the flight logging code working that way.
The plots I created looked great, but using an AVR programmer to read the data looked daunting for most people as it requires:
An AVR programmer. Adafruit sells the surprisingly useful USBtinyISP programmer. There are Windows drivers available for this, and you can get the necessary avrdude binaries from the usbtiny page above. The programmer itself comes in kit form, so you have to solder it together. There are other programmers available for a bit more than come pre-assembled, but all of them require that you wander around the net finding the necessary drivers and programming software.
A custom MicroPeak programming jig. We have these for sale in the Altus Metrum web store but, because they need special pogo pins and a pile of custom circuit boards, they’re not cheap to make.
With the hardware running at least $120 retail, and requiring a pile of software installed from various places around the net, this approach didn’t seem like a great way to let people easily capture flight data from their tiny altimeter.
The Blinking LED
The only other interface available is the MicroPeak LED. It’s a nice LED, bright and orange and low power. But, it’s still just a single LED. However, it seemed like it might be possible to have it blink out the data and create a device to watch the LED and connect that to a USB port.
The simplest idea I had was to just blink out the data in asynchronous serial form; a start bit, 8 data bits and a stop bit. On the host side, I could use a regular FTDI FT230 USB to serial converter chip. Those even have a 3.3V regulator and can supply a bit of current to other components on the board, eliminating the need for an external power supply.
To ‘see’ the LED blink, I needed a photo-transistor that actually responds to the LED’s wavelength. Most photo-transistors are designed to work with infrared light, which nicely makes the whole setup invisible. There are a few photo-transistors available which do respond in the visible range, and ROHM RPM-075PT actually has its peak sensitivity right in the same range as the LED.
In between the photo-transistor and the FT230, I needed a detector circuit which would send a ‘1’ when the light was present and a ‘0’ when it wasn’t. To me, that called for a simple comparator made from an op-amp. Set the voltage on the negative input to somewhere between ‘light’ and ‘dark’ and then drive the positive input from the photo-transistor; the output would swing from rail to rail.
Bit-banging async
The ATtiny85 has only a single ‘serial port’, which is used on MicroPeak to talk to the barometric sensor in SPI mode. So, sending data out the LED requires that it be bit-banged — directly modulated with the CPU.
I wanted the data transmission to go reasonably fast, so I picked a rate of 9600 baud as a target. That means sending one bit every 104µS. As the MicroPeak CPU is clocked at only 250kHz, that leaves only about 26 cycles per bit. I need all of the bits to go at exactly the same speed, so I pack the start bit, 8 data bits and stop bit into a single 16 bit value and then start sending.
Of course, every pass around the loop would need to take exactly the same number of cycles, so I carefully avoided any conditional code. With that, 14 of the 26 cycles were required to just get the LED set to the right value. I padded the loop with 12 nops to make up the remaining time.
At 26 cycles per bit, it’s actually sending data at a bit over 9600 baud, but the FT230 doesn’t seem to mind.
A bit of output structure
I was a bit worried about the serial converter seeing other light as random data, so I prefixed the data transmission with ‘MP’; that made it easy to ignore anything before those two characters as probably noise.
Next, I decided to checksum the whole transmission. A simple 16-bit CRC would catch most small errors; it’s easy enough to re-try the operation if it fails after all.
Finally, instead of sending the data in binary, I displayed each byte as two hex digits, and sent some newlines along to keep the line lengths short. This makes it easy to ship flight logs in email or whatever.
Here’s a sample of the final data format:
MP
dc880100fec000006800f56d8f63b059
73516447273fa93728301927d91b7712
730bbf0491fe88f7c5ee8ee896e3fadc
9dd9d3d502d1afcea2cbafc6b4c34ec1
bfbfcabf10c03dc05dc070c084c08fc0
9cc0abc0b9c0c1c0ccc0dcc020c152c4
71c9a6cf45d623db7de05ee758edd9f2
b4f9fd00aa074311631a9221c4291330
c035873b2943084bbb52695c0c67eb6b
d26ee5707472fb74a4781f7dee802b84
09860a87e786ad868a866e8659865186
4e8643863e863986368638862e862d86
2f862d86298628862a86268629862686
28862886258625862486
d925
Making the photo-transistor go fast enough
The photo-transistor acts as one half of a voltage divider on the positive op-amp terminal, with a resistor making the other half. However, the photo-transistor acts a bit like a capacitor, so when I initially chose a fairly large value for the resistor, it actually took too long to switch between on and off — the transistor would spend a bunch of time charging and discharging. I had to reduce the resistor to 1kΩ for the circuit to work.
Remaining hardware design
I prototyped the circuit on a breadboard using a through-hole op-amp that my daughter designed into her ultrasonic guided robot and a prefabricated FTDI Friend board. I wanted to use the target photo-transistor, so I soldered a couple of short pieces of wire onto the SMT pads and stuck that into the breadboard.
Once I had that working, I copied the schematic to gschem, designed a board and had three made at OSHPark for the phenomenal sum of $1.35.
Aside from goofing up on the FT230 USB data pins (swapping D+ and D-), the board worked perfectly.
The final hardware design includes an LED connected to the output of the comparator that makes it easier to know when things are lined up correctly, otherwise it will be essentially the same.
Host software
Our AltosUI code has taught us a lot about delivering code that runs on Linux, Mac OS X and Windows, so I’m busy developing something based on the same underlying Java bits to support MicroPeak. Here’s a sample of the graph results so far:
Production plans
I’ve ordered a couple dozen raw boards from OSH Park, and once those are here, I’ll build them and make them available for sale in a couple of weeks. The current plan is to charge $35 for the MicroPeak serial interface board, or sell it bundled with MicroPeak for $75.
MicroPeak — tiny peak-recording altimeter now available
MicroPeak is a miniature peak-recording altimeter. About the same size and weight as a US dime (with battery), MicroPeak offers fabulous accuracy (20cm or 8in at sea level) and wide range (up to 31km or 101k’).
Uses the Measurement Specialties MS5607 barometric sensor.
Includes built-in battery holder for easily replaceable CR1025 lithium battery
Compact design is only 18mm x 14mm or 0.7” x 0.56”. Weighs 1.9g including the battery.
Low power design lasts for over 40 hours in flight.
Auto-poweroff on landing.
Learn more at the Altus Metrum web site
Buy these at the gag.com web store for Altus Metrum products
The size of the board was predicated with the premise that we needed a battery included to avoid having wiring running between the altimeter and the board, we found some small lithium coin-cell battery holders for the CR1025 battery. These battery holders are rated to hold the battery secure up to 150gs.
We’d already started playing with the Measurement Specialties MS5607 pressure sensor which offers amazing accuracy while using very little power. Taking full-precision measurements every 96ms consumes about .2mA on average. Once on the ground, we stop taking measurements entirely, dropping the power use to around 1µA. It’s also pretty small, measuring only 5mm x 3mm.
For a CPU, this little project didn’t need much. The 8-bit ATtiny85 comes in a 20qwfn package which is only 4mm x 4mm. When run at full speed (8MHz), it consumes a couple of mA of power. Reduce the clock to a pokey 250kHz and the CPU has enough CPU power to track altitude while consuming less than .2mA on average.
To avoid losing the battery, we wanted to avoid having it removed while the board wasn’t in use. So, we added a little power switch to the board. The one we found is good to at least 50g.
Finally, we wanted to find a nice bright LED to show the state of the device and to blink out the final altitude. The OSRAM LO T67K are bright-orange surface-mount LEDs that run happily on 2mA.
We used OSHPark.com to create prototype circuit boards for this project. Because of the small size of the board, each prototype run cost only $2 for three boards. It takes a couple of weeks to get boards, but it’s really hard to beat the price.
All of the schematic and circuit board artwork are published under the TAPR Open Hardware License and are available via git.
All of the source code is published under the GPLv2 and is included in the main AltOS source repository.
AltOS 1.1 — Bug fixes and some nice new features
Bdale and I are pleased to announce the release of AltOS version 1.1.
AltOS is the core of the software for all of the Altus Metrum products. It consists of cc1111-based micro-controller firmware and Java-based ground station software.
We’ve spent the last flying season chatting with people flying TeleMetrum and TeleMini boards and they came up with some great ideas to add to the system.
AltOS Firmware — Features and fixes
There are bug fixes in both ground station and flight software, so you should plan on re-flashing both units at some point. However, there aren’t any incompatible changes, so you don’t have to do it all at once.
New features:
Apogee-lockout timer. For situations where the normal apogee determination algorithm could be fooled, we’ve added a timeout value to prevent premature firing of the apogee charge. Normal flights won’t need this, but a couple of users asked for this feature.
RSSI value for Monitor Idle mode. The TeleDongle firmware has been updated to report signal strength information for data received from the altimeter. This allows the user to see how well the radio is working without having to switch to flight mode.
Force the radio to 434.550MHz. This is useful with TeleMini devices where the only way to talk to the device is through the radio. If you don’t know the frequency, it’s really hard to make that work.
Bug fixes:
- Stale telemetry data reported when switching frequencies. TeleDongle would accidentally re-transmit old telemetry packets when the radio frequency was changed. This would be harmless except that when scanning to find the frequency used by an altimeter, you’d appear to get packets at every frequency.
AltosUI — Easier to use
AltosUI has also seen quite a bit of work for the 1.1 release. There aren’t any huge new features, but some activities are restructured to make them easier to navigate. And, of course, we’ve fixed a bunch of bugs.
New features:
Configure Ground Station activity. This provides a way to set the default radio frequency for each TeleDongle. This replicates the frequency menu present in the Monitor Flight activity, but doesn’t also bring up that giant window.
Support the apogee lockout timer. This just adds another entry in the dialog for configuring the altimeter to configure the new timer. By default, the timer is disabled, allowing the apogee detection code in the flight computer to operate normally.
Add imperial units option. When enabled, this uses imperial units (feet and miles) for all values on the screen and in the voice announcements.
User interface changes:
Make the look-n-feel configurable. Java offers many different user interface styles on each platform. This exposes the available set and lets the user pick one. By default, we continue to use the native platform appearance.
Add an ‘Age’ element to the Monitor Flight UI. This shows how long it has been since the last valid telemetry packet was received, making it easy to tell when communications are lost.
Change flight data downloading. Instead of selecting which to download and which to delete at the same time, the interface now has separate steps for downloading and then deleting files. This makes it easier to verify that the files were downloaded before deleting flights from the on-board memory.
Re-compute boost and landing times. Given the whole flight history, it’s easy to find the time when the rocket started and stopped flying. Having these get recomputed means the boost time, acceleration values and main descent rates are computed more accurately.
Bug fixes:
Wait for 10 valid GPS messages before marking GPS as ready. Before this fix, GPS was marked as ready when 10 valid packets were received from the flight computer after the first valid GPS data arrived. This waits for 10 valid GPS packets instead.
Fix Google Earth file export. The format requirements for Google Earth files became more strict in recent releases; this patch changes how the files are formatted to make them work again.
Make AltosUI run on Mac OS X “Lion”. Apple changed the default heap size for Java applications with this release, dramatically reducing the memory available to applications. This would cause map tiles to fail to load and other random problems.
Improve COM port handling on Windows. This eliminates the need to wait 5 seconds between closing and re-opening devices, and also eliminates other spurious errors when opening devices.
Forward Error Correction with the TI CC1120 Sub-GHz transceiver
We’re building a new, fancier flight computer and decided to give the new, fancier TI CC1120 chip a try. It has significantly more transmit power (+16dBm) and receive sensitivity (-109dBm) than the transciever built in to the TI CC1111 RF SoC that we’ve built our other boards with. Given that we’d already decided to use a fancier STM32L processor, using the nicest stand-alone radio chip we could find seemed to make good sense.
One of the nice features found in the CC1111 is support for FEC using a 1/2 rate constraint length 4 convolutional code. Both the encoder and the soft-decision Viterbi decoder are built right into the chip; all we had to do was flip a couple of bits and we got error correction, interleaving, data whitening and CRC checking all for free.
We assumed that, as the CC1120 was advertised as a ‘better’ replacement for our CC1111 radio, that it would also include all of these fine features. After we got the chip all soldered down to our first prototype boards, we read through the reference manual looking for the right register values to flip for forward error correction. We found support for CRC computation and data whitening, but no mention of interleaving or forward error correction at all.
Thanks, TI. Of course, without the FEC pieces, the other packet handling hardware is worthless—you can’t exactly do a CRC on the encoded data and expect it to be useful on the other end of the link, and data whitening happens after the CRC.
Basic CC1120 driver
I assumed I’d eventually figure out something to do about the FEC pieces and started writing a basic CC1120 driver AltOS, the operating system used in all of our projects. I started with the transmit side, as that seemed easier as I could use the existing packet hardware by uploading the desired bit sequence using whatever fancy encoding desired and the hardware would happily transmit it.
I first tested that using low data-rate bits (2kbps), transmitting an alternating sequence of zeros and ones to generate a 1kHz tone on a regular 70cm receiver. That seemed to work just fine, demonstrating that I had some grasp of the basic operation of the chip.
Convolutional Encoding in Software
Not to be daunted by a small challenge in software, I set out to replicate the encoding scheme used in the CC1111 chips for use in our CC1120-based design. We obviously want our CC1120 boards to interoperate with the CC1111 boards. Fortunately, TI fully documents the CRC, data whitening, convolutional encoding and interleaving done in the hardware.
I created my own implementation of the encoder (licensed, as usual, under the GPLv2) which you can see in the file ao_fec_tx.c It’s not quite as flexible as the hardware, it always whitens the data and always appends the CRC bytes to the end of the packet, along with the necessary trellis termination bytes.
The core of that code is surprisingly simple:
static const uint8_t ao_fec_encode_table[16] = {
/* next 0 1 state */
0, 3, /* 000 */
1, 2, /* 001 */
3, 0, /* 010 */
2, 1, /* 011 */
3, 0, /* 100 */
2, 1, /* 101 */
0, 3, /* 110 */
1, 2 /* 111 */
};
uint8_t
ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out)
{
uint8_t extra[AO_FEC_PREPARE_EXTRA];
uint8_t extra_len;
uint32_t encode, interleave;
uint8_t pair, byte, bit;
uint16_t fec = 0;
const uint8_t *whiten = ao_fec_whiten_table;
extra_len = ao_fec_prepare(in, len, extra);
for (pair = 0; pair < len + extra_len; pair += 2) {
encode = 0;
for (byte = 0; byte < 2; byte++) {
if (pair + byte == len)
in = extra;
fec |= *in++ ^ *whiten++;
for (bit = 0; bit < 8; bit++) {
encode = encode << 2 | ao_fec_encode_table[fec >> 7];
fec = (fec << 1) & 0x7ff;
}
}
interleave = 0;
for (bit = 0; bit < 4 * 4; bit++) {
uint8_t byte_shift = (bit & 0x3) << 3;
uint8_t bit_shift = (bit & 0xc) >> 1;
interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3);
}
*out++ = interleave >> 24;
*out++ = interleave >> 16;
*out++ = interleave >> 8;
*out++ = interleave >> 0;
}
return (len + extra_len) * 2;
}
ao_fec_encode_table takes care of the convolutional piece, ao_fec_whiten_table (not shown) contains the data whitening codes while the little loop at the bottom does the interleaving. I didn’t spend a lot of time optimizing this as it seemed to run plenty fast on the 32MHz processor.
With the bits all nicely encoded, I passed them to my simple CC1120 driver and let it send them along to our CC1111 receiver. Much to my delight, with only a few bugs fixed, it worked just fine! I’d managed to get one direction working, validating the hardware and making it clear that we’d at least be able to use the board in flight for telemetry.
Getting Soft-decision data out of the CC1120
In packet mode, the CC1120 receiver converts the incoming GFSK stream directly into bits, making its best guess as to whether the detected value was a one or zero. Of course, like any FM modulation, the receiver will be producing intermediate values, especially when the signal is weak or masked by interference. A Viterbi decoder can make good use of this information;these noisy intermediate values are less influential in the final resulting path cost which allows the strong 0/1 values to pull the solution to the right one. Soft decision decoding yields a theoretical 2dB gain over hard decision decoders, and given our desire for maximum packet reception over long distances, it seemed important to make this work.
The CC1120 has a way to recover the soft decision values, but only one 8-bit value at a time. It does, however, helpfully provide a GPIO wire which can be programmed to interrupt the CPU when the soft decision data has arrived.
So, I hooked up a GPIO line on the processor to the GPIO line on the CC1120 and let it interrupt once per bit time, or 38400 times per second, to read this valuable soft decision data out of the radio part. According to TI support, this is the only way to make this work, and that they generally recommend that developers use the packet mode stuff and throw away this valueable source of data.
I was happily surprised to learn that the STM32L can in fact survive this interrupt rate, and by setting interrupt priorities appropriately, I manage to reliably capture an entire packets worth of data without dropping a single bit.
I set up a simple packet dumping function to run on the prototype board and captured raw encoded bytes from our CC1111-based flight computer so that I’d have some “real” data to work from.
Soft-decision Viterbi Decoding
The sample encoding implementation from TI made that piece fairly straightforward. Lacking a similar sample for the decoding piece meant that I’d be starting from scratch. And, implementing something that seemed like magic to me when I started. I started by reading a few articles on Viterbi decoding:
I found Chip Fleming’s tutorial very useful as it included a bunch of worked examples using a convolutional encoders with constraint length (k) of 3 instead of 4; this makes all of the trellis diagrams half the size.
I also sent my friend, Phil Karn, a query about this process, and he responded with a bunch of helpful suggestions, while also recommending that I just steal his DSP and FEC library implementation. Of course, I don’t like using code that I can’t understand, and his code only implements much longer codes than I needed, so I’d have to understand it anyways to make it work for me. Phil’s code is a marvel, but it’s not exactly comprehensible to someone who doesn’t even know what a Viterbi decoder is supposed to do.
So, with Chip’s tutorial on my screen, I wrote a primitive Viterbi decoder. This did only the Viterbi step, and split that into two phases. The first computed the cost for each state in the system for every received pair of symbols received. It also tracked the chain of states through the entire decode process:
for (state = 0; state < 8; state++) {
struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]);
struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]);
uint8_t zero_state = ao_next_state(state, 0);
uint8_t one_state = ao_next_state(state, 1);
int zero_cost = ao_cost(s, zero);
int one_cost = ao_cost(s, one);
zero_cost += cost[b][state];
one_cost += cost[b][state];
if (zero_cost < cost[b+1][zero_state]) {
prev[b+1][zero_state] = state;
cost[b+1][zero_state] = zero_cost;
}
if (one_cost < cost[b+1][one_state]) {
prev[b+1][one_state] = state;
cost[b+1][one_state] = one_cost;
}
}
At the end of the packet, it found the least costly path and walked that from back to front, generating output bits (yes, one bit per element of the ‘bits’ array):
for (state = 1; state < 8; state++) {
if (cost[b][state] < c) {
c = cost[b][state];
min_state = state;
}
}
for (b = len/2; b > 0; b--) {
bits[b-1] = min_state & 1;
min_state = prev[b][min_state];
}
Completely separate from this code were the interleaving and data whitening stages. Keeping those separate allowed them to be tested independently, which made debugging them far easier.
None of this code ever ran on the STM32L processor, it was instead run in a test framework on my laptop. I first got this working with data generated by the software convolutional encoder, then I managed to get it to decode the raw packets that I had recorded directly from the receiver it self.
This marked a significant milestone in my mind—I’d managed to replace, in software, the CC1111 FEC encoder and decoder. However, the decoder performance was not fast enough to manage back-to-back packets yet. Having something in hand that worked meant that further development would be directly comparable to something that did work, making optimization much easier. Yet another lesson in making it work, and then making it work fast.
Optimizing the Viterbi Decoder
The first step was to reduce memory usage within the decoder. While it’s best to defer computing the path until the very last bit has been received, it’s also true that the chances of a bit affecting old data reduces as the distance between the new and old data increases. With the rule of thumb being a distance of k × 6 or k × 7, I saved 32 output bits for each state and wrote the oldest of 8 each time the buffer filled up, making a distance of 24 bits between the newest saved data and the current decoding position. That meant a fixed amount of storage was needed for an arbitrarily long packet.
I tested a variety of different history sizes from 8 to 56 bits (cooresponding to 16, 32 and 64 bits of saved data for each state). With 100000 random packets generated that had gaussian noise added to each bit, here are the error rates for the different history lengths:
| History Length | Total Packets | Correct | Incorrect |
|---|---|---|---|
| 8 bits | 100000 | 90520 (90.52%) | 9480 (9.48%) |
| 24 bits | 100000 | 93614 (93.61%) | 6386 (6.39%) |
| 56 bits | 100000 | 93620 (93.62%) | 6380 (6.38%) |
The performance of the 8-bit history and 16-bit history versions turned out to be essentially identical (given the 32-bit nature of the STM32L, that shouldn’t be too surprising). The performance of the 56-bit version, which manipulated uint64_t data types was sigificantly slower, and given the very modest benefit, deemed not worth it. If we move to a larger constraint length (k > 4), or started using a punctured convolutional encoding, we would want to re-measure this.
The next step was to combine the de-interleaving, decoding, de-whitening and CRC computation into a single loop. This would eliminate a pile of data copying and extra memory usage. Nothing fancy here, but it made enough of a difference that I could decode most of the incoming packets now, dropping only about 25% of them.
To get to being able to decode every packet, I needed to start decoding the packet while it was being received. Because of interleaving, I had to have 32 bits of data to be able to decode anything, so it was a simple matter of having my per-soft-value interrupt handler start the decoder going after each interleave block of data was received. With this in place, I was able to decode a 76-byte payload (160 transmitted bits) in 14.7 ms, or just about 50% of the time it took to transmit the packet. Unrolling one of the inner decoding loops eliminated a bunch of computation and sped this up even more, decoding packets in 9.5ms.
Success at last, a solid 100% of packets received were being decoded, as long as the CPU was otherwise idle.
Finally, I went and re-read Phil Karn’s code and pondered over how it works. It was opaque until I wrote a message back to Phil asking how it worked and pointing out sections that were confusing. Fortunately, simply phrasing my confusion in words made me understand how the code works. Here’s my original code for computing the per-state cost metric:
/* Metric for a zero bit */
uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) +
(uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1]));
{
/* Total path metric and state for a zero bit */
uint32_t cost0 = cost[p][state] + bitcost;
uint8_t state0 = ao_next_state(state, 0);
/* Compare the total path metric against all existing
* metrics heading into the same new state, choosing
* the least expensive and killing the others. Record
* the new lowest cost and output bit.
*/
if (cost0 < cost[n][state0]) {
cost[n][state0] = cost0;
bits[n][state0] = (bits[p][state] << 1) | (state & 1);
}
}
{
/* Total path metric and state for a one bit. Because
* encoding a one is always exactly the opposite of
* encoding a zero from any state, this cost is
* 255*2 - bitcost
*/
uint32_t cost1 = cost[p][state] + 510 - bitcost;
uint8_t state1 = ao_next_state(state, 1);
if (cost1 < cost[n][state1]) {
cost[n][state1] = cost1;
bits[n][state1] = (bits[p][state] << 1) | (state & 1);
}
}
Before this loop is run, I have to initialize cost[n] to a large value so that the comparisons will be true for the first case to reach each state. Phil’s code, in contrast, doesn’t have to initialize cost[n] as we know which two states can reach any possible new state. His code looks like this:
/* Metric for a zero bit */
bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) +
(uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)|1]));
/* Only state and state+4 reach state<<1 with a zero bit */
/* Cost from state to state<<1 for a zero bit*/
m0 = cost[p][state] + bitcost;
/* Cost from state+4 to state<<1 for a zero bit */
m1 = cost[p][state+4] + (510 - bitcost);
/* Which source state is cheaper? */
bit = m0 > m1;
/* Record the cheaper cost and the add to the path of bits */
cost[n][state<<1] = bit ? m1 : m0;
bits[n][state<<1] = (bits[p][state + (bit<<2)] << 1) | (state&1);
/* State and state+4 reach (state<<1)+1 with a one bit */
/* Cost from state to (state<<1)+1 for a one bit */
m0 -= (bitcost+bitcost-510);
/* Cost from state+4 to (state<<1)+1 for a one bit */
m1 += (bitcost+bitcost-510);
/* Which source state is cheaper? */
bit = m0 > m1;
/* Record cheaper cost and add to the path of bits */
cost[n][(state<<1)+1] = bit ? m1 : m0;
bits[n][(state<<1)+1] = (bits[p][state + (bit<<2)] << 1) | (state&1);
This code does two states at a time, and so while it’s slightly longer than the above, it only needs to run half as many times. The resulting code now decodes packets in 5.7ms.
The final version of the code can be see in ao_fec_rx.c
The whole AltOS operating system, with many drivers and support for CC1111, AVR and STM32L processirs is available, under the GPLv2 from git://git.gag.com/scm/git/fw/altos
AltOS 1.0 — TeleMini support and a host of new features
Bdale and I are pleased to announce the release of AltOS version 1.0.
AltOS is the core of the software for all of the Altus Metrum products. It consists of cc1111-based microcontroller firmware and Java-based ground station software.
AltOS Firmware — TeleMini support, Kalman Filtering and more
Support for the new TeleMini altimeter is included in version 1.0 along with a wealth of other new features:
Change telemetry to be encoded in multiple 32-byte packets. This enables support for TeleMini and other devices without requiring further updates to the TeleDongle firmware.
Previous versions of the firmware used a large monolithic telemetry packet 95 bytes long. The old single-packet format included all of the rapidly updating data coming from the on-board sensors, along with slowly changing GPS data and never-changing configuration data. Not only were the packets large (reducing the reliability of reception), they were also device-specific, encoding precisely the set of information available in TeleMetrum.
The new telemetry system uses mulitple different formatted telemetry packets, all 32 bytes in length, transmitting rapidly changing data often and other data more slowly. This should improve reception, but more importantly, allows for different devices to send different sets of data.
Within the TeleDongle, this change was implemented by removing all of the telemetry decoding logic from the embedded device and moving it to the AltosUI java code running on the host. This means that the TeleDongle can now receive arbitrary telemetry packets without having new firmware installed.
Support operation of TeleMetrum with the antenna pointing aft. Previous firmware versions required the antenna to be pointing upwards, now there is a configuration option allowing the antenna to point aft, to aid installation in some airframes.
A TeleMetrum user, DK Duncan, changed the firmware on his board to flip the accelerometer ADC values around. This produced something that worked on the ground, so he went and flew it. And it just worked.
I added this as a configuration option, including all of the Java code to change it. Nice that any Altus Metrum user can try things like this out and then have them get added in the next version of the software.
Ability to disable telemetry. For airframes where an antenna just isn’t possible, or where radio transmissions might cause trouble with other electronics, there’s a configuration option to disable all telemetry. Note that the board will still enable the radio link in idle mode.
Terry Lee is taking a TeleMetrum board for a ride during LDRS this year, but with TeleMetrum mixed in with a pile of other electronics, he didn’t want us transmitting during flight and causing potential RFI issues with other boards in the air frame. Instead of building a custom version of the firmware, we just made this a configurable mode.
Arbitrary frequency selection. The radios in Altus Metrum devices can be programmed to a wide range of frequencies, so instead of limiting devices to 10 pre-selected ‘channels’, the new firmware allows the user to choose any frequency in the 70cm band. Note that the RF matching circuit on the boards is tuned for around 435MHz, so frequencies far from that may reduce the available range.
Kalman-filter based flight-tracking. The model-based sensor fusion approach of a Kalman filter means that AltOS now computes apogee much more accurately than before, generally within a fraction of a second. In addition, this approach allows the baro-only TeleMini device to correctly identify Mach transitions, avoiding the error-prone selection of a Mach delay.
Developing this feature made extensive use of the simulator which runs the flight management code using sensor data captured on previous flights. Somehow, we’ve managed to collect log data from over 100 flights; replaying them on the ground means that even before the first flight with the new firmware, we were confident that it would work.
AltosUI — New Features
AltosUI has also seen quite a bit of work for the 1.0.1 release. Of course, many of the changes in AltosUI are to accomodate the new TeleMini altimeter and changes in the AltOS firmware for TeleMetrum. In addition, we’ve also added lots of new features in response to user requests.
Add main/apogee voltage graphs to the data plot. This provides a visual indication if the igniters failed before being fired.
Scan for altimeter devices by watching the defined telemetry frequencies. This avoids the problem of remembering what frequency a device was configured to use, which is especially important with TeleMini which does not include a USB connection.
Monitor altimeter state in “Idle” mode. This provides much of the information presented in the “Pad” dialog from the Monitor Flight command, monitoring the igniters, battery and GPS status withing requiring the flight computer to be armed and ready for flight.
Pre-load map images from home. For those launch sites which don’t provide free Wi-Fi, this allows you to download the necessary satellite images given the location of the launch site. A list of known launch sites is maintained at altusmetrum.org which AltosUI downloads to populate a menu; if you’ve got a launch site not on that list, please send the name of it, latitude and longitude along with a link to the web site of the controlling club to the altusmetrum mailing list.
Flight statistics are now displayed in the Graph data window. These include max height/speed/accel, average descent rates and a few other bits of information. The Graph Data window can now be reached from the ‘Landed’ tab in the Monitor Flight window so you can immediately see the results of a flight.
TeleMini Dual-deploy altimeter with telemetry now available
TeleMini is a miniature dual-deploy flight computer with data logging and radio telemetry. Small enough to fit comfortably in an 18mm tube, this powerful package does everything you need on a single board:
5kB on-board data logging memory.
70cm ham-band digital transceiver for in-flight telemetry and on-the-ground configuration.
Transmitted telemetry includes altitude, speed, acceleration, flight state, igniter continutity, temperature and battery voltage. Monitor the state of the rocket before, during and after flight.
Radio direction finding beacon transmitted during and after flight. This beacon can be received with a regular 70cm Amateur radio receiver.
Barometer accurate to 45k’ MSL. Reliable apogee detection, independent of flight path. Barometric data recorded on-board during flight.
Dual-deploy with adjustable apogee delay and main altitude. Fires standard e-matches and Q2G2 igniters.
0.5” x 1.5”. Fits easily in an 18mm tube.
Uses rechargeable Lithium Polymer battery technology. All-day power in a small and light-weight package.
Learn more at http://www.altusmetrum.org/TeleMini/
I don’t have anything in these images to show just how tiny this board is—but the spacing between the screw terminals is 2.54mm (0.1in), and the whole board is only 13mm wide (1/2in).
We’ve been flying these for quite a while; testing the hardware and tuning the firmware. My new 29mm mmt airframe, Koala, sports a TeleMini board for apogee-only deployment. It’s been really nice to have something flying on G’s and H’s that doesn’t depend on the vagaries of delay grains.
AltOS 0.9.2 — Minor update to ground station software
Bdale and I are pleased to announce the release of AltOS version 0.9.2.
AltOS is the core of the software for all of the Altus Metrum products. It consists of cc1111-based microcontroller firmware and Java-based ground station software.
AltosUI — Just a few bug fixes
AltOS version 0.9.2 is a minor release with just a couple of fixes:
Mac OS X graphing repaired. The 0.9 release was missing a file required to support the graphing feature (jcommon.jar). This has been added.
Fixed multiple flight log downloading. Attempts to download more than one recorded flight log would fail in weird ways. The failures have been addressed and additional diagnostics are presented when things go wrong.
You can see the AltOS version number in the ‘Configure AltosUI’ dialog box now. This should make it easier to tell what you’ve got installed.
Post-flight graphing tool. This lets you explore the behaviour of your rocket after flight with a scroll-able and zoom-able chart showing the altitude, speed and acceleration of the airframe along with events recorded by the flight computer. You can export graphs to PNG files, or print them directly.
No Firmware Update
AltOS version 0.9.2 does not include any firmware changes. We’re still busy testing the Kalman filter code; that’ll be in the next major release.
AltOS 0.8 — New Software and Firmware for Altus Metrum Devices
Bdale and I are pleased to announce the release of AltOS version 0.8.
AltOS is the core of the software for all of the Altus Metrum products. It consists of cc1111-based microcontroller firmware and Java-based ground station software.
AltosUI — New Features in the AltusMetrum Ground Station
AltOS version 0.8 contains significant upgrades to the ground station software, AltosUI:
- Post-flight graphing tool. This lets you explore the behaviour of your rocket after flight with a scroll-able and zoom-able chart showing the altitude, speed and acceleration of the airframe along with events recorded by the flight computer. You can export graphs to PNG files, or print them directly.
- Real-time moving map which overlays the in-progress flight on satellite imagery fetched from Google Maps. This lets you see in pictures where your rocket has landed, allowing you to plan recovery activities more accurately.
Wireless recovery system testing. Prep your rocket for flight and test fire the deployment charges to make sure things work as expected. All without threading wires through holes in your airframe.
Optimized flight status displays. Each flight state now has it’s own custom ‘tab’ in the flight monitoring window so you can focus on the most important details. Pre-flight, the system shows a set of red/green status indicators for battery voltage, apogee/main igniter continutity and GPS reception. Wait until they’re all green and your rocket is ready for flight. There are also tabs for ascent, descent and landing along with the original tabular view of the data.
Monitor multiple flights simultaneously. If you have more than one TeleDongle, you can monitor a flight with each one on the same computer.
Automatic flight monitoring at startup. Plug TeleDongle into the machine before starting AltosUI and it will automatically connect to it and prepare to monitor a flight.
Exports Google Earth flight tracks. Using the Keyhole Markup Language (.kml) file format, this provides a 3D view of your rocket flight through the Google Earth program.
Continuing Features
AltOS version 0.8 continues to provide the following features:
Receive and log telemetry from a connected TeleDongle device. All data received is saved to log files named with the current date and the connected rocket serial and flight numbers. There is no mode in which telemetry data will not be saved.
Download logged data from TeleMetrum devices, either through a direct USB connection or over the air through a TeleDongle device.
Configure a TeleMetrum device, setting the radio channel, callsign, apogee delay and main deploy height. This can be done through either a USB connection or over a radio link via a TeleDongle device.
Replay a flight in real-time. This takes a saved telemetry log or eeprom download and replays it through the user interface so you can relive your favorite rocket flights.
Reprogram Altus Metrum devices. Using an Altus Metrum device connected via USB, another Altus Metrum device can be reprogrammed using the supplied programming cable between the two devices.
Export Flight data to a comma-separated-values file. This takes either telemetry or on-board flight data and generates data suitable for use in external applications. All data is exported using standard units so that no device-specific knowledge is needed to handle the data.
Speak to you during the flight. Instead of spending the flight hunched over your laptop looking at the screen, enjoy the view while the computer tells you what’s going on up there. During ascent, you hear the current flight state and altitude information. During descent, you get azimuth, elevation and range information to try and help you find your rocket in the air. Once on the ground, the direction and distance are reported.
AltOS Firmware Update
AltOS version 0.8 contains a minor firmware update for TeleMetrum to resolve an issue with main deployment. A mis-feature in the igniter firing code would delay main deployment by 2 seconds in some cases.
Thanks to our contributors!
We had a lot of help with this release:
Anthony Towns wrote both the new data graphing interface and the moving map display.
Bob Finch helped clean up our documentation, and provided flight testing for the firmware updates.
Future Plans
A number of features are implemented or in process in the sources available in our publicly visible repository that are not part of the current stable release.
A Kalman-filter based approach to apogee detection using more than just the baro sensor, so that we can safely control apogee ejection on flights to altitudes beyond the range of our baro sensor alone. Unlike the other items on the list, this will be a significant change to the in-rocket TeleMetrum firmware. It may therefore be a while before this becomes part of a stable firmware release.
Motor characterization. Because TeleMetrum contains a high-resolution, high-frequency accelerometer, it is possible to take the data from that and compute an accurate thrust curve for the motor.
Comprehensive PDF and/or HTML -based flight report. Construct a complete report of the flight suitable for publication on the web that includes graphs of the flight and details about motor performance etc.
Publish flight data to the Altus Metrum web site. This will allow you to share your flight data with others, and let you download flights published by others.
There are any number of additions that could be made to this list; feel free to send along ideas that you’ve got. Of course, all of this software is licensed under the GNU General Public License, so you can get the source and hack on it in the comfort of your own home.
The PSAS team planned to have their LV2.3 airframe updates ready for BALLS this year, but RL interfered and they weren’t ready to go on time. A quick bit of rescheduling and we decided to fly over the weekend of the 16-17 of October.
Tsolo and family welcomed us warmly as we arrived on Saturday afternoon after driving over from Portland. They’ve got a new puppy who is also cute and friendly.
We managed to get the launch tower and flight operations set up before dark, cooked dinner and spent the evening prepping the airframe. It was cold overnight, but the light cloud cover that had been there when we arrived was nearly gone by morning. I called in to open the waiver and was asked to hold until noon, which suited us just fine.
The rocket finally made it onto the rail around 1:30 and we managed to convince the launch controller to actually light the motor at 2:44:39 (according to the GPS data). Flying on a CTI N2850 blue-streak, LV2.3 hit about 380m/s and reached 4851m.
This was the first flight with the new fin system, you can see how that works in the video here:
Portland State Aerospace LV2.3 flight with roll control from Keith Packard on Vimeo.
The roll control system worked as designed, executing a programmed sequence of maneuvers during ascent. You can see the canard fins moving back and forth in the video, controlling the roll of the airframe.
Yes, the fins really do spin separately from the airframe. You can see how that was constructed here:
Live telemetry and stored flight data, consisting of GPS coordinates along with barometry altimeter and accelerometer information, was collected using the TeleMetrum flight computer. The airframe was recovered about 800m downrange.
Thanks to Portland State University for their support in hosting PSAS and Oregon Rocketry for letting us fly at their launch site.















