Hardware Debugging the Arduino using Eclipse and the AVR Dragon

There is no music associated with this post.

I’ve written before about using an Atmel AVR Dragon to debug an Arduino board, using AVR Studio 4. I recently had some communication from Stephen Lake where he mentioned he was using Eclipse for Arduino development. I’d looked at Eclipse a long time ago and setting it up was an absolute terror with no real benefit. Stephen said it was much easier now, so I figured I’d have a look. Along the way I found the toolchain is robust enough these days to support DebugWIRE debugging of the Arduino and not have it suck too hard. I spent a lot of time trying to get the setup right, so I figured I’d detail it out if you’re trying to figure it out too, and save you the effort.

I’m standing on the shoulders of giants here. I’ve developed none of the software/plugins involved. I just put the pieces together from some disparate sources, some of which are a little out of date. The real credit goes to the authors of the software used in this. I did the setup on Windows and Linux, and the steps are 90% the same. I haven’t tried any of this out on OSX. This worked for me, maybe it will work for you. Maybe it won’t. I did this with Arduino IDE 1.0 installed.

Here’s what you’re going to need:

  • An Arduino that’s been modified for DebugWIRE operation
  • Eclipse
  • An AVR Dragon. Other debuggers might work, but a Dragon is what I have
  • WinAVR (Windows) or the AVR Toolchain (Linux)
  • libusb for Windows
  • Some patience. Okay, a lot of patience.

Get a DebugWIRE-capable Arduino

I wrote a whole big-ass article on this before, so you can reference that. For this experiment I used my modified Diecimila board. It will probably work with the UNO and other boards, I just haven’t tested them. Your mileage may vary.

Eclipse

More specifically, Eclipse IDE for C/C++ Developers (includes Incubating components). At the time of this writing Eclipse was 3.7.2. The nice thing about Eclipse is that it doesn’t have to be “installed” on your system, you can just unzip the folder and run it from that. That means you can keep many, many different versions of Eclipse configured for different tasks like I do around and not have to worry about trying something that will foul it up in some other aspect. I started out with the base CDT version and added into it. You’ll also need Java for this, of course, since Eclipse requires Java to run. Hey, I hear Eclipse can be used for Java development. groan.

On Ubuntu you can just apt-get it, but I chose to download and unzip it.

Atmel AVR Dragon

The dragon is (still) only $54 from Digikey in Canada. I’m sure you can get one just about everywhere. You can probably make all this work with the Atmel JTAG ICE III (I didn’t even know they had a III out), but those are expensive and so I don’t have one. You don’t have to do any mods to the Dragon other than maybe put some pin headers on it. I put a ZIF socket onto mine, but we won’t use it for this exercise.

AVR Dragon connected to Diecimila via ISP cable

WinAVR (ie – GCC Toolchain)

For Windows you want WinAVR. I used WinAVR 20100110 in this, and there’s nothing newer (and not likely to be anything newer). You might think that 2010 is old and you need something newer and cooler, but trust me working with the 20100110 is a lot easier than trying to build your own toolchain on Windows. When I started with this I had problems and I thought “a newer version might fix it”, and the problems just turned out to be me, and the building new stuff turned out to be a colossal pain.

You’ll also want some version of AVR Studio. In this I used 5.1 but I know it works with AVR Studio 4, since my previous article involved Studio 4. The thing to note is that v4.x and v5.x want different versions of the Dragon firmware, so if you want to go back and forth between 4.x and 5.x you’ll have to keep re-flashing the Dragon too. That’s a pain in the ass.

On Ubuntu you can just use the stock available AVR toolchain stuff,

apt-get install gcc-avr binutils-avr gdb-avr avr-libc avrdude avarice

As of this writing, the versions were gcc-avr (1:4.5.3-2), binutiles-avr (2.20.1-2), gdb-avr (7.2-1), avr-libc (1:1.7.1-2), avrdude (5.10-3), avarice (2.10-3ubuntu1). Like WinAVR, there are newer versions available but the stock ones worked (I did build avarice 2.12 to test, didn’t make any difference in what I saw). I also had the stock Ubuntu 11.10’s OpenJDK for Eclipse.

From here on out I’m going to stick to the Windows side of things, but really, if you use Ubunnnntu you’ll figure out how to set the right stuff in Eclipse, you’re smart like that.

libusb for Windows

Here’s where the pain in the ass really comes in. I spent the longest time trying to get this sequence of stuff right, and here’s what worked. This is the primary reason I wrote this article, because it was such an orderal figuring out the right way to make this all work correctly.

If you install one of your AVR Studio (v4 or v5), it will install the AVR Dragon USB driver. That’s great. The Dragon works fine in AVR Studio. Problem: nothing else will. The WinAVR stuff won’t talk through the Jungo driver to the Dragon. Instead, you’ll have to install libusb-win32 to provide an alternate usb access that the WinAVR stuff can work with.

Difficulty: when you install the libusb stuff, the Jungo driver is not active, and so AVR Studio doesn’t work with the Dragon. So if you’re like me and you keep popping back and forth between environments, you have to keep changing the driver. The good part is, it’s easy to do, it’s just busyness. There may be an alternate way to make this work, but I couldn’t find it.

So you need libusb-win32 for this. I used version 1.2.6. There is a version that comes inside the WinAVR directory itself, but I wasn’t successful getting it to work flawlessly. It probably does, but if so I wasn’t doing it right. I was able to do it right with the 1.2.6 version, so that’s what I’ll describe.

With AVR studio installed, and your dragon attached, you can check in the Windows device manager that you have a driver for “Jungo” in play, and the AVR Dragon is associated with it. Unzip the libusb-win32 stuff, and look inside for the “install-inf.exe” program. If you run that, this will make a very nice .INF style installer for your Dragon that uses the libusb driver.

Once you’re done you can push the “Install Now” button to actually install the driver.

From here on out, if you’re going to go back and forth between AVR Studio and the WinAVR-style toolchain you’ll have to learn how to switch between the Jungo driver and the libusb driver. It’s pretty easy. With your Dragon attached, bring up the device manager. Select whatever driver is currently installed, right-click and select “uninstall.” Don’t worry, this doesn’t remove anything, the driver sticks around on your computer. The driver will disappear from the device manager list. Unplug and re-plug in your Dragon via USB and you’ll see the Windows “found new hardware” message. Walk through the Install New Hardware wizard, but don’t let it automatically install anything. Choose “Install from a list or specific location”, and “Don’t search. I will choose the driver to install.” Then you’ll get to pick between the Jungo driver and the libusb driver.

Verify Dragon Operation with Jungo and libusb drivers

AVR Studio

Before you go any futher, you should verify that you can get your Dragon to work in AVR Studio and the WinAVR toolchain. Switch to the Jungo driver, start up AVR Studio, and start up the “AVR Programmer”.

