Annoy-a-tron

Very simple circuit: connect power to pins 4 and 8 on the ATtiny85 and connect a buzzer between pin 6 of the ATtiny85 and GND (the minus of the battery) You can download the .hex file or compile the code yourself (below, or from https://raw.githubusercontent.com/pedroliska/ATtiny85/master/watchdog-wake/watchdog-wake.ino). See here for a finished project on protoboard.

Code from https://github.com/pedroliska/ATtiny85/blob/master/watchdog-wake/watchdog-wake.ino

#include <avr/interrupt.h> #include <avr/io.h> #include <avr/power.h> #include <avr/sleep.h> #include <avr/wdt.h> #include <util/delay.h> #ifndef ARDUINO #include #include "millionUtil.h" //not needed if compiled with Arduino & Arduino-Tiny #endif #define BODS 7 //BOD Sleep bit in MCUCR #define BODSE 2 //BOD Sleep enable bit in MCUCR int PIN = 1; int REGULAR_HI_MS = 800; int WAKE_INDICATOR_HI_MS = 0; //200; int INITIAL_BEEP_COUNT = 3; // number of "test" beeps before we go into the real loop // RANDOM_SLEEP_MIN = minimum number of 8-sec WDT periods to sleep for // RANDOM_SLEEP_MAX = maximum number of 8-sec WDT periods to sleep for int RANDOM_SLEEP_MIN = 7; // 1 min (1 * 60 / 8) int RANDOM_SLEEP_MAX = 30; // 4 mins //int RANDOM_SLEEP_MIN = 225; // 30 mins //int RANDOM_SLEEP_MAX = 525; // 70 mins uint8_t mcucr1, mcucr2; bool keepSleeping; //flag to keep sleeping or not unsigned long msNow; //the current time from millis() unsigned long msWakeUp; //the time we woke up long wdtCount; //how many 8-sec WDT periods we've slept for void setup() { for (int i=0; i < INITIAL_BEEP_COUNT - 1; i++) { makeTone(REGULAR_HI_MS); goToSleep(1); } } void loop() { makeTone(REGULAR_HI_MS); goToSleep(random(RANDOM_SLEEP_MIN, RANDOM_SLEEP_MAX + 1)); } void makeTone(int msOfTone) { pinMode(PIN, OUTPUT); startTone(); delay(msOfTone); // let the tone sound for a bit stopTone(); pinMode(PIN, INPUT); } void startTone() { //TCCR1 = 0x94; // faster clock //TCCR1 = 0x99; //TCCR1 = 0x9F; // slower clock (max value) //OCR1C = 4; // highest pitch (hard to listen) //OCR1C = 5; //OCR1C = 200; //OCR1C = 255; // lowest pitch (max value) // hi pitch combo (perfect with 3v no resistor, and no transistor) TCCR1 = 0x94; //OCR1C = 4; OCR1C = 7; // // old phone combo (too silent with 3v, no resistor, and no transistor) // TCCR1 = 0x99; // OCR1C = 255; // // audible combo // TCCR1 = 0x94; // OCR1C = 20; } void stopTone() { TCCR1 = 0x90; // stop the counter } // wdtLimit = number of WDT periods to wake after void goToSleep(long wdtLimit) { msNow = millis(); wdtCount = 0; do { ACSR |= _BV(ACD); //disable the analog comparator ADCSRA &= ~_BV(ADEN); //disable ADC set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); wdtEnable(); //start the WDT //turn off the brown-out detector. //must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD. //current while sleeping will be <0.5uA if BOD is disabled, <25uA if not. cli(); mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector mcucr2 = mcucr1 & ~_BV(BODSE); MCUCR = mcucr1; MCUCR = mcucr2; sei(); //ensure interrupts enabled so we can wake up again sleep_cpu(); //go to sleep //----zzzz----zzzz----zzzz----zzzz cli(); //wake up here, disable interrupts sleep_disable(); wdtDisable(); //don't need the watchdog while we're awake sei(); //enable interrupts again (but INT0 is disabled above) if (++wdtCount < wdtLimit) { keepSleeping = true; if (WAKE_INDICATOR_HI_MS > 0) { makeTone(WAKE_INDICATOR_HI_MS); //briefly blink an LED so we can see the wdt wake-ups } } else { keepSleeping = false; } } while (keepSleeping); msWakeUp = millis(); } ISR(WDT_vect) {} //don't need to do anything here when the WDT wakes the MCU //enable the WDT for 8sec interrupt void wdtEnable(void) { wdt_reset(); cli(); MCUSR = 0x00; WDTCR |= _BV(WDCE) | _BV(WDE); WDTCR = _BV(WDIE) | _BV(WDP3) | _BV(WDP0); //8192ms sei(); } //disable the WDT void wdtDisable(void) { wdt_reset(); cli(); MCUSR = 0x00; WDTCR |= _BV(WDCE) | _BV(WDE); WDTCR = 0x00; sei(); }