watchdog reset

hi there i have been using the watchdog timer been working fine been using it like this:

#include <avr/io.h>
#include <avr/wdt.h>



void setup()
{
MCUSR=0;
wdt_enable(WDTO_8S);

} 

void loop()
{
  
//do somthing                  

 wdt_reset();
}

is it possible to do something before it resets? like save something to the eeprom?

Of course you can // do something BEFORE WDT reset - likes "write EEPROM " which takes time or send a very long message to COM port .
You have initialized / enabled / started the timeout of 8 seconds.
Now if it takes "write EEPROM" 6 seconds to complete, placing the WDT reset after the "write EEPROM" code will keep the WDT from resetting the whole system.

If it takes over 8 seconds the WDT reset will not execute in time and WDT will do its deed as expected.

WDT can be handy during development to keep processor "accidentally" to hang in an infinite loop, but you need some kind of indicator, I use Serial.print, to really keep track of what is happening before WDT restarts the whole program.

Joes:
hi there i have been using the watchdog timer been working fine been using it like this:

#include <avr/io.h>

#include <avr/wdt.h>

void setup()
{
MCUSR=0;
wdt_enable(WDTO_8S);

}

void loop()
{
 
//do somthing

wdt_reset();
}




is it possible to do something before it resets? like save something to the eeprom?

You can do whatever you like before the WDT times out. If you need more time, you can, of course, reset the WDT.

Otherwise, of course it will time out and reset the processor.

But I wonder why you're using the WDT? The only real use for it is an unattended system where it would be a pain to have to, say, drive out to a remote site and press a reset button. If your remote software crashed for some reason, the WDT would "push the button" for you.

Other than that, I don't see any need for it.

As VACLAV said, well placed [b]Serial.print[/b] statements in your code will show you where things are working (and where they are not). You can always use something like "#ifdev DEBUG, Serial.print(info); , #endif" and then just enable or disable it at will (enable when developing the code, disable it when it's done).

Joes:
is it possible to do something before it resets? like save something to the eeprom?

Do you mean: "do something in case it resets"?
The WDT can be run in "interrupt mode" where it does not reset the processor immediately but calls an ISR first. This is the place where you can do things like "save something to the eeprom". Things are somewhat more complicated because AFAIK you cannot write to the EEPROM within an ISR, so you just set a flag in the ISR and let you main loop act on that condition.
Consider reading the data sheet and this excellent introduction by Nick Gammon

did you use eeprom as an example or do you actually want to write the the eeprom before it resets ?

right i think i will start again with what i have at mo, what i want to do and what i was thinking of doing

what i have at mo:
i have a DS18B20 temp sensor display the temp on a OLED and a high and low set point what can be adjusted using a rotary encoder. when the temp is outside the high and low set point pin13 will altar

// WATCHDOG
#include <avr/io.h>
#include <avr/wdt.h>


int encoderPin1 = 2;
int encoderPin2 = 3;
int buttonPin   = 4;
int led         = 13;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

volatile int  lastEncoded    = 0;
volatile float encoderValue  = 15;
volatile float encoderValue2 = 33;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;


//            TEMP
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

/*-----( Declare Constants )-----*/
#define ONE_WIRE_BUS 7 /*-(Connect to Pin 7 )-*/

/*-----( Declare objects )-----*/
/* Set up a oneWire instance to communicate with any OneWire device*/
OneWire ourWire(ONE_WIRE_BUS);

/* Tell Dallas Temperature Library to use oneWire Library */
DallasTemperature sensors(&ourWire);


//            LCD
#define _Digole_Serial_UART_  //To tell compiler compile the special communication only, 
//all available are:_Digole_Serial_UART_, _Digole_Serial_I2C_ and _Digole_Serial_SPI_
#include <DigoleSerial.h>
//--------UART setup, if you don't use UART, use // to comment following line
#if defined(_Digole_Serial_UART_)
DigoleSerialDisp mydisp(&Serial, 9600); //UART:Arduino UNO: Pin 1(TX)on arduino to RX on module
#endif

#define LCDCol 16
#define LCDRow 2

const unsigned char fonts[] = {
  6, 10, 18, 51, 120, 123};

void setup() 
{
  MCUSR=0;
  wdt_enable(WDTO_8S);

  pinMode(led,        OUTPUT);
  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);
  pinMode(buttonPin,   INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on
 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);
  
    mydisp.begin();
    delay(1000);
    mydisp.clearScreen(); //CLear screen
    mydisp.drawStr(5, 0, "Hello"); //display string at: x=5, y=0
  
    delay(1000);

    mydisp.clearScreen(); //CLear screen
    mydisp.drawStr(0, 0, "Temp:");
    mydisp.drawStr(0, 1, "Set LO:");
    mydisp.drawStr(0, 2, "Set HI:");

sensors.begin();  // Start up the DallasTemperature library       
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println(buttonPushCounter);
    } 
  }
  lastButtonState = buttonState;
  
 
  

       sensors.requestTemperatures(); // Send the command to get temperatures

       mydisp.setPrintPos(7, 0);
       mydisp.print(sensors.getTempCByIndex(0)); // display a char array
       
       mydisp.setPrintPos(7, 1);
       mydisp.print(encoderValue); // display a char array 
       
       mydisp.setPrintPos(7, 2);
       mydisp.print(encoderValue2); // display a char array




  if (buttonPushCounter % 2 == 0) {
      mydisp.drawStr(13, 1, "*");
  } else {
      mydisp.drawStr(13, 1, " ");
  }
  
  
    if (buttonPushCounter % 2 == 1) {
        mydisp.drawStr(13, 2, "*");
    } else {
        mydisp.drawStr(13, 2, " ");
    }
    
    
       
       if (encoderValue < sensors.getTempCByIndex(0) && encoderValue2 > sensors.getTempCByIndex(0)) {
         digitalWrite(led,    HIGH);
       }
       else {
         digitalWrite(led,    LOW);
       }
    wdt_reset(); 
}