You should be able to connect to your Dragon, and read the fuses on the chip. The nice thing about AVR Studio 5.1 is the programmer will tell you the correct chip if you’ve picked the wrong one. On my Diecimila it’s an ATMega168.

NOTE THE FUSE CONFIGURATION. Messing up the fuses is the easiest and fastest way to making your Arduino experience unhappy. We’re going to be changing some fuses during the course of debugging, so you’ll have to learn how to put all the fuses back correctly when you’re done. If you screw up the fuses, the on-board Arduino bootloader will not work correctly. Also note that the fuses are different for the different Arduino models. The ones I show are for my Diecimila. The ones on the UNO are set differently.

Also, you can use the AVR Studio programmer to burn the bootloader back to the Arduino in the event you mangle things up pretty good. This is useful since the Arduino IDE will let you burn the bootloader with a variety of devices but the Dragon is not one of them. Remember to choose the right bootloader for your chip for pity’s sake.

AVRDUDE and libusb

With your Dragon connected, and connect to your modified-Arduino via the ISP cable, switch over to the libusb driver as described earlier. Open up a command prompt (Start -> Run -> cmd). The main command-line program from WinAVR we’ll use will be AVRDUDE. WinAVR sets that PATH variable, so you can type avrdude commands from any directory.

Easy: Check to see that your dragon even responds. Use dragon_isp with avrdude:

avrdude -p atmega168 -c dragon_isp -Pusb 

You should get something like this:

avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.17s
avrdude: Device signature = 0x1e9406
avrdude: safemode: Fuses OK
avrdude done.  Thank you.

Sometimes you have to hit the command a couple of times before the Dragon will start talking. You’ll hear windows make that little “dunk” sound as the Dragon resets itself, and if you try to avrdude it too quickly it won’t respond correctly. With the libusb driver installed and set to be the current driver you can unplug/replug as much as you want and it’ll always use the libusb driver. It won’t go back to Jungo unless you uninstall the libusb one and switch back manually.

If you get something like this:

avrdude: Version 5.10, compiled on Jan 19 2010 at 10:45:23
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch
         System wide configuration file is "C:\WinAVR-20100110\bin\avrdude.conf"
         Using Port                    : usb
         Using Programmer              : dragon_isp
avrdude: usbdev_open(): did not find any USB device "usb"

That means you have usb issues. Check that the libusb driver is being used. Try replugging your Dragon and see if that helps.

For even more detail, use the -v flag on avrdude:

avrdude -p atmega168 -c dragon_isp -Pusb -v

You’ll get reams of data. Remember, this is for the Diecimila with the ATMega168. If you have an UNO or a Mega or something with the ATMega328 your results will be different.

avrdude: Version 5.10, compiled on Jan 19 2010 at 10:45:23
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2009 Joerg Wunsch
         System wide configuration file is "C:\WinAVR-20100110\bin\avrdude.conf"
         Using Port                    : usb
         Using Programmer              : dragon_isp
avrdude: usbdev_open(): Found AVRDRAGON, serno: 00A200011176
JTAG ICE mkII sign-on message:
Communications protocol version: 1
M_MCU:
  boot-loader FW version:        255
  firmware version:              7.21
  hardware version:              1
S_MCU:
  boot-loader FW version:        255
  firmware version:              7.21
  hardware version:              7
Serial number:                   00:a2:00:01:11:76
Device ID:                       AVRDRAGON
         AVR Part                      : ATMEGA168
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65     5     4    0 no        512    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     16384  128    128  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
         Programmer Type : DRAGON_ISP
         Description     : Atmel AVR Dragon in ISP mode
         Vtarget         : 5.0 V
         SCK period      : 8.00 us
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.16s
avrdude: Device signature = 0x1e9406
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as 0
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK
avrdude done.  Thank you.

Remember our little talk about fuses earlier? Take note of your fuse values (in my case, FF DF 00), as you’ll need them later to reset stuff. You can choose to have avrdude write them to a file, but it’s also good just to make a note somewhere.

If your Dragon talks to avrdude correctly with the libusb driver, you’re all set. Practice going back and forth between AVR Studio configuration and avrdude configuration for your Dragon.

You can also use avrdude to re-flash the arduino bootloader, in case you mess it up. Just change references to the dragon_isp and -Pusb for the configuration.

For example, for my Diecimila, and the Dragon programmer I use this, which also sets the fuses:

avrdude -p atmega168 -c dragon_isp -Pusb -v -U flash:w:ATmegaBOOT_168_diecimila.hex:i -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m -U efuse:w:0x00:m

For just the bootloader, and no fuses:

avrdude -p atmega168 -c dragon_isp -Pusb -v -U flash:w:ATmegaBOOT_168_diecimila.hex:i 

Where the ATmegaBOOT_168_diecimila.hex is from the arduino bootloader directory in the Arduino IDE tree (in Arduino-1.0’s case that’s arduino-1.0\hardware\arduino\bootloaders), pick the right bootloader for your chip. Remember your fuses are probably different. Which is why it’s good to use AVRDUDE or AVR Studio to find them out and write them down before you mess with anything. The ultimate reference is your arduino boards.txt (arduino-1.0\hardware\arduino\boards.txt). If you’re too lazy to look there, there is this reference as well, but I note that one of my fuses is slightly different in my Diecimila. Look up what all the fuse codes do if you’re concerned.

AVRDUDE will erase all the flash as a feature of doing this, so if you had an arduino program on the chip it will also be gone when you re-flash the bootloader. When the Arduino is “empty” it sits there flashing the LED (pin 13) on the arduino board on and off.

Ladyada also has a tutorial on using AVRDUDE, where they talk about more of the options.

Install Arduino Support for Eclipse

This is the reason that this whole post is even possible. It used to be a huge pain in the ass. No stop, don’t do anything that article says. Instead take the advice at the top of it and go get this plugin instead. The full installation instructions are there on that nice person’s site. Thanks very much for that.

In short: in Eclipse, choose “Install new software”, enter his plugin repository address, and add the latest version of the plugin (1.2.1 as of this writing).



Now at this point you’re all set to do Arduino development in eclipse. You can write code in Eclipse, and upload it in Eclipse (via avrdude). There are some differences between doing development in Eclipse vs. doing it in the Arduino IDE. If you’re new to Eclipse you’ll find it has a shit-tonne of features and things that make you scratch your head. Also, code you develop has to be modified slightly to conform to the Eclipse CDT standards. This is detailed in the baeyens.it instructions. In particular Eclipse will throw out tons of warnings you never knew about for code that works fine in the Arduino IDE, because the Arduino IDE is set to compile with the warnings off. Warnings on is helpful if you’re trying to figure out problems, but if you’re new to the whole coding scene it will probably be pretty daunting to wrap your head around them. Also, the Eclipse ide still requires prototypes for functions, which if you’re written functions in the Arduino IDE you’re probably asking “What are prototypes?” I wouldn’t call using Eclipse for Arduino development a beginner’s task. Learn to do stuff with the Arduino IDE first. Again, the reason I’m writing this is because we want to move on to doing hardware debugging with Eclipse.

