(This is another article I wrote a year or more ago but never got around to publishing until now)
I’ve been helping an ecologist make a “compass bearing data logger” using an Arduino Uno. Actually, I’ve been doing most of the implementation while Erik has defined the requirements based on his many years doing field work with other logging tools. (It is pure joy to have crisp requirements so you know your solution happens to match the problem at hand!) Erik picked the Uno and it seemed like an excellent choice because it was very easy for him to combine bits and pieces from Adafruit to create a solution. We quickly became aware of off the shelf software libraries that either come with the Arduino IDE or that are available as add-ons from the main Arduino repositories to support the hardware. At the start of the project it seemed unimaginable to exhaust the Uno’s memory capacity with such a simple application. Does that sound familiar?
After getting about 98% of the functionality in place the IDE still reported only about 24 kilobytes of text usage along side the Uno’s 32 kilobyte capacity figure. But after the addition of the last hundred or so lines of C++ the system became unstable. It wasn’t unstable in the usual sense that the new code didn’t work right the first time. (My batting average up to that point had been excellent, but there had been a number of surprises.) The system was unstable in the sense that only the first sliver of initialization code was executing, but it was executing over and over forever. The CPU was reseting after just a little bit of the application code had executed.
When I was much younger I might have thrashed with this a long time, struggling to determine what broken code fragment I’d added somehow explained the failure. Instead I got out the machete and gutted the bodies of several functions until the overall code size was similar to what it had been the last time the system had run properly. Sure enough, it ran properly again. Replacing stub code with full function bodies in various combinations proved that it was simply the amount of code involved that caused the instability. I should point out that this program has very little “variable” storage in relation to the Uno’s 2kb of RAM. That is, it has maybe a dozen scalar variables, one small character array for building file pathnames, and a couple of objects to do with the clock/calendar and compass chips and the SPI interface to the SD card used for the actual data logging. Also, there are no recursive routines and very few local variables and very shallow call nesting, so stack demands are trivial too. In short, the bad magic was to do with undiagnosed overflow of “something” to do with the amount of text (machine instructions produced by the C++ compiler).
Except that C semantics require initialized string constants to be put into the data segment, and this has to be mutable, and therefore in RAM vs flash memory. Duh. So I was overflowing RAM, causing the stack to walk over the top of variable storage as it nested during routine calls.
The trouble in paradise is that in my world it’s just not acceptable that overflow of a statically allocated memory segment would go unnoticed by the tool chain. In my world this kind of misbehavior forces the Arduino IDE into the “piece of sh*t” bucket and I’m only persevering with this tool chain now for the sake of Erik’s target user group being able to make this logger with user-friendly tools. The Arduino IDE is fantastically user-friendly for making an Arduino blink LEDs. Going much beyond that in my experience has given appreciation for the “get what you paid for” adage.
But the other trouble is that it appears that some combination of Linux, the USB library “RXTX”, and the Arduino IDE are conspiring to ruin my system’s uptime record. If I had a nickle for every time a failure to do with the USB connection between the IDE and my Uno has forced a reboot I could buy another several TI MSP430 Launchpads. More on this here.