Arduino Watchdog Timer (WDT) Example Code

I guess I’ve been pretty lucky with my arduino projects for the most part. I have 3 arduinos that run around the clock. One has run for 3 years, one for 2 years, and one for one year. Two of them run flawless and have never required ‘rebooting’.

The one that has been running for 2 years hangs every couple of months. This one monitors a bunch of motion detectors and often hangs when I’m away from home which is quite inconvenient.

I have spent more than enough time trying to debug the one that hangs. I’ve checked my loops and there is just no way my code is the problem. I’ve tried to figure out where the problem lies. I’m 90% sure it lies in the library I’m using for the Nano Ethernet shield but the problem occurs so infrequently that debugging is difficult at best.

So I’ve come to the realization that I’ve just been really lucky with the two that don’t hang. I should have been making allowances for a problem because I sure don’t want to go out to an outside box in the winter, open it up, and mess with an arduino. In the future, all my projects need to use a watchdog timer (WDT).

Back in the very early days of email, we had Netware/MHS mail servers that transmitted email to branches via dialup modems (this was before internet mail). MHS was kind of buggy and it would hang periodically. If it did that when no one was at corportate, email between branches started queuing up which was a very bad thing at that company. I’d come in in the morning and get a call from a branch manager yelling at me.

To resolve the problem, I purchased WDTs that were internal PC boards you could insert into a PC. You initialized it with a time, say 20 minutes, and then between every email sent, the script would send a reset to the WDT board. As long as the PC didn’t hang, no problem. If it did, the WDT would timeout, reboot the PC, and it usually would reconnect without problem.

The Arduino WDT runs in a ‘process’ outside of your program. You initialize it with a time from perhaps 15ms to 8secs. If you don’t ‘reset’ the timer before it hits 0, it will reset the arduino and your code starts over. This keeps your program from getting stuck in an infinite loop. Just like the PC WDTs we used on the MHS servers, except the time limits are much smaller.

You can search the internet for Arduino WDT and find lots of good examples of how to setup code for the Arduino WDT. I’m including my own example program, not because it is better than any others, but it will remind ME exactly how I want to implement WDT.

I implement WDT like the PC WDT did – if you don’t acknowledge the WDT before the time limit, the timer pops and the hardware is reset. You can get fancier and instead of resetting the arduino you can have it call an interrupt handler.

One guy’s example of using an interrupt handler actually records where the program counter was when the WDT timed out and stores it in EEPROM. That gives you the ability to try to track back and figure out where the code got stuck in a loop. This is a cool idea and I may want to use it someday, so here is a link to that site:

http://www.megunolink.com/how-to-detect-lockups-using-the-arduino-watchdog/

Here is my sample code:

#include <Arduino.h>
#include <avr/wdt.h>
/*
  watchdog timer example code.

  flashes LED three times quickly on boot up. Then goes thru a loop delaying
  an additional 250ms on each iteration. The LED is on during each delay.
  Once the delay is long enough, the WDT will reboot the MCU.
*/

const int                                onboardLED            = 13;

void setup() {

    int                                  k;

    // immediately disable watchdog timer so set will not get interrupted

    wdt_disable();

    // I often do serial i/o at startup to allow the user to make config changes of
    // various constants. This is often using fgets which will wait for user input.
    // any such 'slow' activity needs to be completed before enabling the watchdog timer.

    // the following forces a pause before enabling WDT. This gives the IDE a chance to
    // call the bootloader in case something dumb happens during development and the WDT
    // resets the MCU too quickly. Once the code is solid, remove this.

    delay(2L * 1000L);

    // enable the watchdog timer. There are a finite number of timeouts allowed (see wdt.h).
    // Notes I have seen say it is unwise to go below 250ms as you may get the WDT stuck in a
    // loop rebooting.
    // The timeouts I'm most likely to use are:
    // WDTO_1S
    // WDTO_2S
    // WDTO_4S
    // WDTO_8S

    wdt_enable(WDTO_4S);

    // initialize the digital pin as an output.
    // Pin 13 has an LED connected on most Arduino boards:

    pinMode(onboardLED, OUTPUT);

    // at bootup, flash LED 3 times quick so I know the reboot has occurred.

    for (k = 1; k <= 3; k = k + 1) {
        digitalWrite(onboardLED, HIGH);
        delay(250L);
        digitalWrite(onboardLED, LOW);
        delay(250L);
        }
    // delay a bit more so it is clear we are done with setup
    delay(750L);
    }

void loop() {

    int                                    k;

    // this loop simply turns the LED on and then waits k*250ms. As k increases, the amount of time
    // increases. Until finally the watch dog timer doesn't get reset quickly enough.
    for (k = 1; k<= 10000; k = k + 1) {
        // at the top of this infinite loop, reset the watchdog timer
        wdt_reset();
        digitalWrite(onboardLED, HIGH);
        delay(k*250L);
        digitalWrite(onboardLED, LOW);
        delay(250L);
        }
    }
