Project

General

Profile

Sleepy::loseSomeTime() prevents watchdog reset

Added by nubble over 5 years ago

Hi,
I tried searching the forum for something similar but not found anything.

I have a basic watchdog sketch together with Sleepy class on UNO with code as below. When I have delay methods the watchdog works as expected and resets after 4 seconds when in the infinite while(1) loop. Then I replace the delay() method with Sleepy::loseSomeTime() method and the sketch remains in the infinite while(1) loop and the watchdog doesnt reset the mcu.

Can anyone help me determine why this is so?

thanks Nubs

#include                                                      

#include                                                      // Download JeeLib: http://github.com/jcw/jeelib
ISR(WDT_vect) { Sleepy::watchdogEvent(); }     
int j;
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
wdt_enable(WDTO_4S);   
j=0;
Serial.println("Sketch Init");
}

void loop() {
  // put your main code here, to run repeatedly:
wdt_reset();
Serial.print("j=");
Serial.println(j);
if(j>3){
  while(1){
   Serial.println("Inside infinite loop...."); 
   Serial.flush();

    delay(2);
   Sleepy::loseSomeTime(1000);
   //delay(1000);
  }
}
j++;
Serial.flush();
delay(2);
Sleepy::loseSomeTime(1000);
//delay(1000);

}

Replies (15)

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by nubble over 5 years ago

I have gone through that blog, and that is why I am using sleepy. LoseSomeTime instead of delay for power efficiency.

Is there a way to use sleepy as well as the reset watchdog?

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

In broad terms, you could replace:

wdt_reset();

by the setting of a volatile flag and then check this flag inside the ISR:

ISR(WDT_vect) { 
if flag true{
Sleepy::watchdogEvent(); } 
}    
flag = false
}

I guess this might cause a WDT reset if the flag was not being set.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by nubble over 5 years ago

I have tried as suggested above but the code remains in the infinite loop and doesnt reset the mcu - for both flag= true and false.

Here is the code below:

#include                                                      

#include   
#include 
volatile bool flag;

ISR(WDT_vect) { 
  if(flag){
    Sleepy::watchdogEvent();   
  }
  flag= false;  
}     

//ISR(WDT_vect) { 
//    Sleepy::watchdogEvent();  
//} 

int j;
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
wdt_enable(WDTO_2S);   
j=0;
Serial.println("Sketch Init");
}

void loop() {
  // put your main code here, to run repeatedly:
//wdt_reset();
flag=true;
Serial.print("j=");
Serial.println(j);
if(j>3){
  while(1){
   Serial.println("Inside infinite loop...."); 
   Serial.flush();

    delay(2);
   Sleepy::loseSomeTime(500);
   //delay(500);
  }
}
j++;
Serial.flush();
delay(2);
Sleepy::loseSomeTime(500);
//delay(500);

}

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

This is bending my head a little but what about this line at the end of loop?

The logic is that if “flag” is not preserved in a true state then the watch dog action is to to reset at the end of the next “loop” + 2 seconds. It would be work checking my bit logic with the data sheet.

void loop() {
  // put your main code here, to run repeatedly:
//wdt_reset();
flag=true;
Serial.print("j=");
Serial.println(j);
if(j>3){
  while(1){
   Serial.println("Inside infinite loop...."); 
   Serial.flush();

    delay(2);
   Sleepy::loseSomeTime(500);
   //delay(500);
  }
}
j++;
Serial.flush();
delay(2);
Sleepy::loseSomeTime(500);
//delay(500);
if (!flag) WDTCSR &=  ~_BV(WDTON);  // Set system reset as response to Watchdog Timeout.

}

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

I knew my bit logic was suspect.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

I now don’t think that is good enough, we need to put

if (!flag) WDTCSR &=  ~_BV(WDTON);  // Set system reset as response to Watchdog Timeout.

into the ISR to ensure it is tested regularly. Where I had it would not trigger if loop got hung.

ISR(WDT_vect) { 
  if(flag){
    Sleepy::watchdogEvent();
    flag = false;
  } else {
    WDTCSR &=  ~_BV(WDTON);  // Set system reset as response to Watchdog Timeout.
  }
}     

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

Development of the fly, I have edited my previous post.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by nubble over 5 years ago

Thanks John for the ‘fly’ code! :)

I have the error: ’WDTON" was not declared in this scope, even though I have #include at the beginning of the sketch. Tried this include inside the ISR but still a no-go.

Googled a bit and I see that the WDTON fuse can be programmed with an ISP. Is this necessary? Is WDTON a typo?

Thanks in advance
Jason

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

No ISP needed, just a slower reading of the datasheet - do you have it?

ISR(WDT_vect) { 
  if(flag){
    Sleepy::watchdogEvent();
    flag = false;
  } else {
    MCUSR |=_BV(WDRF);  // Set system reset as response to Watchdog Timeout.
    WDTCSR |= _BV(WDE);
    WDTCSR &=  ~_BV(WDIE);  
  }
}     

I wonder if this will work.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

I wonder if some of the new values I have set will be undone by the exit from the interrupt routine restoring from the stack.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

You might be able to get away with this:

ISR(WDT_vect) { 
  if(flag){
    Sleepy::watchdogEvent();
    flag = false;
  } else {
   delay(65535);  // Wait here until the next WDT triggers - should cause a reset
  }
}     

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

No, the delay won’t work since Sleepy doesn’t enable the reset bit.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by JohnO over 5 years ago

• Bit 6 - WDIE: Watchdog Interrupt Enable
When this bit is written to one and the I-bit in the Status Register is set, the Watchdog Interrupt is
enabled. If WDE is cleared in combination with this setting, the Watchdog Timer is in Interrupt
Mode, and the corresponding interrupt is executed if time-out in the Watchdog Timer occurs. If
WDE is set, the Watchdog Timer is in Interrupt and System Reset Mode. The first time-out in the
Watchdog Timer will set WDIF. Executing the corresponding interrupt vector will clear WDIE and
WDIF automatically by hardware (the Watchdog goes to System Reset Mode). This is useful for
keeping the Watchdog Timer security while using the interrupt. To stay in Interrupt and System
Reset Mode, WDIE must be set after each interrupt. This should however not be done within the
interrupt service routine itself, as this might compromise the safety-function of the Watchdog
System Reset mode.

RE: Sleepy::loseSomeTime() prevents watchdog reset - Added by nubble over 5 years ago

Hi,
Sorry for the delay. Ive been out of town.

Ive tried many combinations of the above suggested code and all with the same outcome as the original problem in this thread.
Ive been digging a bit and I think I know what the problem is:
Sleepy::loseSomeTime() calls a method Sleepy::watchdogInterrupts() which changes the watchdog register to only have interupts and not reset.
So it seems that no matter what get done in the sketch loop ito configuring the watchdog register, this all get undone with any call to Sleepy::loseSometime().
Here is the code snippets from the Sleepy lib:

void Sleepy::watchdogInterrupts (char mode) {
    // correct for the fact that WDP3 is *not* in bit position 3!
    if (mode & bit(3))
        mode ^= bit(3) | bit(WDP3);
    // pre-calculate the WDTCSR value, can't do it inside the timed sequence
    // we only generate interrupts, no reset
    byte wdtcsr = mode >= 0 ? bit(WDIE) | mode : 0;
    MCUSR &= ~(1<
    (1-15/15)