Category Archives: Arduino

Arduino and the evil print statement

freakduino_chibi-thumb-505x579-58708I finally got around to reading Akiba’s excellent blog article entitled Intermittent Bugs and How to Strike Fear In the Heart of Experienced Devs, and this statement jumped out at me:

It just so happens that print statements in the Arduino library use an interrupt service routine and since the AVR doesn’t allow nested interrupts, any interrupt must wait until the current interrupt is finished before being serviced.

In short, one should never issue a print statement from within an interrupt service routine on the Arduino platform.  This implementation was the root cause of a rather nasty hanging bug in Akiba’s ChibiArduino product, and it was a tricky one to track down.

I’ve been working with Arduino for a few years now, and time and time again I’ve run into odd problems which were ultimately traced down to serial.print().  Timing glitches, random lockups, and other bizarre behaviors were all ultimately caused by relying on print statements to provide status during development.  Serial buffer overflows are a huge issue – it’s really easy to cram more data into the UART than the receiving end is able to handle, especially at low baud rates.  The default 9600 baud setting certainly exacerbates this issue; bumping this up to 115200 often avoids the lockup-causing buffer overflow but can introduce other odd timing issues.

As Akiba alludes to in the aforementioned article, it is often safer to toggle or pulse a debug pin to externally monitor events.  This technique is very helpful for measuring time consumption for a block of code – toggle the pin high at the beginning of the block of code to measure (preferably by directly manipulating port register bits – Arduino’s digitalOut() is horrifically inefficient) and toggle it low at the end of the block.  Monitor this pin on your oscilloscope to measure the time.

A couple of pearls of wisdom to pass along:

  • Keep ISR implementations as short as possible.
  • Do not perform expensive operations (eg, logging, printing, etc) within an ISR.
  • If you find your Arduino code hanging randomly, print statements may be to blame.
  • If you do use Arduino Serial.print(), set the baud rate as high as possible.

Recently I’ve found myself working less and less with the Arduino environment and moving more towards direct AVR development.  Arduino is a double-edged sword – lots of libraries and community support, but the indirection and abstractions offered by the platform often come at a high price.

 

Driving Cheap EBay OLED Displays With Arduino

Kozig OLED DisplayOver the last couple of years I’ve picked up a few little 128×64 OLED displays, mostly through EBay auction sniping.  These displays are similar to those offered by Adafruit, likely using the same chip-on-glass (COG) OLED display with a SSD1306 controller.  The Adafruit version gives you direct access to the controller, so the SSD1306 datasheet is all you need to write a driver.  In fact, Adafruit has released a perfectly adequate driver for their offering; it’s available from the link shown above.  For some reason, however, the designer of the displays that I purchased decided to put their own microcontroller between the exposed I2C bus and the SSD1306.  The only feature that I’m aware of which utilizes this intermediate microcontroller is an 8×16 font; devices using these displays would require a bit less memory, as the font is stored on the display itself.  Other than this rather dubious advantage, the controller is more hindrance than help.  Adding insult to injury, the command set for the display is completely undocumented; the only information I was able to find was a rather spartan Arduino sample application.  Contacting the EBay sellers failed to bear fruit.  They are completely clueless regarding how to drive the display.

I’ve got three different variants of this display, all labeled as “Kozig”; a couple of them refer to kozig.com, a site which resolves to a single login page. Not much help there. The three variants of this display that I have on hand are:

Kozig 128×64 I2C OLED Displays (EBay Special) 
Model I2C Pins Status
ZT.SCOI2CM2 (monochrome, white) 0x51 2×4 Working
ZT.SCOI2CM1 (bi-color: yellow, blue) 0x51 1×10 Working
ZT.SC-I2CMx (monochrome, white) 0x27 2×4 Pending

The displays with part numbers ZT.SCOI2CM2 and ZT.SCOI2CMx are mounted on a PCB with black solder mask and have a nice metal frame surrounding the display; this is what attracted my attention in the first place, as they should be slightly more rugged than the exposed glass displays (at least in theory.)  I’ve contacted several EBay sellers about their offerings, and they seem to all be selling the Kozig ZT.SC-I2CMx displays now; I was unable to find anyone offering the ZT.SCOI2CM1.  Note that the sample code that I was able to track down DOES NOT WORK with this newer display; in fact, as of today I’ve been unable to find a working block of code for this device. Edit: 03/26/2013: Received an email message from Alexander Steingass, who was kind enough to send along technical details for the ZT.SC-I2CMx displays along with a driver from Kozig.  Here’s the driver file for the sake of posterity:  ZT.SC-I2CMx