void updateEncoder(){
 int MSB = digitalRead(encoderPin1); //MSB = most significant bit
 int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 2) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if (buttonPushCounter % 2 == 0) {
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue = encoderValue + 0.1;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue = encoderValue - 0.1;
}
  if (buttonPushCounter % 2 == 1) {
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue2 = encoderValue2 + 0.1;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue2 = encoderValue2 - 0.1;
  }

  lastEncoded = encoded; //store this value for next time
}

what i want to do:
when i power up my high and low set point comes up with 15 and 30 because of the valve below
volatile float encoderValue = 15;
volatile float encoderValue2 = 33;

so if i adjest them and the watchdog reset they go back to 15 and 30

what i was thinking of doing:
well what i was thinking is when i power up it looks at the eeprom for its high and low and when the watchdog comes to reset it save the new high and low to the eeprom.

what do you think is a good way of going about this or is there a easier or better way of doing this?

thanks Joe

If you want to save current high / low BEFORE you remove power / stop processor,
than apply similar method as in post#3, but monitor "low power" interrupt. .
I am sure whatever processor you are using has an ability to gracefully shut down.

Actually - if you save the high / low when it changes you do not need to bother during power outage.

Than after restart you would read the EEPROM for "new" high/low values.

Initialize your high / low to zero and than read for current values and save them in EEPROM or read the EEPROM ( as suggested above) and compare current values.

I am not sure you really need WDT.

right i have been looking about and i have come up with this for the watchhdog, but after 8s it does not run though the interrupt and just freezes any idea?

#include <avr/wdt.h>


void setup()
  {
  Serial.begin(9600);
  Serial.println("turning on");
  delay(1000);
  watchdogsetup();
} 

void watchdogsetup(void)
{
  cli(); // disable all interrupts
  wdt_reset(); // reset the WDT timer
  /*
  WDTCSR CONIGURATION:
  WDIE = 1;  Iterrvpt Enable
  WDE = 1    :Reset Enable
  
  WDP3 = 1   :Set the four prescaler bits for a 8sec timecut
  WDP2 = 0
  WDP1 = 0
  WDP8 = 1
  */
  // Enter Watchdog conifiguration mode:
  //(1<5) generated a byte with all zeras and one 1 at the 5th (counting from zero) bit from the right.
  //hence for example, (1<<WDCE) generates "00010000", since MDCE=4
  WDTCSR |= (1<<WDCE) | (1<<WDE);
 // Set Watchdog setting:
  WDTCSR =(1<<WDIE) | (1<<WDIE) | (1<<WDP3) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0); // 8sec
  sei(); // enble inerrupts
} 

void loop()
{
  
// Man code here
Serial.println("timing down");
 return;
 
 wdt_reset();    // reset the watch dog to zero 
}

ISR(WDT_vect) // Watchdog timer interrupt
{
  // do somthing befor reset here
  Serial.println("all over now");
  delay(1000);
}
ISR(WDT_vect) // Watchdog timer interrupt
{
  // do somthing befor reset here
  Serial.println("all over now");
  delay(1000);
}

Don't do serial prints in an ISR. Don't call delay in an ISR.

right ok then i have dun it with a LED now:

#include <avr/wdt.h>


void setup()
  {
 pinMode(13,    OUTPUT);
 digitalWrite(13, HIGH);

  watchdogsetup();
} 

