1

I want to use Arduino's sleep and wakeup functionality but have hit a roadblock and can't seem to get past it. As I am just prototyping for a final system, I cannot use the LowPower library to implement the functionality so I am doing it barebones. I am able to put the Arduino to sleep just fine, the main problem is with the watchdog timer. I have or I think I have configured it for a 8 sec interrupt to wake the Arduino back up from sleep but Arduino comes out of the sleep just as it enters it without any delay. The code is

#include <Arduino.h>
#include <avr/sleep.h>

void goToSleep();
void setupWDT();
void stopWDT();

ISR(WDT_vect) {
  sleep_disable(); // wake up the Arduino
}

void setup() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  stopWDT();

  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);
  Serial.println("Uno is in setup funtion.");

  bool ledState = 0;
  while(millis()<3000){
    digitalWrite(LED_BUILTIN, ledState);
    ledState = !ledState;
    delay(500);
  }
}

void loop() {
  Serial.println("Uno is awake.");
  digitalWrite(LED_BUILTIN, HIGH);
  delay(2000);
  Serial.println("Going to sleep...");
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);

  setupWDT();
  goToSleep();
  stopWDT();
  delay(100);
  digitalWrite(LED_BUILTIN, HIGH);
}

void goToSleep() {
  ADCSRA &= ~(1<<ADEN); // disable ADC
  sleep_mode(); // put the Arduino to sleep
}

void setupWDT() {
  cli();
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1 << WDE);
  WDTCSR |= (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // configured for 8 sec delay interrupt
  sei();
}

void stopWDT() {
  cli();
  MCUSR &= ~(1 << WDRF); // clear reset flag
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1<<WDE);
  WDTCSR = 0x00; // stop WDT
  sei();
}
phizaics
  • 11
  • 1

1 Answers1

1

Try changing this:

void setupWDT() {
  cli();
  WDTCSR |= (1 << WDCE);
  WDTCSR &= ~(1 << WDE);
  WDTCSR |= (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // configured for 8 sec delay interrupt
  sei();
}

to:

void setupWDT() {
  cli();
  WDTCSR = (1 << WDCE) | (1 << WDE) ;
  WDTCSR = (1 << WDCE) | (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // configured for 8 sec delay interrupt  
  sei();
}

It appears that your construct violates the 4 clock cycle window that the WDCE Watchdog Change Enable bit allows for updates to the WDE bit.

6v6gt
  • 549
  • 3
  • 6