Install GDB Hardware Debugging into Eclipse

Most of this is similar to this setup for doing debugging with basic AVR chips, and not specific to the Arduino. I’ll give some specific setup points for integrating this with the Arduino plugin.

Here’s some more magic install stuff. In Eclipse “Install New Software”, and you can select “Work With: all available” sites. You will see a staggering amount of extra stuff you can install into Eclipse, only a fraction of which I even know what it does. What you’re looking for is GDB Hardware Debugging, so you can enter “gdb” into the filter box, and it will narrow the list down.

I didn’t install SimulAVR (the simulator), because I didn’t care about that. I also didn’t set up AVARice as an Eclipse “external tool” because quite frankly figuring out this debugging setup was more difficult that way. I found it much easier just to rely on running the WinAVR tools from an open command-line window.

Most of the settings are project dependent, so you’ll have to set them every time you start debugging a new project in eclipse, so I’ll go through that using some demo code.

A Simple Project in Eclipse

First off, make a new Arduino sketch in Eclipse using the Arduino plugin instructions. (File -> New Project)

Note that this will make two projects in your Eclipse tree. One for your test project, and one which contains the core Arduino code in a separate project meant for your specific Arduino board. In my case, the Diecimila. I called my project “ArduinoDebugTest.”

In the ArduinoDebugTest.cpp file, let’s use this code:

// Do not remove the include below
#include "ArduinoDebugTest.h"
#define LEDPIN 13
//The setup function is called once at startup of the sketch
void setup()
{
// Add your initialization code here
    pinMode(LEDPIN,OUTPUT);
    Serial.begin(9600);
}
// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here
    digitalWrite(LEDPIN,HIGH);
    digitalWrite(LEDPIN,LOW);
    delay(1000);
    digitalWrite(LEDPIN,HIGH);
    Serial.println("I turned the LED on, off, and on again");
}

This code is pretty simple, because all we want is something simple we can use with the Dragon debugger to see that it works. It’ll flash the LED on the arduino board, then print something via the Serial porn on the Arduino.

Build this code with Eclipse (there are many ways to do this, including the little hammer icon on the toolbar, also right-clicking on the project). You’ll see in the console lots of messages go by as it builds the Arduino Core and then builds your program. If everything works out the final message will include the size of your code:

Device: atmega168
Program:    2568 bytes (15.7% Full)
(.text + .data + .bootloader)
Data:        232 bytes (22.7% Full)
(.data + .bss + .noinit)

That should look at least partially familiar, since the Arduino IDE also reports a size when it’s done compiling. Connect your Arduino board via USB to your computer and upload the code with Eclipse (the AVR upload button). Note that the Arduino Plugin very nicely sets up avrdude for you for the upload.

Here’s a fine point to remember: because you’ve modified this Arduino board to work with DebugWIRE, you’ve also lost the ability for avrdude (and the Arduino IDE, which uses avrdude) to auto-initiate the upload. So you have to be quick and push the reset button on the Arduino board when you start the upload. That will trigger the bootloader to look for a new upload for a couple of seconds, then it starts your on-chip arduino program. Timing is important. I find I can push the “AVR Upload” button, then immediately push the reset on the Diecimila and the upload works fine. You can see it works if the TX/RX led’s on the Arduino furiously light up for a few seconds. With the Arduino 1.0 IDE your timing has to be more precise because the IDE always does a build before the upload, so you have to wait until the build part is done – push the reset button – and then catch when the IDE’s upload starts. Also, in Eclipse you’ll see some status messages in the Console saying the upload is working and finishes.

After the upload finishes you should see the Arduino LED start to flash. Then start up the Arduino IDE’s serial monitor (or your favourite terminal program that you know how to get to talk to the Arduino’s usb-serial), and you should see this:

Congratulations, you’ve successfully gotten the code-edit-build-upload workflow working. Now the real fun starts. You can actually stop here and happily continue on your life using Eclipse for Arduino development and never have to bother yourself with hardware debugging.

Build your project with Debugging Info Available

With Eclipse, normally you have build configurations for “Release” and “Debug” versions. When you build for debug the compiler adds in extra symbols and shit which the debugger (GDB) uses to figure out just what the heck is going on in your compiled code, and trace that back to what the source code was.

I had issues making a “Debug” build configuration work with the Arduino plugin, and I think it’s because of the separate project for the Arduino Core that has to be compiled against. Headers would get confused and code wouldn’t build (“pins_arduino.h” kept getting involved, so something was wrong). So in the end I just elected to turn on debugging in the Release configuration and it works fine. The Arduino IDE normally does build things in debug mode (-g), and I think from the output the Arduino Eclipse Plugin is the same, so this may not make any difference – but I set some options to be sure.

In the properties for your project (not preferences for eclipse – these properties are stored for each project), go to the C/C++ Build Settings, and in the Release configuration (the only one which should be there) you want to turn on debugging information.

Normally it looks like this by default:

Change it to “Standard debugging info -g2” and “stabs (avr-gdb / insight)”. Do this for both “AVR Compiler” and “AVR C++ Compiler” to be sure.

(This may not make any difference, as the Arduino Plugin is already setting flags, but this makes me feel better).

After this you should rebuild your program, and upload it to the Arduino over the USB port.

If you have consistency problems with building, trying doing the “make clean” before rebuilding, as that will make it recompile everything. Computers are fast, you can wait the ten extra seconds.

Put Arduino chip into DebugWIRE mode

This is pretty easy, but very important. The Dragon can only debug in debugwire if debugwire is turned on in the AVR chip (duh). Problem is when debugwire is active SPI is not available, so you can’t leave debugwire on all the time. So get used to putting it in and out of debugwire mode.

To set debugwire mode, the easiest way in this workflow is to use avrdude to set the appropriate fuse. You can use the fuse calculator in eclipse, or one of a million online ones. You can also use AVR studio, but if you do this you’ll have to pop back to the Jungo USB driver, then back to the libusb driver to get anything more done.

In my case, the Diecimila’s regular hfuse setting is 0xDF (we saw that earlier with avrdude, remember?). To enable DebugWIRE the hfuse setting has to be changed to 0x9F. Use avrdude to change it:

avrdude -p atmega168 -c dragon_isp -Pusb -v -U hfuse:w:0x9F:m

Results are something like this:

Changing fuses:
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.16s
avrdude: Device signature = 0x1e9406
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as 0
avrdude: reading input file "0x9F"
avrdude: writing hfuse (1 bytes):
Writing | ################################################## | 100% 0.16s
avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0x9F:
avrdude: load data hfuse data from input file 0x9F:
avrdude: input file 0x9F contains 1 bytes
avrdude: reading on-chip hfuse data:
Reading | ################################################## | 100% 0.06s
avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as 9F
avrdude: safemode: efuse reads as 0
avrdude: safemode: Fuses OK
avrdude done.  Thank you.

