Attiny85 hangs? Sleep mode, Watchdog timer, Interrupt

Dear people,

I’m working on a device that runs from a cell battery and has a buzzer and 1 button. The processor I use is Attiny85V. The schematic is very simple: Port 1 is connected to the buzzer and port 2 connected to a switch (switch to ground). All inputs (also unused) are internally pulled-up. When battery is connected the device starts in ‘On’ state, which means it will buzz randomly every ±10 minutes. When pressing the button shortly, it will switch off. Press-and-hold the button will switch to a higher level (1,2 or 3), which means the buzzing intervals will go up (from ±10 to 15 or 20 minutes).

When not buzzing, the device is in sleep mode, and wakes-up by a Watchdog timer. When pressing the button in sleepmode, the INT0 (same pin as port 2) gets the device out of sleep.

My problem: Sometimes the device seems to ‘hang’. It is not doing anything, doesn’t react on button press. It will only go back to normal after I disconnect battery.

Anyone there to help looking for the problem?

Is it maybe the part in setup where I switch-off the ADC to save power? Or do I make a mistake with the Interrupt? I’m not really good in programming, so forgive me for stupid mistakes I have made… ::slight_smile:

Many thanks - Steven

main_code_revE_debug.ino.ino (6.8 KB)

Probably easier if I put the code in the message… These are the important parts:

Watchdog setup :

//This runs each time the watch dog wakes us up from sleep
ISR(WDT_vect) {
  //Don't do anything. This is just here so that we wake up.

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

Setup and wake-up function:

void wakeUpNow(){        // here the interrupt is handled after wakeup

void setup()
  justSwitched = LOW;
  pinMode(BuzzPort, OUTPUT);       //This is where the buzzer is connected
  pinMode(SwitchButton, INPUT_PULLUP); //This is where the switch is connected
  pinMode(0, INPUT_PULLUP); //just to keep them high
  pinMode(3, INPUT_PULLUP); //just to keep them high
  pinMode(4, INPUT_PULLUP); //just to keep them high
  pinMode(5, INPUT_PULLUP); //just to keep them high
  //Power down various bits of hardware to lower power usage  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything, wake up from WDT
  ADCSRA &= ~(1<<ADEN); //Disable ADC, saves ~230uA


Main sleep and wake-up code:

  //******* This is the main sleep code *********//
       setup_watchdog(9); //Setup watchdog to go off after 8sec
       attachInterrupt(0, wakeUpNow, LOW);
       sleep_mode(); //Go to sleep! Wake up 8sec later

       sleep_disable();                       // first thing after waking from sleep: disable sleep...

Hope this makes it easier to help. Thx again!