If you’re in the market for a nice, bright little 128×64 OLED display, I’d recommend purchasing directly from Adafruit; they actually support what they sell, and the price is only a couple of dollars more than the EBay offerings.  If, however, you’ve purchased one of these displays and are looking to use it with an Arduino project, read on.

I’ve written a little Arduino driver for these displays which should ease the pain of incorporating them into your designs.  This driver utilizes my AnyDisplay core and provides some nice features – optimized buffered drawing, different pen and fill modes (none, normal, clear, XOR), filled shapes, user-defined fonts and bitmaps as well as polar lines and points which don’t require floating point support.  Since the driver uses an in-memory buffer it does require a chunk of your Arduino’s precious RAM (128×64 bits, or 1024 bytes).  Optimized drawing requires another 128 bytes if you choose to enable it; it’s a case of display speed vs memory, and you’ll need to make that determination yourself.  The ATMega328 only has 2K of RAM, so display buffering takes about half of it.  I’m also working on a version which uses an external SRAM or FRAM as the display buffer that I can make available if there’s any interest.

The driver will be available on my GitHub page soon.  Comments are encouraged!  Do you have one of these displays?  Let me know by posting a comment!

AnyDisplay Supported Displays

Here’s my initial list of displays which will be supported by AnyDisplay. Currently working on a breakout board for the Sharp MLCD devices which should make these easier to work with.

Display Type Price Size Resolution Colors Controller
Sharp LS013B4DN02 PNLC $20.43 28×32 96×96 Mono
Sharp LS027B7DH01 HR-TFT $45.25 62×42 400×240 Mono
Liquidware Touchshield Slide OLED     320×240 RGB666
EA DOGM128W-6 FSTN $18.00 55×46 128×64 Mono ST7565R
EA DOGXL160W-7 FSTN $35.98 78×61 160×104 Mono UC1610
Newhaven 
NHD-C160100DiZ-FSW-FB
FSTN $18.55 49×48 160×100 4 bit gray ST7528i
ScreenKey TFT128 TFT n/a 35×30 128×128 RGB565  
Nokia 6100 TFT $4.95 27×27 128×128 RGB565 PCF8833
Osram Pictiva OLED n/a 92×19 288×48 8 bit gray

AnyDisplay: Unified library for graphical displays

OK, I admit it.  I have a weakness for displays.  Most of the projects that I’ve got in the hopper include some sort of graphical display.  While the ubiquitous LCD character display may be inexpensive, I find them to be terribly limiting and, frankly, kind of boring.

Since delving into microcontroller development I’ve managed to get my hands on a pretty decent collection of graphical displays.  I’m currently rather obsessed with the new(ish) MemoryLCD displays from Sharp; look for a subsequent post detailing how to work with these.

One of my frustrations with the current state of graphical displays in the microcontroller realm is the lack of consistency and uniformity in terms of libraries.  Switching displays is a painful proposition; if you are lucky you may find an existing library for the display as a starting point.  The library may or may not be functional, will undoubtably be incomplete, and will most likely have a completely different API than what you are used to.    The GLCD project makes an attempt at supporting several displays, but I’m not fond of the API and adding support for new displays is rather difficult.  Some vendors such as Adafruit do take the time to build simple display libraries for the displays that they sell, but they tend to lack uniformity between displays.

I’ve spent a good deal of time researching and prototyping solutions and have designed a new unified library for graphical displays.  Called AnyDisplay, this library will provide a single, consistent API for integrating graphical displays with Microcontroller projects.  The library consists of a well-fleshed out, well tested API for graphics primitives which is consistent across all displays.  Adding support for new devices requires developing a small driver for device-specific implementations.

Ultimately, this will allow you to easily add cool graphical displays to your projects.  Focus on the product that you are trying to build rather than spending so much time dealing with low-level details.  The consistent API will make experimenting with new displays a much simpler proposition.