To change it back, reset them to 0xDF:

avrdude -p atmega168 -c dragon_isp -Pusb -v -U hfuse:w:0xDF:m

You may have to do the operation twice, as avrdude might have trouble on the first pass and ask you to redo the command without powercycling. There is a “-c dragon_dw” mode you can use, but I find that avrdude is smart and notices the dragon is in Debugwire mode and switches as needed.

After you change the debugwire fuse state, you have to power-cycle your Arduino. You also might as well power-cycle the Dragon itself, since I have much more “first try worked” success if both get power-cycled.

Once you’ve enabled the debugwire fuse, the Arduino’s on-board bootloader will not work. SPI is disabled and so the bootloader doesn’t function correctly. So make sure you’ve got the correct code uploaded before you enable debugwire. Otherwise you’ll have to disable it, upload, then re-enable it.

Hardware GDB Debugging with the Dragon

If you found the stuff up until now not complicated enough, this probably will satisfy you. What we’ve done up until this point is essentially the same workflow as the Arduino IDE does. What we’re going to have to do now is change the build process slightly in order to accommodate GDB, which is the program behind all the debug session stuff we’re about to do. Then we’re going to find a really big pitfall, but more when we get to that.

Debugging is accomplished through GDB. Eclipse talks to GDB. GDB knows how to talk to AVARICE. AVARICE is the program that knows how to run DebugWIRE on the AVR Dragon. The Dragon is the board that talks via DebugWIRE over the ISP cable to control the execution of code on the Arduino board. Make sense? We have to get all these layers to talk to each other correctly or none of this shit works.

We’ll start on the Eclipse end. Start by making a new “Debug Configuration” in Eclipse (click the arrow next to the little picture of the bug, a couple of squares to the right of the hammer… sigh). A dialog starts up with a bunch of C/C++ options on the left side. Click and add a new configuration on the one called “GDB Hardware Debug”

Then we’re going to march through the tabs on this debug configuration.

First thing is in the “Main” tab to pick your .elf file, which is the compiled code used by the debugger which has all the symbols and shit in it. When I use this with the standard AVR development plugin it auto-inserts the proper .elf file for me, but with the Arduino plugin you have to navigate to your Arduino Eclipse workspace and select the .elf by hand. No big deal.

Set your GDB command to be the avr-gdb.exe in the WinAVR directory. You need to change the preferred launcher to the “Standard GDB Hardware Debugging Launcher” down at the bottom of the dialog window. I couldn’t make this work with the DSF launcher. You can tell you’ve got the right one because it has the option for “protocol version: mi” as shown. I change the port number to 4242, only because the original AVR Debugging article does that.

Then in the “Startup” tab have the setup as shown. Note this is different than the AVR debugging article setup. In particular rather than break on “main” we’re going to break on “setup” since in the Arduino version of the world the “main” is hidden. Turn off reset, halt, and load image (I couldn’t get it to work anyway). Turn on load symbols. I don’t make any changes in the next two tabs (source, common) so you can leave those as is.

Once you’ve got all the settings done, you can click “Apply” and close the dialog. Don’t bother trying to start “Debug” yet, because we need to get AVARICE running.

Running AVARICE is pretty easy. In a command window:

avarice --debugwire --dragon --ignore-intr :4242

If your Dragon is connected properly, you have libusb active as the driver, and your chip is in DebugWIRE mode. you’ll see this:

AVaRICE version 2.9, Jan  7 2010 22:42:57
JTAG config starting.
Found a device: AVRDRAGON
Serial number:  00:a2:00:01:11:76
Reported debugWire device ID: 0x9406
Configured for device ID: 0x9406 atmega168
JTAG config complete.
Preparing the target device for On Chip Debugging.
Waiting for connection on port 4242.

If you get an error, check that you’re using libusb. Also in most cases just cycling the power on both the Dragon and the Arduino puts it back to working. If you give avarice a -v flag for verbose it will constantly spit shit out for you to read and not be interested in as you debug.

Are we there yet? Start the Debug Session

Okay, with your eclipse debug configuration set, debug-enabled code uploaded to the arduino, debugwire enabled, and avarice up and running and waiting for a connection, it’s time to start up the debugger. Click the little bug and select your debug configuration. It will want to change “perspective” on eclipse to show the debug windows, go ahead. It’ll also rebuild your code, but don’t worry about that, since it should be the same version that’s on your arduino already (right?).

if you look at your command window, you should see AVARICE has hooked up with GDB:

Connection opened by host 127.0.0.1, port 4951.

and ta-dah, that’s really it. Because you set the breakpoint for “setup” the code initialized and stopped at the beginning of your setup() routine. Now you can use the single-step commands in the toolbar to march through your code. When you end your debugging session AVARICE will quit, so you need to restart that before you restart debugging. The chip will remain in debugwire mode so you’re all set.

So now, you’re debugging, is it what you expected? Arduino’s success as a platform comes from the fact that the hardware is cheap, the IDE is easy to use, and the Arduino Core is a shitload huge library of awesome functions that make coding for it easy. If you use the “step into” command you’re going to be buried under the mountain of code that goes together to make your own Arduino code run, which will get pretty tedious, and you normally don’t have to debug yourself anyway. Also, timing based things (delay(), sending serial stuff) is going to get seriously broken if you try single stepping through it. Your friend in these cases is the “step over” command in the toolbar, which essentially says “run this whole command, including any subroutines, and come back after you’re done since I don’t want to see any of that single-stepped”.

As the exercise, you can single-step (step into/step over) until you get into your loop() routine, and then you can use step-over each of the digitalWrite() commands, and you should see the light on the Arduino change accordingly. When you hit the delay() and the Serial.print() you’ll want to use step-over unless you’re not bored enough single stepping.

You can set breakpoints and use the “resume” toolbar icon to say “just run until this line gets hit, then I’ll start stepping”, which can be useful if you have a lot of code that runs before your routines you want to debug are executed.

You’ll find your code keeps jumping out to this previously-hidden main() routine, which is how C/C++ actually works, so you just have to step through that back into your loop() code each time.

Also debugwire disables SPI, so if you were hoping to use this to check SPI hardware, I’m afraid you’re out of luck. Back to Serial.print(), or using something like a logic analyser (I have the Salae one).

To get back out of debugging, there’s a red button on the toolbar called “terminate”.

Note that when single-stepping it can take a seemingly long time between steps, because GDB/AVARICE/Dragon is doing a lot of talking amongst themselves getting status from your chip. I believe every time the single-stepper stops the Dragon dumps the entire contents of the Arduino’s ram for display by GDB/Eclipse. You do get lots of fun light flashing on the Dragon during all this, though.

Optimization Can Be a Bitch

