Resetting / Rebooting ATTiny85 with Watchdog Timer (WDT)

I was expecting this to be a no-brainer. I use WDT on Arduinos w/o any trouble. The code for Arduino would roughly be:

#include <arv/wdt.h>

...
wdt_enable(WDTO_1s);
while (true) {}

After one second, the arduino reboots because of the WDT.

That does not work for the ATTiny85. It wants to call the WDT_vect ISR instead and somehow (at least for me) hangs up such that I have to remove power from the ATTiny85 to get it running again.

After hours of banging my head against the wall and searching every source repeatedly I finally was able to put together the following code which correctly reboots the ATTiny85:

#include <avr/wdt.h>

void reboot(
    ) {

cli();
WDTCR = 0xD8 | WDTO_1S;
sei();

wdt_reset();
while (true) {}

} //reboot

void setup (
    ) {

    wdt_disable();

    }

In this example, the WDIE bit is set to 1 which is necessary to get the MCU to reset. Evidently wdt_enable() is not doing that for the ATTiny85. The other possibility is that the wdt_enable() procedure is not fast enough as the ATTiny85 requires everything be set properly in 4 clock cycles.

Note: You MUST include wdt_disable() as the first instruction in setup(). I tried going without this and it hangs under that condition as well.

Either way, this code is working for me, so after 2 evenings of frustration, I can proceed with my project!

This entry was posted in c-tinys and tagged . Bookmark the permalink.

4 Responses to Resetting / Rebooting ATTiny85 with Watchdog Timer (WDT)

  1. mahesh says:

    hi, your code didn’t work for my ATtiny85 (programmed using an Arduino Uno as ISP) but the following did. the main difference is that MCUSR &= ~(1<<WDRF) needs to be set before wdt_disable() in your setup code, so it's the first thing that's executed.

    void setup() {
    MCUSR &= ~(1<<WDRF); // reset status flag
    wdt_disable();
    //… other stuff
    }

    void loop() {
    if (some-condition) reboot2();
    }

    void reboot2() {
    wdt_enable(WDTO_2S);
    while(1){};
    }

  2. Tom Hansen says:

    I’m using an Adafruit Trinket Pro 3V. Here’s my variation that works for me:

    #include

    void reboot() {
    wdt_reset();
    wdt_enable(WDTO_15MS);
    while (true) {}
    } //reboot

    void setup () {
    wdt_disable();
    }

  3. CShannon says:

    The Mahesh method worked for me as well. I’m using the TinyAVR programmer from Sparkfun and USBtinyISP programmer with Arduino 1.8.1 IDE with ATTiny85.

  4. Matthew says:

    There are four or five different versions or avr/wdt.h floating around depending upon your toolchain. The ATTinyx5’s were neglected in the definitions of wdt_enable(). The datasheet is obsessed more with disabling the WDT and less with setting it up. You may also want to redefine WDTO_4S and WDTO_8S as 0x20 and 0x21 so the “bitwise or” works without (messy ternary?) “if” statements. Mahesh is correct and Spence Konde has also noted this in his core with the same syntax. All the wdt.h header files include a commented function to similarly deal with MCUSR including copying it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.