Watchdog Timer- Reset vs Resume

Hello,
My goal is to create code that;
drives a servo to sweep from 0 to 180---->
Goes to sleep for ~ 5 minutes -->
sweep the servo from 180 to 0 --- >
Goes to sleep for 5 minutes ---- >

repeat over and over.
I have the sweep part down- lets not worry about that.
My question is on the terminology of Reset vs, resume.- I am using the following code and it is working 1/2 way----
It will sweep as expected from 0 to 180, ---- but then resets itself quickly back to 0, wait the 8 seconds and star the 0 to 180 sweep at the proper speed.

I was aiming to have the WDT wake up and resume the loop of the code but I feel it is resetting on wakeup.

I am wrong in thinking there would be a way to get the WTD to resume the code?
or
Is there a better mechanism to achieve this. Power consumption is the key here. Also would prefer not adding an external clock if I can get away from it.

Extra credit---- Once I get this working, I want to stretch out the sleep duration to the 5 minutes ( not trying to do that here. Glad to take guidance on that method.
I will also not that there seems to be a few ways of writing this out that I have seen. Confusing for a neophyte such as myself

Thanks



// This is an example how to put an arduino board into deep sleep to save on battery power and
// periodically wake up to run some logic. Ideal for sensor stations like plant moisture sensors.
#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <Servo.h>
// Blink Before sleeping
#define LED_PIN (13)

Servo myservo;  // create servo object to control a servo
int pos = 0;  // variable to store the servo position

// This variable is made volatile because it is changed inside
// an interrupt function
volatile int f_wdt = 1;

// Watchdog Interrupt Service. This is executed when watchdog timed out.
ISR(WDT_vect) {
  if (f_wdt == 0) {
    // here we can implement a counter the can set the f_wdt to true if
    // the watchdog cycle needs to run longer than the maximum of eight
    // seconds.
    f_wdt = 1;
  }
}

// Enters the arduino into sleep mode.
void enterSleep(void) {
  // There are five different sleep modes in order of power saving:
  // SLEEP_MODE_IDLE - the lowest power saving mode
  // SLEEP_MODE_ADC
  // SLEEP_MODE_PWR_SAVE
  // SLEEP_MODE_STANDBY
  // SLEEP_MODE_PWR_DOWN - the highest power saving mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();

  // Now enter sleep mode.
  sleep_mode();

  // The program will continue from here after the WDT timeout

  // First thing to do is disable sleep.
  sleep_disable();

  // Re-enable the peripherals.
  power_all_enable();
}

// Setup the Watch Dog Timer (WDT)
void setupWatchDogTimer() {
  // The MCU Status Register (MCUSR) is used to tell the cause of the last
  // reset, such as brown-out reset, watchdog reset, etc.
  // NOTE: for security reasons, there is a timed sequence for clearing the
  // WDE and changing the time-out configuration. If you don't use this
  // sequence properly, you'll get unexpected results.

  // Clear the reset flag on the MCUSR, the WDRF bit (bit 3).
  MCUSR &= ~(1 << WDRF);

  // Configure the Watchdog timer Control Register (WDTCSR)
  // The WDTCSR is used for configuring the time-out, mode of operation, etc

  // In order to change WDE or the pre-scaler, we need to set WDCE (This will
  // allow updates for 4 clock cycles).

  // Set the WDCE bit (bit 4) and the WDE bit (bit 3) of the WDTCSR. The WDCE
  // bit must be set in order to change WDE or the watchdog pre-scalers.
  // Setting the WDCE bit will allow updates to the pre-scalers and WDE for 4
  // clock cycles then it will be reset by hardware.
  WDTCSR |= (1 << WDCE) | (1 << WDE);

  /**
	 *	Setting the watchdog pre-scaler value with VCC = 5.0V and 16mHZ
	 *	WDP3 WDP2 WDP1 WDP0 | Number of WDT | Typical Time-out at Oscillator Cycles
	 *	0    0    0    0    |   2K cycles   | 16 ms
	 *	0    0    0    1    |   4K cycles   | 32 ms
	 *	0    0    1    0    |   8K cycles   | 64 ms
	 *	0    0    1    1    |  16K cycles   | 0.125 s
	 *	0    1    0    0    |  32K cycles   | 0.25 s
	 *	0    1    0    1    |  64K cycles   | 0.5 s
	 *	0    1    1    0    |  128K cycles  | 1.0 s
	 *	0    1    1    1    |  256K cycles  | 2.0 s
	 *	1    0    0    0    |  512K cycles  | 4.0 s
	 *	1    0    0    1    | 1024K cycles  | 8.0 s
	*/
  WDTCSR = (1 << WDP3) | (0 << WDP2) | (0 << WDP1) | (1 << WDP0);
  // Enable the WD interrupt (note: no reset).
  WDTCSR |= _BV(WDIE);
}

// Setup for the serial comms and the other things
void setup() {
  Serial.begin(9600);
  Serial.println("Initialising...");
  delay(100);
  pinMode(LED_PIN, OUTPUT);
  setupWatchDogTimer();
  Serial.println("Initialisation complete.");
  delay(100);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

// main loop
void loop() {
  for (pos = 0; pos <= 180; pos += 1) {  // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);  // tell servo to go to position in variable 'pos'
    delay(80);           // waits xxxms for the servo to reach the posit
  }
 
  // Wait until the watchdog have triggered a wake up.
  if (f_wdt != 1)
    return;


  // Toggle the LED on
  digitalWrite(LED_PIN, 1);
  // wait
  delay(200);
  // Toggle the LED off
  digitalWrite(LED_PIN, 0);

  // clear the flag so we can run above code again after the MCU wake up
  f_wdt = 0;

  // Re-enter sleep mode.
  enterSleep();

 {
  for (pos = 180; pos >= 0; pos -= 1)  // goes from 180 degrees to 0 degrees
    myservo.write(pos);                // tell servo to go to position in variable 'pos'
  delay(80);                           // waits xxxms for the servo to reach the position
}
  // Wait until the watchdog have triggered a wake up.
  if (f_wdt != 1) {
    return;
  }

  // Toggle the LED on
  digitalWrite(LED_PIN, 1);
  // wait
  delay(200);
  // Toggle the LED off
  digitalWrite(LED_PIN, 0);

  // clear the flag so we can run above code again after the MCU wake up
  f_wdt = 0;

  // Re-enter sleep mode.
  enterSleep();
}

If the watchdog resets the processor and it reboots, all program variables are reset to their startup state.

If you are not sure what is happening, check the startup messages. "Initializing..." will be printed every time it reboots.

stretch out the sleep duration to the 5 minutes

Sleep for 8 seconds, count wakeups using f_wdt, and resume program execution after f_wdt exceeds 37 or 38. See this excellent tutorial: Gammon Forum : Electronics : Microprocessors : Power saving techniques for microprocessors

That is the crux of my question- what is the mechanism to resume vs reset when using WDT?
I only get the "intializing" message once on the the serial printer- but I cannot seem to get the second half of the loop to work -aka- going from 180 to o after a sleep.

Loop function execution never reaches the part where sleep mode is activated. f_wdt serves no useful purpose in your code, and you are accessing it incorrectly.

Study the tutorial on sleep modes linked above.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.