The sample program above didn’t have any variables, on purpose. When you’re debugging in Eclipse one of the windows shows the variables in your program, which is – in my opinion – the best part of debugging. It lets you spy into the variables and see if variable “a” is really holding what you think it’s holding. I didn’t use any variables for illustration above because it wouldn’t have worked right, here’s why, and here’s how you work around that.

The Arduino is an embedded platform with limited ram and storage (flash). The Arduino people (correctly) turned on size optimization in the Arduino’s compiler. Optimization is big topic in compiler design, and it essentially boils down to “the user wrote this code to do this task, and as the compiler I will re-write it to make it work faster/better/smaller”

The problem with debugging optimized code is that… well, it’s different code than what you wrote. In particular, the size optimizer (-Os) on GCC will do some amazing stuff like “you set this variable, and never used it, so I removed all references to it from the actual compiled code.” There’s also the general case of “oh, you didn’t have a lot of variables, so instead of keeping them in ram I kept them in registers instead for easier access.” Variables held in registers tend not to show up in the “variable” window so you can’t spy on them, you have to go look at the registers directly.

Let’s do a little experiment to show this. Make a new Eclipse Arduino Sketch called ArduinoOptimizerTest and use this code in your .cpp file:

// Do not remove the include below
#include "ArduinoOptimizerTest.h"
//The setup function is called once at startup of the sketch
void setup()
{
    Serial.begin(9600);
}
// The loop function is called in an endless loop
void loop()
{
    int a;
    int b;
    a=25;
    b=a+a;
    Serial.print("a is ");
    Serial.println(a);
    Serial.print("b is ");
    Serial.println(b);
    delay(1000);
}

Now this is a damned boring program. It stores a number in a variable, does some math, and prints it out. Yawn. You don’t need an Arduino for this, but we will do this to show just how much the Optimizer works to make you a better person. To show we’re not cheating, build this with the debugger info set, load it onto your arduino, and check it with the serial monitor to see that it does give output. (“a is 25” “b is 50” over and over).

Easy, it worked, right? This is a stupid experiment, right? So now go into debugging mode with the Dragon. Put the chip into debugwire mode, do a debug config, and start debugging in Eclipse and have a look at what’s going on.

Oh shit, check it out. See when you ran your program and single stepped it… it never ran the a=25 / b=a+a lines, for some reason the single step went right over them to the Serial.print() line. Why did it do that? Well, check the disassembly window on the right hand side. The Disassembly is the “these are the actual machine code instructions GCC compiled your code into and are running on the Arduino.” It’s a lot of strange looking little single-purpose instructions but you can see how your code has been translated into the machine code.

See how it says “loop:”, a couple of push r16/push r17 and then the instruction pointer for “Serial.print” is that “ldi” instruction? The GCC -Os optimizer said “you know what, you set those a and b variables, but never actually use them other than to do that print, so we just skipped all that and moved it all into the print call itself. The code was simple enough that the optimizer optimized it all away. The results are the same, but the execution is different than you expected.

Note that this is not actually a problem, this is a good thing. It means the compiler is looking out for you and trying it’s damnedest to make your code fit in the limited Arduino space and still do everything you want. It does mean that if you’re stepping through the code you may get surprised.

As an aside, many many many years ago when I was writing unix code on Sun systems you could not debug optimized code at all with the debugger. You had to debug with the un-optimized code only. So if you had a bug that showed up when optimized, but not when un-optimized, you were really shit-outta-luck. It was the best thing evar(tm) when GCC started doing enough work to let you debug stuff that had been mangled by the optimizer.

So okay, as an academic exercise now, what if you want the “pure” code you wrote to debug, and not the optimized version? Easy. We go back into the project properties and turn off the optimizer (-O0 instead of -Os for both the AVR Compiler and AVR C++ Compiler).

Then you have to rebuild – right click your project and do “make clean” first, to make sure all the code gets rebuilt without optimzations. When your build finishes you’ll see that sure enough, your code is larger than when it was built with -Os. You could get a problem where the code could be too big to fit in your Arduino, but in this test case it’s still okay. Upload the code to your Arduino (remember you’ll have to take it out of debugwire mode to do that, then re-enable debugwire again), start up AVARICE, start up the debugger, and here’s what you’ll see:

See that the instruction pointer will actually be able to land on the “a=25” line, and the disassembly shows that there’s actual code assigned to it now. You can also see the disassembly directly for each of the instructions that follow (a shit load of instructions to do something that seems simple, isn’t it? This is why the optimizer works so hard for you).

In the two screenshots you can also see that “a” and “b” were set to some random values before being initialized, which is the reason you initialize variables.

Remember to re-build your projects with optimization on (-Os) again if you’re going to continue.

If you’re doing all this on Linux, you don’t have to worry about the libusb steps, since avrdude/avarice work on linux just fine with the default ubuntu install. Also there’s no AVR studio for linux, so hey, no having to deal with that end at all. Just remember how to set your chips back to factory with avrdude if you mess things up.

Condensed Version

  • Write Code in Eclipse, build without errors
  • Upload to Arduino over usb-serial in Eclipse
  • Enable DebugWIRE on Arduino with AVRDUDE
  • Start AVARICE
  • Configure and start up debugging in Eclipse
  • Debug until your eyes cross
  • Disable DebugWIRE when done

Summing Up

So this works for me, maybe it will work for you. Is it easier than debugging using my previous method with AVR Studio? I guess that depends on how much you like Eclipse.

Is this any better than debugging using AVR Studio? Not sure on that one yet, I’m still investigating doing the debug with AVR Studio 5.1. Certainly less toolchain setup in that case. Using Eclipse in the mix does give you better diagnostics on code errors than using the Arduino IDE, at the cost of more complexity.

Is any of this easier than just using Serial.print() statements? Hell no. But if you really can’t figure out why something’s not right, this might be the best way.

Finally, here’s another Arduino picture, as required by law.

Really, that's all folks.

More on the Speakjet and TTS256 Chip

As fun as it is to use the Magnevation Speakjet shield for the Arduino, perhaps you want to do an application where you don’t want to have to program all those stupid codes, as I showed in an earlier post.

At that time I mentioned the TTS256 chip from Sparkfun, which is essentially a little text-to-speech dictionary chip made to work with the Speakjet. You pump in some regular boring text over the serial connection to the TTS256, it converts it to that phoneme stuff and presto, the chip speaks.

At the time I did that previous post I didn’t have a TTS256, but now I do. Sparkfun have a very nice tutorial on how to wire up the chip into your Speakjet shield. That tutorial is really good, and has demo code and so I will repeat none of it here.

I followed the instructions as shown and had no problems, but the difference to what I did is that rather than solder the speakjet onto the shield, I soldered on a 24-pin socket (technically two sockets, since I didn’t have a 24-pin, but the effect is the same). The advantage of doing things this way is that if you want to go back to the ‘old’ way of using the Speakjet – in direct phoneme mode – all you have to do is jumper two areas in the socket and it works as it did before you ruined it.

