Sunday, June 3, 2018
Writing small and simple Arduino code
Although Arduino isn't my primary development platform, but I have still used it many times over the past few years. The intent of Arduino prioritized ease-of-use over efficiency, so when experienced software developers work with it, some degree of holding your nose may be necessary. Lately I've been making contributions to MicroCore, and therefore the Arduino IDE and libraries. My most recent impulse buy on Aliexpress is a 7-segment LED & pushbutton module using a TM1638 controller that sells for $1.50, so I decided to test it out using MicroCore.
I found a few existing Arduino libraries for the TM1638, all of which were rather large. The smallest one I found is TM1638lite, which still uses over half the 1KB flash in a tiny13 for anything more than a minimal use of the library. At first I considered improving the library, but soon decided the best course would be a full rewrite.
The first problem with the library is a common one since it follows the Arduino library example. That problem is creating an instance of a class when the use case is that only one instance of the class will be created. By only supporting a single attached LED&Key module, I can make the library both smaller and simpler. It also solves another problem common to classes that take pin numbers in their constructor. It is very easy to mix up the pin numbers. Take the following example:
TM1638lite tm(4, 7, 8);
Without looking at the library source or documentation, you might think data is pin 4, clock is pin 7 and strobe is pin 8. Named parameters would solve that problem, but the issue of unnecessarily large code size would remain. I decided to use a static class in a single header file, which minimizes code size and still maintains type safety. Writing "const byte TM1638NR::STROBE = 4;" makes it obvious that strobe is pin 4. With the default Arduino compiler optimization setting, no space is used to sore the STROBE, CLOCK, and DATA variables; they are compiled into the resulting code.
Another improvement I made was related to displaying characters on the 7-segment display. TM1638lite uses a 128-byte array to map the segments to light up for a given ASCII character. Since 7-segment displays can't display characters like "K" and "W", or distinguish "0" from "O", I limited the character set to hex digits 0-9 and "AbCdEF". The second improvement I made was to store the array in flash (PROGMEM).
I made some additional improvements by code refactoring, and I added the ability to set the display brightness with an optional parameter to the reset() method. With the final version of the library, the buttons example compiles on the tiny13 to only 270 bytes of code. You can find the library in my github repo: