// Note: The AVR SLEEP is not yet supported in Wokwi for a ATmega328P.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h> // for sleep/powerdown functions
#include <avr/wdt.h>
#define LED1_PIN (13) // D13
#define LED2_PIN (12) // D12
#define SLEEP_CYCLES_MAX (10)
volatile uint8_t sleep_cycles_count = 0;
volatile boolean wdt_enabled = true;
ISR(WDT_vect) { // ISR for WDT interrupt
digitalWrite( LED1_PIN, !digitalRead(LED1_PIN) ); // toggle the LED
sleep_cycles_count++;
sleep_disable();
}
void powerdown() {
noInterrupts();
set_sleep_mode( SLEEP_MODE_PWR_DOWN );
sleep_enable();
sleep_cpu();
interrupts();
}
void wdt_setup() {
noInterrupts();
MCUSR &= ~_BV(WDRF); // Clear the WDRF bit in MCUSR
WDTCSR |= _BV(WDCE) | _BV(WDE); // Enable WDT change
// Set WDT prescaler (WDT timeout for 1sec)
WDTCSR = _BV(WDP2) | _BV(WDP1);
// or wdt_enable(WDTO_1S);
// Enable WDT interrupt
WDTCSR |= _BV(WDIE);
interrupts(); // Enable global interrupts
}
void setup(void) {
pinMode( LED1_PIN, OUTPUT );
pinMode( LED2_PIN, OUTPUT );
wdt_setup(); // enable WDT
}
void loop() {
if (wdt_enabled) { // Check whether the WDT-powerdown operation is enbled ?
digitalWrite( LED2_PIN, !digitalRead(LED2_PIN) ); // toggle the LED
if (sleep_cycles_count >= SLEEP_CYCLES_MAX) {
digitalWrite( LED1_PIN, LOW );
digitalWrite( LED2_PIN, LOW );
wdt_disable(); // Disable WDT
wdt_enabled = false;
} else {
powerdown(); // Enter powerdown mode
}
}
}