Seriously, always use a socket with a through-hole part if you can get away with it. Makes replacing the chip a dream when you blow it up.

I have the ‘newer’ version of the board which has the surface-mount version of the speakjet (the tutorial has the through-hole version), but the pins are the same so the locations of the solder points don’t change.

Also, the sparkfun pictures are good but aren’t so clear where the connections are, so I tried to take some clearer pictures.


Don’t lose your shit when you lose your shit.

Ever had your laptop stolen? That would suck, wouldn’t it. It’s pretty inconvenient to be without your facebooks and your twoofters, sure, but what’s really inconvenient is all your information getting into the hands of some thieving bastard.

Sure, in most cases people who steal your laptop are going to just sell it to some pawn shoppe for crack or linden dollars. In lots of cases they’re just bozos and take it home and start using it themselves. The problem is that if you’re like most people, your personal info is still on that machine for them to access.

I’m not thinking of stupid stuff like those ‘pictures’ of you and that guy’s wife, or all your l33t torr3ntz of Master Chef. I’m talking about stuff like your banking passwords, your email passwords. Use Firefox/Chrome/Internet Asploder? Do you have it ‘save passwords’? You’re screwed. Have your email program remember your password? You’re screwed. Lose your laptop and in a short time, a determined thief can clean you out.

What about your iPhone? Your Android phone? Same thing. There’s the inconvenience of having your shit stolen (or just lost), but the terror knowing that all those camera phone pictures of you and that guy’s dog wife are loose and in the wild.

So take some steps to keep yourself from freaking out.

You have to do these steps before you lose your stuff. Don’t do it after because that would be stupid.

Backups

I’ve been harping with you miserable fucks for years now to make backups, and you still don’t. This will also have the side benefit of saving your ass if your hard drive dies or you just accidentally drop your laptop off a bridge.

You have no excuse. Backup and Restore is built into Windows 7 now, and those insufferable mac people have had this for a while as well. You don’t have to do anything, you just need to set that shit up. Set that shit up already.

Disk Encryption

Yes, encrypt your damned hard drive. If you’ve got a portable machine that people can walk off with, you want to do this.

Using Windows? Then use Truecrypt or Bitlocker and enable the “whole disk encryption”. Using a Mac? Turn on Filevault for fuck’s sake. The Filevault in OSX Lion will encrypt the entire drive, and Filevault in 10.6 and lower will encrypt your home directory and make it safe. These are Free.

Yes, you can even do disk encryption in Linux. Don’t worry, nobody wants to steal your linux laptop.

The nice thing about using disk encryption like this is that it takes almost no effort on your part, you spend a few minutes clicking the mouse (I know that’s hard for you), and it’s done. Then all you have to do is remember your damned password.

Passwords

This one is kind of simple. If you have a computer, set it to require a password to log in. Sure, if you haven’t encrypted the disk it’s fairly trivial to bypass that, but look at who most thieves are: morons. They aren’t going to try to beat the password, they’ll just move on. It also keeps casual people from poking at your shit.

For your other passwords, use something like 1password, Lastpass, Keepass, or Supergenpass or even the built-in sync in Firefox and Chrome to manage your passwords. That way you have them synchronized off that laptop, and you can systematically go and change all your passwords – which you should do if your laptop gets stolen.

Scorched Earth

Here’s where you break out the heavy artillery. Remember you have to set these up before your shit gets stolen. If someone steals your iPhone/Android/Mac/PC, you want the ability to either

  • Get it back (unlikely)
  • Prevent them from using it

If you’ve encrypted the drive, don’t have an easily guessable password, and haven’t written it on a sticky note inside the case lid, that will probably do the job right there. The thieves’ only recourse will be to format the hard drive (destroying your data, keeping it out of their hands).

There are several solutions to tracking down your lost stuff, which is especially important for iPhones/Android phones, which can be pretty trivial to break into. For the iPhone it comes free with the phone: Find my iPhone is a service you had to pay for MobileMe to get, but is now free. Set this up right now. It lets you track the phone’s location (also good if you’ve just lost it behind the couch), put messages on the screen (“give me back my phone you knob”), or – most useful – wipe the phone from remote so nobody can get at the stuff on it. Then your phone just becomes another black market phone for drug dealers and terrorismists.

I don’t have an Android phone, but there are solutions for Android including Prey for Android. I’m sure you know a hundred better ones, and I don’t care.

For the laptop, there is the Prey Project, which is free for three machines – you can pay for more if you’re filthy rich and own so many computers. Prey will let you shut the machine down, get pictures from the webcam of the thief, location, etc. It’s free – so why the hell not? There are other solutions like Lojack, but I have no experience with them. I’m sure you’ve used a hundred better ones, and I don’t care.

Let’s face it: if you go to the cops with the exact location of the criminal, his picture in a mug shot, and him holding up a big sign saying “YO DAWG I STOLE THIS GUY’S LAPTOP”, that’s still not going to be enough to get cops to get off their donut-eating behinds to come out and do something about it. I have first-hand experience with this aspect of law enforcement. So the next best thing is going to be just being able to shut down and wipe the machine from remote to keep their grubby mitts out of your stuff.

The point is, setting up this stuff is easy, and is well worth it for the peace of mind you get when your shit gets ripped off.

Woe to the Stupidshield

(There still is no music associated with this post)

Here’s what I figured was a useful shield for an arduino that I wanted when I was debugging all that bullshit SPI interaction when I was making the ADT7310/Logshield combination. It’s a passthrough shield that has a breakout for all arduino pins that can be inserted between the arduino and a shield. Not fancy, but let’s you get access to any pin easily without having to grope around and get a spring clip onto a board.

Having said that, I finished the ADT7310/Logshield long before this thing showed up from the boardhaus. Maybe this will be helpful on my next project.

You don’t need me to show you this, here’s the schematic and the board layout. These were done with Eagle, but come on – you could lay these out with an ink marker if you wanted. I hand routed the traces since that was easier than watching the autorouter put tons of vias in.

I started the Eagle design from the Macetech Scaffold (there is a newer version than I used), simply because it has the board outline and header positions right. The Arduino has non-standard pin spacing between the headers for some unfathomable reason, and now that shields are designed around it they can’t change. Another option is to start from a design like the Adafruit protoshield, and just toss out the bits you don’t want.

The two 90-pin connectors are digikey # S5559-ND and # S5561-ND. I’m sure you can get them just about everywhere.

90-Pin Connectors S5559-ND and S5561-ND

You can get the stacking headers from Adafruit, although I got mine from eBay.

Stackable Headers

Unfortunately, there was an error at the boardhaus, and the boards showed up… wrong.

That was supposed to be copper, not silkscreen

At first I thought I messed up the gerbers, which would be pretty damned embarassing considering how simple this board is. I checked with le boardhaus, and it turned out to be manufacturing on their end – the place that actually produced the board mistook the copper layer for a silkscreen layer. I have no clue how you could, they were named correctly and passed all the DRC checks, but hey. They offered to make me another set for free, or give me a refund. I elected to get them to make me a proper set, what the heck.

