/* Tree Ornament By Chris Ritchie 17/3/2017 Watchdog timer code by Sparkfun from H2OhNo - https://github.com/sparkfun/H2OhNo */ #include <avr/sleep.h> //Needed for sleep_mode #include <avr/wdt.h> //Needed to enable/disable watch dog timer byte randomNumber; struct LEDS { byte selected: 1; }; struct LEDS flash[5]; byte flashed = 0; ISR(WDT_vect) { } void setup() { randomSeed(analogRead(2)); pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); // Turn on all leds for (int i = 0; i <= 4; i++) digitalWrite(i, HIGH); delay(100); for (int i = 0; i <= 4; i++) digitalWrite(i, LOW); delay(200); //Power down various bits of hardware to lower power usage set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT sleep_enable(); } void loop() { ADCSRA &= ~(1 << ADEN); //Disable ADC, saves ~230uA // If all all 5 sets of leds have flashed, reset if (flashed >= 5) { reset(); } randomNumber = random(5); // Only flash led if it hasn't already flashed if (flash[randomNumber].selected == false) { wdt_disable(); digitalWrite(randomNumber, HIGH); delay(500); digitalWrite(randomNumber, LOW); setup_watchdog(7); //Setup watchdog to go off after 1sec sleep_mode(); ADCSRA |= (1 << ADEN); //Enable ADC flash[randomNumber].selected = true; flashed++; } } void reset() { for (int i = 0; i < 5; i++) { flash[i].selected = false; } flashed = 0; return; } //Sets the watchdog timer to wake us up, but not reset //0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms //6=1sec, 7=2sec, 8=4sec, 9=8sec //From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/ void setup_watchdog(int timerPrescaler) { if (timerPrescaler > 9 ) timerPrescaler = 9; //Limit incoming amount to legal settings byte bb = timerPrescaler & 7; if (timerPrescaler > 7) bb |= (1 << 5); //Set the special 5th bit if necessary //This order of commands is important and cannot be combined MCUSR &= ~(1 << WDRF); //Clear the watch dog reset WDTCR |= (1 << WDCE) | (1 << WDE); //Set WD_change enable, set WD enable WDTCR = bb; //Set new watchdog timeout value WDTCR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int }