This entry was posted in c-arduino. Bookmark the permalink.

20 Responses to Arduino Watchdog Timer (WDT) Example Code

  1. thushan says:

    thank you very much for your help.
    I’m developing an application that uses an interrupt at wireless serial data receiving. then how can I be able to manage that problem with the above code?
    I guess in the above code, all the interrupts are disabled..!

    • Dan TheMan says:

      If I understand you correctly, you want to know if the WDT code will work with normal pin driven interrupts? Yes, you can write normal interrupt code for the pin receiving the serial data and the WDT code still works fine.

  2. djmkhardy says:

    Do all standalone arduino projects benefit from using the WDT? What program functions would necessitate using it?

  3. Dan TheMan says:

    Any ‘production’ program I write I use the WDT. If your program (or a you use library) gets stuck in a loop, the arduino will reboot itself. I would rather the device reset itself that I have to go outside into a below freezing garage and mess around doing a manual reset.

    One of the most complex arduino projects I’ve done monitors 10 electrical buses in a large computer room. I retrieve data from each bus by telneting into a terminal server, connecting to each bus, retrieving the current stats, and then making that data available as an SNMP client so the company’s SNMP console can monitor the computer room power in near real-time.

    It has run, non-stop, for around 4 years now and I never get a support call for it. It reboots itself once a week automatically, and if something does go wrong, WDT reboots it so no one is ever the wiser that something went wrong.

  4. mysz0n says:

    Could someone tell me what I would have to do if you set a value for the variable using buttons (eg. temperature beyond which alarm will activate) after such a reset, the variable is set to the default value.
    Is it possible (without using an SD card) to save this value so that after a reset by the watchdog the variable would still be set as before the reset?

    • Dan TheMan says:

      As you have seen, the WDT has the same effect has rebooting the arduino and you loose all of your variables’ values. To maintain those values between reboots, you can write them to EEPROM. I believe all arduino models have some EEPROM available. Here is the EEPROM library reference: https://www.arduino.cc/en/Reference/EEPROM

      In some of my programs, I like to keep user configuration information in EEPROM. when the user makes a config change, I update eeprom so the next time the arduino starts, I can retrieve the configuration setting.

  5. Technoblog says:

    Hello,

    Nice example; however, on my Arduino Nano, it doesn’t behavle as expected: once the WatchDog reset the microcontroler, it seems to get stuck (the led flickers at a high rate).
    I’m guessing the WD is firing again and again, before the setup() could disable it…

  6. Gus Smith says:

    Hi this is interesting. Is this reset by the watchdog timer the same as if you would press the reset button?

  7. Resington Juana says:

    Hi Dan, Thanks a lot for your code…That really saves my time. Can anyone please tell me, what i have to do to set a WDT for 100 Seconds…Which means, if my program hangs up for more than 100 Seconds i have to reset the Arduino…Thanks in Advance…

    • Dan TheMan says:

      It looks like the max for an AVR is around 8 seconds so to implement my code as-is won’t work for you.

      I have a project where the timeout is around 40 seconds and I handle it by using an intermediary timer ISR. Let’s see if I can clearly describe what I do.

      My main code (loop()) does some network operations which can take up to 30 seconds to complete, during which time my code cannot reset the WDT.

      In loop() at various locations, I set a timer using

      myclock = millis();

      I then have defined a function that is an interrupt timer called every 100ms. In that function I check to see if my own timer has not ‘popped’, in which case I reset the WDT:

      if (millis() <= myclock + 40000UL) // has it been <= 40 seconds?
      <>

      I know that isn’t the clearest explanation, but it should be enough to give you the idea.

  8. Resington Juana says:

    Hi Dan, Your code and explanation saved my time…It works for me.. Thank you very much…..

  9. how to calculate time required for reset i.e time to put in WDT function? as in above case you told i am working with project having 40 sec timeout

    • Dan TheMan says:

      I’m not quite sure of the question, but I think you want to know what WDT timeout I was using in the example dated Nov 4, 2017.

      If the interrupt is occurring every 100ms, you just need a WDT somewhat larger than 100ms.

  10. Thanks for this well written example. I try to use it on an Arduino Nano 3. It works the first time with the blinks as expected, but after reset it just blink the red LED fast and I cannot even reset it by pressing the reset button, I have to remove power, before it resets.
    Do you have any idea what is wrong. Is it something with the Arduino Nano 3? (I use the $2 chinese version)

  11. Hmmm… see my post just above here. Now I also tried this WatchDog example: http://makecourse.weebly.com/week13segment1.html
    I tried both on two different Arduino nano 3 boards (different chip versions). All 4 test failed in the same way described above.

  12. Andre says:

    Hi, I have a standalone 328p without bootloader and also hangs after wdt activates a reset, It resets the mcu but doesn’t reboot. Have checked fuses, reset pin is pulled up with 10k resistor, no luck. I use USBASP to program. Can’t find a solution anywhere..:-(

Leave a reply to Thomas Pedersen Cancel reply

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