Of course, the last set took a month to arrive, and I didn’t really want to wait another month before writing this post assembling the board, so I resorted to my gorilla/guerrilla bluewire ratnest fix.

and finally, here it is doing it’s actual job – sandwiched between an Arduino and a shield.

Stupidshield on Arduino Stupidshield and Logshield, note connectors peeking out from the stupidshield

An Arduino Library for the ADT7310 SPI Temperature Sensor

(There is no music associated with this post, either)

I wanted a temperature logger for monitoring one of my labs. In the first iteration I used an Adafruit Data Logging Shield with a TMP36 sensor, pretty much as they describe in their fridge logger tutorial.

Problem: the problem that always comes up with microcontroller measurements. That stupid 10-bit A/D converter. I realize that microcontrollers aren’t supposed to be high-accuracy data acquisition systems, but damn I wish they were at least 12-bit. 10-bit means 1024 (2^10) discrete measurement levels. That’s great when reading a potentiometer position, but it introduces a lot of quantize error with things like the TMP36.

Quantizing sucks

The TMP36 works from -40 C to +125C, with 750mV output at 25 C and 10mV/C range. If you use the TMP36 with the 3.3V source and reference, that means that 10-bits gives you… 3.22 mV resolution per bit.

Example: The arduino A/D reads a value of 200 (0.645 V with a 3.3V reference). That corresponds to temperature (0.645-0.5)*100 = 14.45 C. If the A/D reads 201 (one bit higher), that corresponds to a temperature of 14.77 C. So you can see that your temperature quantizes to 0.32 C. You can’t read 14.6 C, it clips to either 14.45 or 14.77. If you’re monitoring room temperature that kinda sucks.

Who cares

So, what to do? You can get a more sensitive temperature sensor. The TMP37 has a sensitivity 20 mV/C. Still not a lot of bits in the range I want to use it in. If the lab gets above 100 C I figure it’s time to get the fuck out anyway.

Another solution You could get a different outboard A/D and use it to read the TMP36. I’ve used MCP3304’s (12/13-bit SPI A/D), but that’s a lot of effort just to read one sensor. the TMP’s are only really rated at +/- 1 C at 25 C anyway, so at some point the sensor itself is going to be the limit.

The route I went was: find a temperature sensor with a digital output (SPI, I2C, whatever) that has higher resolution, skipping the A/D issue. For no good reason I picked the Analog Devices ADT7310. It has an SPI interface, doesn’t require calibration, and is 16-bit capable (0.0078 C resolution). They were also fairly cheap ($3 from digikey).

Package issues

First issue was just wiring the stupid thing up. I wanted to use it with that Adafruit Logger Shield I mentioned earlier. The ADT7310 is an SOIC package, and the Logshield doesn’t have any footprint placement for SOIC parts (the protoshield does, but the logshield just has some through-hole places). A long time ago I shunned surface-mount parts because I solder like a gorilla, but in these times if you want IC’s you have to go surface-mount. At least it wasn’t a BGA.

To solve this first problem, I used a couple of different little SOIC-pin header adapter boards. The first couple I built I adapted from a 20-pin SOIC board I had lying around, so I cut the board short with a dremel. Nice but the spacing is wide, so it covers lots of holes. A later one I use some really sexy small adapters from Sparkfun. $2.95 was a little much, but still cheaper than making my own board.

I’m old, half blind, and my hands aren’t all that steady. All of that can be compensated for by doing something easy: solder under a microscope. I bought a cheap stereo dissecting scope from eBay a few years ago and it makes soldering all these fine pitch things a dream. Use a fine-tip iron, thin solder, and a solder fluxpen and yer golden.

Here’s some of the completed modules.

I put on a 0.1 uF capacitor, as recommended (ADT7310 needs it), and the two recommended pullup resistors for the alarm pins. I don’t know if the chip works just as good without the pullups, but it was easy to put them on. Shows how small this package is when it’s dwarfed by the through-hole resistors. In a better design you could use some SMT chip resistors.

Some issues found during the breadboard stage

First thing, is this silly chip is really fussy. That decoupling cap on the power? Yeah, you really need that. I had a hell of a time getting the communication over SPI to work with this chip, and a lot of it was fixed by adding the decoupling cap, and using shorter leads to the breadboard. The chip would happily clock along and drop an error every few measurements. Decoupling cap dropped that to a few dozen measurements, and short leads meant I could run tens of millions of measurements (no joke) without errors.

Errors? Yeah. With some SPI devices, selecting them with the chip select does the reset and sets things up for a read/write and you’re good to go. The MCP3304 works like that, I believe. The ADT7310 powers up, gets its registers configured, and then you communicate with SPI. If the chip gets fussy or you lose a bit or a clock somewhere, it goes into sulk mode and won’t respond with anything other than “0” on output. The only way out of this is to do the soft reset – clock in 32 or more “1’s” on the SPI line and the ADT7310 resets itself. It also means you have to reconfigure your configuration registers if you changed them from the default powerup settings.

In the first few trials writing for this guy I was doing “bit-bang” SPI, where I was providing my own clock and control signals directly. This works great, but again mr. fussy ADT7310 was very specific about when the clocks had to come. Mysterious stuff like losing the last bit on a read, that sort of thing. Although I did get that working I then re-coded everything to use the Hardware SPI, as I was able to make the SD card (which also uses SPI) and the ADT7310 co-exist on the Arduino logshield without interfering. Using Arduino’s hardware SPI library is a lot easier, too – let it do all the heavy lifting.

The problem I had was trying to determine if you’ve lost communication sync. If the chip is sulking all it will do is crank out “0” on the output. If you were actually reading a temperature that was around zero that might make it hard to detect. The technique I eventually settled on was to do things the hard way: after reading the temperature, check the Tcrit setpoint register (the ADT7310 has a couple of setpoint registers that can hardware assert two pins on the chip for alarm interrupt purposes, the setpoints are set through writing to one of the registers, and can be read back). Register 0x04 (Tcrit) very nicely has a default value of 0x4980 (147 degrees) at powerup, so it’s got enough bits to give me confidence things are still reading right (0x06-Thigh has 0x2000 and 0x07-Tlow has 0x0500, not enough ‘set’ bits to be confident you’re reading them all correctly). Mind you, you can always load one of these registers with whatever value you wanted.

Something that would have really helped doing this was spying on the SPI bus with a logic analyser. Using an oscilloscope is okay, but it can be hard to track what you’re seeing if you don’t have storage. Although I figured out my bit-bang issues before it showed up, I broke down and bought a Saleae Logic Analyser. I hooked that shit up and it worked exactly as advertised. I should have bought it sooner.