void watchdogsetup(void)
{
  cli(); // disable all interrupts
  wdt_reset(); // reset the WDT timer

  // Enter Watchdog conifiguration mode:
  //(1<5) generated a byte with all zeras and one 1 at the 5th (counting from zero) bit from the right.
  //hence for example, (1<<WDCE) generates "00010000", since MDCE=4
  WDTCSR |= (1<<WDCE) | (1<<WDE);
 // Set Watchdog setting:
  WDTCSR =(1<<WDIE) | (1<<WDIE) | (1<<WDP3) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0); // 8sec
  sei(); // enble inerrupts
} 

void loop()
{
// Man code here
 return;
 
 wdt_reset();    // reset the watch dog to zero 
}

ISR(WDT_vect) // Watchdog timer interrupt
{
  // do somthing befor reset here
    digitalWrite(13, LOW);
}

after 8 sec the LED go's low but never resets, should i be calling for a reset in the interrupt?

  WDTCSR =(1<<WDIE) | (1<<WDIE) | (1<<WDP3) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0); // 8sec

That's not the right bit pattern for 8 seconds.

In any case, didn't we agree in this thread that all you need to do is save to EEPROM when you change the setting? Trying to save it after 8 seconds by a watchdog isn't very helpful.

That's not the right bit pattern for 8 seconds.

is it not, where am i going wrong there then?

In any case, didn't we agree in this thread that all you need to do is save to EEPROM when you change the setting? Trying to save it after 8 seconds by a watchdog isn't very helpful.

right thought this was plausible, all so was thinking the eeprom would last longer if i did it this way.
if you save when you change the set point would it not save several time as your moving it?

thanks Joe

Joes:
is it not, where am i going wrong there then?

Look at the table. 8 seconds requires WDP0 and WDP3 and no other ones.

right thought this was plausible, all so was thinking the eeprom would last longer if i did it this way.
if you save when you change the set point would it not save several time as your moving it?

Well, you can do 100,000 writes to it. Make sure you don't write the same value (ie. if it is unchanged). What I would do in this situation is something like this (in the main loop):

  • Has the set point changed from what is in EEPROM?
  • If so, has 5 seconds elapsed from when the set point last changed?
  • If so, write the new set point to EEPROM

That gives you a window of 5 seconds to make an adjustment, before it is written.

Look at the table. 8 seconds requires WDP0 and WDP3 and no other ones.

what like this?

  WDTCSR =(1<<WDIE) | (1<<WDIE) | (1<<WDP3) | (1<<WDP0); // 8sec

Well, you can do 100,000 writes to it. Make sure you don't write the same value (ie. if it is unchanged). What I would do in this situation is something like this (in the main loop):

Has the set point changed from what is in EEPROM?
If so, has 5 seconds elapsed from when the set point last changed?
If so, write the new set point to EEPROM

yes that does make more sense i will have a look into something like that and i will be back with my finding lol

thanks again for your help :slight_smile:

  WDTCSR =(1<<WDIE) | (1<<WDIE) | (1<<WDP3) | (1<<WDP0); // 8sec

Yes, except you hardly need to set WDIE twice. More like this:

  WDTCSR =(1<<WDIE) | (1<<WDP3) | (1<<WDP0); // 8sec

right on nick theory what you think, am i on the right lines?

#include <EEPROM.h>
int value;
int value1;
int a = 0;
int z;
int zz;

unsigned long previousMillis = 0;    
const long interval  = 5000;   

volatile float encoderHI = 15; // encoder Hi 
volatile float encoderLO = 30; // encoder Lo

void setup() { 
encoderHI = EEPROM.read(1);  // look at the eeprom for the value on start up
encoderLO = EEPROM.read(2);
}

void loop(){
  unsigned long currentMillis  = millis();

  if(currentMillis - previousMillis > interval) { // has 5s been yet?
    previousMillis = currentMillis;               // reset millies
    value  = EEPROM.read(1);
    value1 = EEPROM.read(2);

    if (value != encoderHI,1) { // if value and encoderHI are not the same conscience
      z = encoderHI,1;
      EEPROM.write(1,z); // rite to eeprom at position one the value of encoderHI
    }

    if (value1 != encoderLO,1) {
      zz = encoderLO,1;
      EEPROM.write(2,zz);
    }
  }
  // do my other bits here 
}
    if (value != encoderHI,1) { // if value and encoderHI are not the same conscience

Can you run through what you think that line is doing?

if value and encoderHI are not the same execute the code

I was wondering about the ",1" part.

to limit it to one desimol place (00.0)
just had it in my existing code before. would this not work here?