Version 1.3 of of the Trackuino firmware is up in the downloads area! There are lots of improvements and fixes. Here is a summary:
Improved GPS compatibility
The previous GPS code made too many risky assumptions about the NMEA format, so it failed miserably on certain versions of the Venus 634FLPx (which, ironically, was the only supported GPS). Now the parsing routines are more tolerant to variations in the numeric formats, so compatibility with other units should be greater.
Signal quality (enter real-time computing)
In Packet Radio, the maximum bandwidth used by the AFSK carrier is 2,200 Hz. Nyquist tells us that we need at least 4,400 samples per second to properly rebuild the signal at the receiver, but that requires an ideal low-pass filter with a cutoff frequency of 2,200 Hz, which is neither physically achievable nor realistic in FM radios where the cutoff is usually higher, around 3,000 Hz. For those two reasons, oversampling is usually desirable (even if not mathematically necessary) if we want to avoid annoying harmonics that distort the signal and waste our scarce power.
The Trackuino firmware uses a 62,500 KHz sample rate, which is well away from the audible spectrum. Oversampling improves the quality of the signal at the receiver, but it requires pushing samples at a rate of 1 sample every 256 clock cycles (16 MHz clock rate / 256 = 62.5 KHz), so it's really taxing on the CPU. To make things worse, the Arduino is also busy doing a lot of equally important things, such as staying up to date with the GPS, keeping track of time so that millis() and delay() keep working as expected, and handling the buzzer (more on the buzzer later). All these tasks are interrupt-driven, which means they happen asynchronously without regard of one another or the normal program flow. The interrupts can be queued, but only one of each kind at a time. If an interrupt comes without having served the previous one, the second interrupt will be lost. So, not only has our modulator a meager 256 cycles to do its job, but it also has to struggle over the CPU with other interrupts... When some task needs to be done under a deadline constraint such as this, it's called a real-time system. Efforts to ensure real-time operation are geared towards three goals:
- Priorizing the real-time task over not-so-important tasks. In the AVR architecture, interrupt priorities are fixed, so we can't do that.
- Keeping our real-time task short, so that it can meet its deadline.
- Keeping non-important tasks short, so that they don't hog the CPU while the important task is waiting.
There are a number of improvements in version 1.3 on those regards:
- Serial (GPS) interrupt: The selfish implementation of this interrupt in the Arduino library spent an abusive 330 cycles on every received byte. It means that, for every received character from the GPS, chances are that one modem interrupt is lost altogether. Arduino version 22 has an optimization that cuts this time down to 80 cycles, so the code now enforces compilation under Arduino version 22 or later.
- Modem interrupt: Some optimizations have been done to shave off a few cycles here and there. The modem interrupt should take 150 cycles max, average is less than that.
- Debug information: By uncommenting a flag in config.h you can get useful information on overrun conditions.
Previous versions of had interrupt overrun issues, which translated into small variations from the nominal baud rate (1200 bps). Luckily receivers have some tolerance to baud rate deviations, so it's not that big a deal. In any case, the new version should improve the rate of successfully decoded packets.
SRAM usage optimization
The Atmega328P has 2 KB of SRAM, of which about 512 bytes were taken up by a huge sine table in modem.cpp. This table has been moved to the much more spacious program memory (32 KB). There are a few other candidates that scream to be moved to PROGMEM too, such as the APRS comment, callsigns and such, but these haven't been moved (yet).
This should help in acoustically locating the payload. The buzzer is handled by timer 1 using PWM. Piezoelectric buzzers demand very little current, so they can be driven directly with pins 9 or 10. The tone frequency can be configured in config.h as well as the duty cycle in seconds. It doesn't make sense to have a payload beeping at 100,000 ft. since there is no air to begin with, so the maximum operating altitude can also be programmed.
CPU usage LED indication
This might look just cosmetic or geeky, but it's actually quite useful. The idea is that the LED will glow increasingly brighter as the CPU gets busier. For example:
- If the AVR is idle, the light will be very dim. Tthe AVR is never really idle for long periods of time, since timers 0 (millis) and 1 (buzzer) are going off periodically.
- When receiving data on the serial port, the LED will turn slightly brighter because it takes extra CPU to process the incoming bytes. This is a way of checking for GPS activity at a glance.
- APRS transmission takes the most CPU, so the LED will be almost fully bright.