So in general, my strategy was:

  • Read temperature register 0x02
  • Read Tcrit register 0x04, compare with known value (0x4980)
  • If you get 0x4980 from 0x04, the temp was probably fine. If not, you’re probably desynchronized and should reset the chip.

So once I had things actually working, I coded everything up into a functional ADT7310 Arduino Library. Like the SerLCD library I’ve previously discussed, putting it up as a proper object-oriented library makes things nice and clean and encapsulates a lot of the busy work so you don’t have to worry about it.

The ADT7310 has lots of operation modes (16-bit, 13-bit, continuous, one-shot, etc). I really only tested all this in 16-bit continuous mode. Everything is just SPI commands though, so it should work (cough). The Datasheet explains what all the modes do, and I include some #define‘s to make it simpler to initialize the chip. I didn’t include any support for the “continuous read” method (I didn’t really care about doing that), or reading the status of the Tlow/Tcrit/Thigh flags (since they don’t appear in the 16-bit read), but you can just pull the bits out yourself from the register 0x02 read value.

Download the library here. This version is now old, the github version is the current one.

You can also download it from github.

Again, like the SerLCD one I made it’s under LGPL because I really don’t give a crap, and I know all you people trying to do your homework aren’t paying attention to licenses anyway.

The library includes functions for reading and writing registers in 8/16 bit modes. It also has a reset function to reset the chip (but does not reprogram the mode, you do that yourself), and it includes a function to convert the 16/13/10/9bit values into temperatures. Why you would use this chip and not go for full on badass 16-bit mode is beyond me, but it’s there. The library also includes a demo example on using reading temperature and checking for desynchronization error. It does depend on the SPI.h library, which is included in the Arduino software package now. I’ve tested this under arduino-0021.

It’s one of those “it works for me” situations now, your mileage may vary. If you don’t like it, tough.

(Yet Another) Sparkfun SerLCD library for Arduino

(There is no music associated with this post)

Recently I did a little project with an Arduino board, using an LCD based on that HD44780 chipset. Reliable, fairly standard. The problem in that project was I essentially ran out of digital control lines. By the time I had analog inputs, SPI, I2C, and this LCD going in 4-bit mode (using 6 lines, 7 if not cheating the Read/Write), I was out of pins. That project finished up fine, but I figured I would investigate using a Serially-enabled LCD for the next thing I did.

The problem with serial-enabled LCD’s is that you can get boring HD44780 parallel units for like a dollar from electronics surplus stores, and the serial-enabled ones are like $80. That’s what put me off them in the past, since I see parts and like to buy a couple and have them sitting in reserve for when I want them.

After this last project I ended up buying a couple of the Sparkfun SerLCD modules. Their unit is pretty cheap ($17 for just the backpack, $25 with an LCD). I got the 5-volt version since the arduino is 5V.

With the HD44780 you have to worry a lot about timing and initialization, although there is an arduino library for them which works fine and abstracts a lot of the mess.

The usage of the SerLCD couldn’t really be simpler. If you send it characters, it prints them on the screen. If you send some special single-byte commands it will do functions like turn the display off, move the cursor, set the position, etc. The SerLCD also has backlight PWM control so you can control the brightness of the illumination of the LCD, which is something you can’t do with a raw parallel HD44780 unit. This is all documented in the SerLCD manual [PDF].

Using the SerLCD with an arduino is also really simply. Send characters out the serial port, and you’re done. There’s already an example in the Arduino Playground that shows this. I recently wrote an actual arduino “library” for another chip I was working with, and so I figured I’d try to apply this blundering knowledge to writing a SerLCD library. There probably are a dozen other libraries that do this already, but this one is mine.

Putting together the SerLCD library means that you can address the SerLCD in that nifty Object-Oriented style that other libraries (LiquidCrystal, Serial, SPI, etc) do without having to fuss with too much precursor setup. Should also make the code more portable between your projects too.

I designed the library to use NewSoftSerial, which you can get from Mikal Hart. I think there are rumblings that NewSoftSerial will get rolled into the main Arduino software eventually, but for now you just have to get it manually. I used NewSoftSerial because the Arduino has a dedicated serial interface on digital pins 0/1 which is also shared with the USB-serial interface. So if you wanted to do USB communication at the same time as drive a SerLCD you need to move the SerLCD to other pins which the Serial class doesn’t do. I think the ArduinoMega’s have multiple hardware serial ports, but I wrote this for an Arduino Duemilanove. Mega’s have tons more digital pins anyway to run HD44780’s directly, so who gives a crap.

If you want to use the HardwareSerial port, the library is trivial to change.

In the library I (tried) to implement all the features of SerLCD. I’ve only tested it with the 16×2 display though, so your mileage may vary. I didn’t include anything towards changing the SerLCD bootup splash or resetting the baud rate, since you have to do those when the SerLCD is first powering up and I didn’t want to be bothered. The only issue I encountered with the SerLCD v2.5 firmware seems to be that it would lock up until powered off/on again if you hammered backlight control commands at it too fast. I put a couple of delay() statements in the backlight settings and haven’t have problems.

Using the library is pretty easy. Download the .zip, and unzip it into your Arduino user-contributed-libraries folder (On Windows, this is your My Documents/Arduino/libraries folder, not inside the Arduino IDE directory. I tested this with arduino-0021 on my Duemilanove with an ATMega168 (not the ATMega328, but there’s no reason it shouldn’t work the same), so again – your mileage may vary.

Download the library here. This version is old, the github version is the current one.

You can also download it from github.

The library includes a demo program in the examples directory. Since most of Arduino is LGPL I made this LGPL, but I know most of you people in your plz send me teh codes mindset don’t obey any licenses. If you don’t like LGPL, tough.

A very basic program would be:

#include <NewSoftSerial.h>;
#include <SerLCD.h>;

// NewSoftSerial Object on pin 2
NewSoftSerial NSS(0,2);
// SerLCD object using that NSS
SerLCD theLCD(NSS); 

void setup()
{
  // Remember to start the NewSoftSerial port 
  // before doing things with the SerLCD
  NSS.begin(9600); 
  Serial.begin(9600);
  // This will attempt to initialize the display to 
  // blank with the backlight on 
  theLCD.begin();   
  // Display some massively important informative text
  theLCD.print("Hello, Jerk"); 
}

void loop() 
{
       // nobody cares  
}

WordPress.com’s code tags are still crap

I tried to do this the “right” way and designed SerLCD to inherit from Print::print , that way it picks up all the methods that print() can do – like formatting floats, handling different variable types – without me having to write a stitch of code. Hopefully it also means it’ll keep lockstep with the Print::print automatically that way, so any new features in Print::print are usable by this. I got this idea from this guy’s post where he implements it for an OLED screen. Yes, I know you’re a much better coder than I. Again, it works for me, any your mileage may vary. If you find this useful, enjoy. If you don’t, well then I don’t care.

Here’s a stupid picture (SerLCD’s Rx is connected to arduino digital pin 2):

and here’s a stupid video: