using wdt in combination with sleeping

Hello All!

I am trying to use the sleep mode along with the WDT.

For example, I am reseting the WDT at the end of my main loop to check upon my program. The problem is when I put the uC to to sleep. During that time the WDT bites and then the whole program hangs, for example the current goes up (from 500uA to 3.9mA !) as well…, otherwise the program is running/working ok…

It looks like my wdt reset is not working properly, actually is there a different way to deal with wdt during sleep mode?

Please have a look at the code and let me know, if I am programming tackling the wdt properly.

The setup:

void setup() {

... the rest of setup!

  //start WDT setup
  myWDTsetup();

}

the wdt setup function!

// wdt setup
void myWDTsetup(void){

  wdt_reset(); //need to reset the WDT timer before you start usinging it, you want to a clean slate!


  // Enter Watchdog Configuration mode: 
  
  // WDIE = 0 : Interrupt disable
  // WDE = 1  : Reset enable 

  WDTCR |= (1<<WDCE) | (1<<WDE);

  // Set Watchdog settings

  WDTCR = (0<<WDIE) | (1<<WDE) |  
   (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);  // when to reset the uC

}

… and the main loop looks like that!

void loop() {

... the main program ...

//reset the WDT
wdt_reset();

}

Best.

What board is this?

If it's a nano/pro mini, burn the Uno (or minicore) bootloader. The bootloader that the pro mini, and clone-nanos and genuine nano's from before last febuary use has a bug that traps it in a reset loop if you reset with WDT (since the WDT stays on with minimum timeout after a WDT reset, and needs to be turned off immediately by the running code - but the older bootloaders don't do this, and run for longer than it takes for the wdt to bite). Optiboot (used on uno, and in improved version in minicore, and a "snatch defeat from the jaws of victory" version on the new genuine nanos) correctly handles the WDT and turns it off if it was on upon startup.

In any event - if you don't want the WDT to reset it out of sleep, you need to turn off the WDT before going to sleep.

Cheers for the explanation. I have sorted it, at least for the moment to work on. Indeed, the wdt is disabled durring the sleepmode, while it is turned back on in the ISR. So far so good. I am developing for tiny.

I found the example below very easy to grasp. But, is it possible it will not work on tiny?

Best.

#include <avr/wdt.h>
void setup(){
wdt_enable(WDTO_2S);
}
void loop(){
//do stuff here
wdt_reset();
}

WDT on tinies works the same as on atmegas (internally some of the bits to control it are in different registers, but the functions provided by avr/wdt.h handle that)

Ok, I got to the point where my program somehow makes a problem for wdt. Not sure what is wrong. For example, if I run the wdt without the “programm” in the main loop, it does its job, however, when programm is in, it hangs when biting, not rebooting properly...

Anyway, the programm works perfectly without the wdt, for example, I can easily printout the counter in the main loop for a test.... It goes to sleep , at that time the wdt is disabled and then, when woken up via interrupt, wdt is enabled back again, inside the isr...

The wdt is set in the setup(), then the main loop interates until the wdt bites and resets the uC, which should reboot the uC, restart the program and continue running in main loop... however, this does not occur, because apparently the wdt hangs somewhere. If I reset the wdt_reset() in the main loop, for example at the beginig or at the end of thr loop, the loop contines well, however, how can I test, know that my wdt works properly, for example, if it will bite, will it reset, reboot the uC and put the program back to the working state? How to test that?

I was thinking to try without the wdt reset in the main loop, but I cannot get over this, indeed, the wdt resets the uC, but this is where it all ends... somehow, it does not want to reboot properly to initial state, it hangs! I can see that also via different, higher current draw...

If you have any ideas how to tackle this,, I would be more than happy!

Best.

Are you using a board with the Optiboot bootloader installed?

If not, after WDT resets the board the WDT is still running with minimum timeout, and can’t be changed because WDRF is set, and you are stuck in a reset loop. At the very start of setup, do:

wdt_reset(); 
MCUSR &= ~(1<<WDRF);
wdt_enable(WDTO_2S);

Cheers DrAzzy, it did the job! It seems you know what are you talking about, therefore, I will pick up you brain a bit more. Currently, I disable WDT when going to sleep and when woken via interrupt, the ISR enables it back. Is this the right way to handle wdt while uC is sleeping? In addition, will it help to reduce power consumption during sleeping, if the ports on uC are in highZ ? Below is some code...

Best.

void goToSleep()
{
  // turn off the led sig
  analogWrite(ledSigPin, 0);

  //  //set pins to HighZ
  //    pinMode(7, INPUT);
  //    pinMode(6, INPUT);
  //    pinMode(5, INPUT);
  //    pinMode(3, HIGH);

  Sensor.clearInterrupt(); //this will clear sensor interrupts! https://github.com/SV-Zanshin/VCNL4010/wiki/clearInterrupt()
  Sensor.setProximityContinuous(true); // read prox while sleeping

  // disable wdt while sleeping
  wdt_disable();
  
  // turin off setting while sleeping
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();
}  // end of goToSleep
//ISR
ISR (PCINT0_vect)
{
  sleep_disable();
  ////  // set pins to original setup
  //    pinMode(7, LOW);
  //    pinMode(6, LOW);
  //    pinMode(5, LOW);
  //    pinMode(3, LOW);

  power_all_enable();    // power everything back on

  // also "wake up" enable the wdt
  wdt_enable(WDTO_2S);

  // *** state machine ***
  if (Sensor.getProximity() > HT) {
    currentState = WAITING_BELOW;
  }
  else {
    currentState = WAITING_ABOVE;
  }
  // *** end of state machine  ***

  // the wanted state after we wake up with interrupt
  //  1-0-0
  ledState = true;
  ledState1 = false;
  fading = false;
  fadeUp = true;

  aboveHT = 0;
  belowHT = 0;

} //end of ISR

I see no problem with that WDT behavior, unless the event you’re hoping to use the WDT to escape is a power supply glitch (brown out) that hangs the chip and you don’t have BOD enabled - then it could happen in sleep and potentially leave the chip in a hung state without WDT to revive it.

Atmel recommends setting them as inputs with pullup enabled.

However, see this thread: http://forum.arduino.cc/index.php?topic=590315.0

Cheers DrAzzy, yes, I am using BOD and seems I am ok with consumption atm 500uA with sensor running in background, btw you are tiny expert, I had to use a new tiny, so I have uploaded the code and so far so good, it works, with all the fuses programmed, however, is there something I should be aware about when going to a new chip?

best.

Hello,

maybe I should open another discussion, but I think here should be just ok to get back to this question, because the subject was partially addressed :)

Indeed, the WDT and sleep (wakeup via interrupt), including BOD works just fine, however, I am not sure what is my protection during sleep mode, e.g. if the uP goes "ballistic", what will then protect me?

For example, when in sleep mode the WDT is disabled, indeed, BOD is on all the time, however, if only the uP make some kind of an error and eg. does not "allow" the sensor to wake the uP and it hangs, the WDT is off, so what will be the guard in this case then?

I am just thinking how to make the program and its application bulletproof :)

Thank and all the best.