Thursday, August 27, 2015

AVR Watchdog timer and Arduino Nano issues

In the past couple of day's I've tried to get the watchdog timer on my Arduino Nano to work properly. With success, eventually, but it took some time.

The watchdog timer is a stand alone timer, available in pretty much every 8 bit AVR, that has its own low power, low precision oscillator (clock) and it runs at about 128 KHz, give or take 10%. The watchdog timer can generate a reset signal after a set amount of time, ranging from 16 milliseconds to 8 seconds. You can reset the watchdog timer from your code using a special instruction ("wdr"). The idea behind this is that when your code gets stuck in a loop, or takes too long to execute for various reasons, the micro controller will reset itself, without needing any human interaction.

The watchdog timer in the more recent AVR microcontrollers (including the ones in the Arduini Nano/Uno) have the ability to generate an interrupt instead of resetting the device. Or to generate an interrupt before resetting the device, giving you a chance to store some valuable parameters.This also means you can use the watchdog timer to wake the AVR from idle/standby/power-down mode, perfect for low power applications! Let's look at the datasheet of the ATtiny13A for a second, chapter 7.1, sleep modes:

There are two sleep modes we're interested in here, the idle mode and power-down mode. The first mode has a lot of ways to wake up from, but also keeps the main clock running, meaning more power is used. The latter mode shuts down nearly everything, but can only be woken up from using an external interrupt or the watchdog timer. Now let's have a look at the supply current. Let's assume we're using the 9.8 MHz internal oscillator as clock source and use a 3.3V supply. That's chapter 19.2:

So we're looking at a bit over 2.5 milliAmps at room temperature. Not bad at all, but too much. That's what we'd be looking at if we'd just use a loop and count sheep until we had something to do again. The idle mode is a bit better, chapter 19.3:
About 0.65 milliAmps, that's a major improvement over just burning clockcycles. We'd have to use a timer to wake up though, adding about 0.1 milliAmp (chapter 19.1). Let's look at the power-down mode with watchdog timer enabled, chapter 19.4:
A bit over 4 microAmps, yes, that's MICRO amps. So in power down mode we're drawing less than 1% of the current we'd be drawing in idle mode, that's definitely worth using.

But programming an ATtiny can be a pain. To be more specific: testing and debugging can be a major pain. There's no serial port on those devices, and there are usually no spare pins left anyway. That is why I usually write and test my code with an Arduino before testing it on an ATtiny.

As with any part of the AVR I never used before, I started out simple: set up the watchdog to generate an interrupt every four seconds and toggle the LED pin on the Arduino. That worked, sort of. After four seconds the LED came on, and then turned off, and on, and off, and on, about ten times per second... What's even more annoying is that I couldn't upload any new code while it was doing that. I'd have to pull the USB cable out and plug it back in right before the new code would be uploaded. I double checked and triple checked my code, tried various stuff but couldn't get this simple bit of code to work properly. Finally I started to expect something was wrong with the fuse setting on the AVR, but the Arduino wouldn't let me read or write the fuse bits.

So after a bit of googling I found out I wasn't the only one having this problem. Apparently the fuses on the Nano have been set to always reset on a watchdog timer overflow. And to make matters worse: the bootloader doesn't handle a reset caused by the watchdog timer properly.

The solution (to both problems) is to burn the optiboot bootloader (used by the Uno) to the Nano. For this you'll need a second Arduino, in my case a Mega2560. You'll need to write the sketch "ArduinoIsp" to that Arduino.

Keep it plugged in, it will now act like a programmer. Next you'll need to wire the Nano to your programmer Arduino as described here. Now select the "Arduino as ISP" as programmer.

 As target board, select "Arduino Uno", this will make sure the optiboot boatloader and correct fuse settings will be burned.

 Finally, select "Burn Bootloader". It will burn the optiboot bootloader to the Nano and set the correct fuses!
Now disconnect the programmer Arduino, plug the Nano back in, and set the programmer setting back to "AVRISP mkII". Your board will now look like an Arduino Uno to the IDE, so remember to select that as board whenever you send a sketch to it.

As a side effect, code is now uploaded twice as fast. Yay! Oh, and the watchdog timer now works correctly: the LED now turns on and off every four seconds :)

1 comment: