A:
For readers who are interested in studying the behavior of the Watchdog Timer (WDT) in its three operating modes (WDT Interrupt Mode, System Reset Mode, and WDT Interrupt + System Reset Mode), I have provided below three separate sketches tested in UNO R3.
I chose to configure the WDT mode of operation using register-level code because the wdt_enable(timeout) function interferes with my implementation of the WDT Interrupt + System Reset Mode. The wdt_enable(timeout) function of interrupt/aver.h Library is hardcoded to configure the WDT in its System Reset Mode.
I have not used the while(true) {} infinite-loop approach to keep the MCU occupied during the 8-second timeout period. Since returning from the WDT ISR causes the MCU to resume execution within the same infinite loop, it becomes difficult to observe and evaluate the experimental results. Instead, I decided to put the MCU into sleep mode by sending command 12 + New Line from the Serial Monitor. After the expiry of 8 s timeout period, the WDT wakesup the MCU from sleep.
To indicate that the MCU is active and running normally, the onboard LED continues to blink at 200 ms intervals except sleeping time.
Feedback is highly appreciated.
1.
Sketch for only WDT Interrupt Mode (8 sec timeout):
At the expiration of each 8 m\s WDT timeout period, the MCU enters the ISR and then returns to the loop() function, where it prints the message "WDT Interrupt happened". It then continues with the main program flow, which includes blinking the onboard LED.
#include <avr/wdt.h>
#include <avr/sleep.h>
volatile bool flag = false;
char myData[20];
byte ledState = HIGH;
unsigned long prMillis = millis();
int y;
void setup() {
Serial.begin(9600);
Serial.println("Sytem Reset");
pinMode(13, OUTPUT);
SMCR |= (1 << SM1); //power down mode
noInterrupts();
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (0 << WDE)
| (1 << WDP3) | (0 << WDP2) //1001 = 8 sec
| (0 << WDP1) | (1 << WDP0); //WDT Interrupt Mode
interrupts();
}
void loop()
{
if(flag == true)
{
flag = false;
Serial.println("WDT Interrupt happened.");
}
byte n = Serial.available();
if (n != 0)
{
byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
myData[m] = '\0';
y = atoi(myData);
if (y == 12)
{
Serial.println("Entering into sleep until WDT timeout.");
Serial.flush(); //to get all the above charcaters onto Serial Monitor
wdt_reset();
sleep_enable();//while(true){;}
sleep_cpu();
sleep_disable();
Serial.println("WDT Interrupt happened; wakeup from sleep.");
flag = false;
wdt_reset();
}
}
else
{
digitalWrite(13, ledState);
if (millis() - prMillis > 200)
{
ledState = !ledState;
prMillis = millis();
}
}
}
ISR(WDT_vect)
{
flag = true;
}
Output:
21:18:07.632 -> Sytem Reset
21:18:15.922 -> WDT Interrupt happened.
21:18:24.292 -> WDT Interrupt happened.
21:18:28.261 -> Entering into sleep until WDT timeout.
21:18:36.612 -> WDT Interrupt happened; wakeup from sleep.
21:18:44.916 -> WDT Interrupt happened.
21:18:53.217 -> WDT Interrupt happened.
2.
Sketch for only System Reset Mode (8 sec imeout): (I have kept the ISR(WDT_vect){} related to code so show that they are not called upon in System Reset Mode.)
At the expiration of each 8 s WDT timeout period, the MCU does not enter the ISR. Instead, it undergoes a system reset and executes the bootloader. After that, it returns to the setup() function, where it prints the message "System Reset", and then proceeds to the loop() function to blink the onboard LED.
#include <avr/wdt.h>
#include <avr/sleep.h>
volatile bool flag = false;
char myData[20];
byte ledState = HIGH;
unsigned long prMillis = millis();
int y;
void setup() {
Serial.begin(9600);
Serial.println("Sytem Reset");
pinMode(13, OUTPUT);
SMCR |= (1 << SM1); //power down mode
noInterrupts();
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (0 << WDIE) | (1 << WDE)
| (1 << WDP3) | (0 << WDP2) //1001 = 8 sec
| (0 << WDP1) | (1 << WDP0); //Reset Mode
interrupts();
}
void loop()
{
if(flag == true)
{
flag = false;
Serial.println("WDT Interrupt happened.");
}
byte n = Serial.available();
if (n != 0)
{
byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
myData[m] = '\0';
y = atoi(myData);
if (y == 12)
{
Serial.println("Entering into sleep until WDT timeout.");
Serial.flush(); //to get all the above charcaters onto Serial Monitor
wdt_reset();
sleep_enable();//while(true){;}
sleep_cpu();
sleep_disable();
Serial.println("WDT Interrupt happened; wakeup from sleep.");
flag = false;
wdt_reset();
}
}
else
{
digitalWrite(13, ledState);
if (millis() - prMillis > 200)
{
ledState = !ledState;
prMillis = millis();
}
}
}
ISR(WDT_vect)
{
flag = true;
}
Output:
21:20:29.369 -> Sytem Reset
21:20:37.710 -> Sytem Reset
21:20:46.087 -> Sytem Reset
21:20:46.873 -> Entering into sleep until WDT timeout.
21:20:55.290 -> Sytem Reset
21:21:03.634 -> Sytem Reset
3.
Sketch for WDT Interrupt + System Reset Mode (8 sec timeout):
At the expiration of the first 8 s WDT timeout period, the MCU enters the WDT ISR and then returns to the loop() function, where it prints the message "WDT Interrupt happened".
At the expiration of the next 8 s timeout period, the MCU passes through the bootloader and then restarts execution from the setup() function, where it prints the message "System Reset". It then enters the loop() function and resumes blinking the onboard LED.
#include <avr/wdt.h>
#include <avr/sleep.h>
volatile bool flag = false;
char myData[20];
byte ledState = HIGH;
unsigned long prMillis = millis();
int y;
void setup() {
Serial.begin(9600);
Serial.println("Sytem Reset");
pinMode(13, OUTPUT);
SMCR |= (1 << SM1); //power down mode
noInterrupts();
WDTCSR |= (1 << WDCE) | (1 << WDE);
WDTCSR = (1 << WDIE) | (1 << WDE)
| (1 << WDP3) | (0 << WDP2) //1001 = 8 sec
| (0 << WDP1) | (1 << WDP0); //WDT Interrupt and Reset Mode
interrupts();
}
void loop()
{
if(flag == true)
{
flag = false;
Serial.println("WDT Interrupt happened.");
}
byte n = Serial.available();
if (n != 0)
{
byte m = Serial.readBytesUntil('\n', myData, sizeof myData - 1);
myData[m] = '\0';
y = atoi(myData);
if (y == 12)
{
Serial.println("Entering into sleep until WDT timeout.");
Serial.flush(); //to get all the above charcaters onto Serial Monitor
wdt_reset();
sleep_enable();//while(true){;}
sleep_cpu();
sleep_disable();
Serial.println("WDT Interrupt happened; wakeup from sleep.");
flag = false;
wdt_reset();
}
}
else
{
digitalWrite(13, ledState);
if (millis() - prMillis > 200)
{
ledState = !ledState;
prMillis = millis();
}
}
}
ISR(WDT_vect)
{
flag = true;
}
Output:
21:26:56.729 -> Sytem Reset
21:27:05.065 -> WDT Interrupt happened.
21:27:13.423 -> Sytem Reset
21:27:21.741 -> WDT Interrupt happened.
21:27:25.387 -> Entering into loop until WDT timeout.
21:27:33.755 -> Sytem Reset
21:27:42.059 -> WDT Interrupt happened.
21:27:50.440 -> Sytem Reset
