Showing posts with label Watchdog Timer. Show all posts
Showing posts with label Watchdog Timer. Show all posts

Monday, February 8, 2016

The Watchdog Timer on Arduino

In this video we take a look at the Watchdog Timer on Arduino and the three different ways to configure it. We show a simple example using the Watchdog Timer and you can find the code from the example below.



//**********************Arduino Code*******************************
#include <avr/wdt.h> //Watch dog timer functions
#include <EEPROM.h> //library for using EEPROM

// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
volatile int wSetting = 1; //variable to store WDT setting, make it volatile since it will be used in ISR

void setup() {
  wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
  pinMode(led, OUTPUT); //set up the LED pin to output
  pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
  getSettings(); //start serial settings menu to choose WDT setting
  //setup the watchdog Timer based on the setting
  if(wSetting == 1) setWDT(0b01000000); //set for interrupt
  else if(wSetting == 2) setWDT(0b00001000); //set for reset
  else setWDT(0b01001000); //set for interrupt and then reset
}

void loop() {
  
  if(!digitalRead(2)) { //check if button to reset WDT was pressed
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    wdt_reset(); //Reset the WDT 
  }
}

//This function gets the WDT setting from the user using Serial comm
void getSettings() {
  Serial.begin(57600);
  Serial.println("We just started up......");
  byte b; //variable to store interrupt / reset tracker
  if(EEPROM.get(10, b)) { //check if interrupt occurred before reset
    Serial.println("...and an interrupt occurred.....");
    b = 0; //reset variable
    EEPROM.put(10,b);
  }
  Serial.println("Select the WDT setting: 1 --> interrupt, 2 --> reset, 3 --> interrupt and reset");
  //wait for user to input setting selection
  while (!Serial.available()) { }
  wSetting = Serial.parseInt(); //get entry and ensure it is valid
  if(wSetting < 1 || wSetting > 3) {
      wSetting = 1;
   }
   Serial.print("WDT setting is ");
   Serial.println(wSetting);
   Serial.println();
   Serial.end(); //don't want to mix serial comm and interrupts together
}

/*
void setSleepInterval(byte timer) {
  sleep_enable(); //enable the sleep mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //set the type of sleep mode. Default is Idle. power down saves the most power
  ADCSRA &= ~(1<<ADEN); //Turn off ADC before going to sleep (set ADEN bit to 0). this saves even more power
  WDTCSR |= 0b00011000;    //Set the WDE bit and then clear it when set the prescaler, WDCE bit must be set if changing WDE bit   
  WDTCSR = 0b01000000 | timer; //This sets the WDT to the interval specified in the function argument
  wdt_reset(); //Reset the WDT 
  sleep_cpu(); //enter sleep mode. Next code that will be executed is the ISR when interrupt wakes Arduino from sleep
  sleep_disable(); //disable sleep mode
  ADCSRA |= (1<<ADEN); //Turn the ADC back on
}*/

//this function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
   WDTCSR |= 0b00011000;
   WDTCSR = sWDT |  WDTO_2S; //Set WDT based user setting and for 2 second interval
   wdt_reset();
}


//This is the interrupt service routine for the WDT. It is called when the WDT times out and is in interrupt mode. 
//This ISR must be in your Arduino sketch or else the WDT will not work correctly
ISR (WDT_vect) 
{
  digitalWrite(led, HIGH); 
  if(wSetting == 3) {
    byte b = 1;
    EEPROM.put(10, b);
  }
  //wdt_disable();
}  // end of WDT_vect