WatchDog bites !!

Was trying to understand the WDT stuff. Located a good tutorial on the same by Nicolas Larsen.

Just one query… to check out the WDT interrupt when it fires put in a print statement. The point i am unable to understand is the process continues till 2000ms , then prints " Watch Dog Bites !!" and then prints 2200ms before rebooting. I am unable to follow the code flow at this point - i expect the processor to reboot after the line " WatchDog bites !!"

Here is the code : ( Of course in real time i never will try to print inside of WDT isr !! )

/*
  Watchdog Timer Basic Example
  10 June 2011
  Nicolas Larsen
*/
#include <avr/wdt.h>
int loop_count = 0;

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting up...");
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  delay (500);
  watchdogSetup();
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void loop()
{
  for (int i = 0; i <= loop_count; i++) 
  {
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(100);
  }
  loop_count++;
  wdt_reset();
  Serial.print(loop_count);
  Serial.print(". Watchdog fed in approx. ");
  Serial.print(loop_count * 200);
  Serial.println(" milliseconds.");
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

ISR(WDT_vect) // Watchdog timer interrupt.
{
  
  // Include your code here - be careful not to use functions they may cause the interrupt to hang and
  // prevent a reset.
  Serial.println( " Watch dog bites !!");
}

//****************************************

void watchdogSetup(void)
{
  cli();  // disable all interrupts
  wdt_reset(); // reset the WDT timer
  /*
    WDTCSR configuration:
    WDIE = 1: Interrupt Enable
    WDE = 1 :Reset Enable
    WDP3 = 0 :For 2000ms Time-out
    WDP2 = 1 :For 2000ms Time-out
    WDP1 = 1 :For 2000ms Time-out
    WDP0 = 1 :For 2000ms Time-out
  */
  // Enter Watchdog Configuration mode:
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  // Set Watchdog settings:
  WDTCSR = (1 << WDIE) | (1 << WDE) | (0 << WDP3) | (1 << WDP2) | (1 << WDP1) | (1 << WDP0);
  sei();
}

//****************************************

Print statements tend to rely on interrupts, so printing in an Interrupt service routine is a bad idea. It may work sometimes but not always.

When you have the watchdog set to fire the interrupt then on the first "bite" it fires the interrupt and on the second "bite" it resets the board. So you see 2 seconds then the first bite, which appears to take about 200ms and then you wait 2 more seconds for the second bite which resets you.

@Delta_G

The Serial Monitor snap shot is attached:

SerialSnapShot.PNG

But I am not sure I get you when you talk about first bite and second bite… what I expected to happen was this :

  1. Loop runs and so does the WDT.
  2. 2000ms elapse.
  3. WDT kicks in. Loop is held as is and code inside WDT_ISR executes which is to print something. Once print completes, the WDT reset takes over and the Loop() resumes fresh starting at 0.

So where does the 2200ms print come in ?? If this is due to the way that WDT reset is implemented, then I always will reset after one more loop ??

You need to go back to the datasheet and read up on how the watchdog works. The watchdog can EITHER call an interrupt OR reset the board. It cannot do both. When you have it set to run an interrupt then it calls the interrupt and switches to reset mode so that if it bites a second time without being fed you get a reset. So the board will only reset if the dog bites twice without being fed. So after the first bite when it calls the interrupt, you get a new 2 seconds for the code to run before you get a second bite.

The purpose is that maybe you can write the interrupt so that it solves whatever problem was holding up the code and gets the dog fed and avoids the reset.

Hopefully you aren't trying to use those timing numbers as real times. Use millis instead and see how long things really take.

What is happening is that the code is running fine until loop count is 10. At 10 the for loop is almost enough to time out and you pat the dog just in time to stop him from biting. Then it runs the case with loopcount at 11 and the for loop is too long. SO the dog bites. And the ISR runs. On return from the ISR the for loop finishes, the dog gets patted and then you get to the print statement that says that it fed the dog in 2200ms. It really didn't feed the dog in 2200ms. The watchdog fired during that 2200ms. But you had it set to interrupt mode, so it ran the interrupt and returned to your loop and tried to keep going and hit that print statement. Then, when loop count is 12 you get the second bite. This is the one that resets the board so you never see that printed as the board reset before you got to that line.

Look at the value of millis at the beginning and end of each run of that for loop and look at millis in the watchdog interrupt and I think you'll see what I mean.

So here we go… snapshot showing the timing at the beginning of Loop() , dog feed timing and actual time when the dog bit. Thanks for the explanation…

Capture.PNG