Attiny85 sleeping malfunction

Hello Everybody! :slight_smile:
I am working on my project and I now got myself into trouble. I made a simple sketch to demonstrate the problem.

First of all I am using Arduino Uno to programme Attiny85 and I want it to make a sound for one second and then go to sleep for 8 seconds and repeat. I am using watchdog and pin change interrupts so whenever I push a button during sleeping the Attiny85 will stop making sound after every 8 seconds and instead a LED will blink after every 4 seconds. When LED is not on then Attiny85 is sleeping.

The problem is that from time to time (not always) Attiny85 will freeze in a spesific location. It is when I want to move on from making sound to blinking the LED. After I push the button the LED blinks once and then should go to sleep, but instead it freezes and never wakes up. Sometimes even the speaker goes wild if Tiny has frozen and I press the button.

The code:

#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management
#include <avr/wdt.h>      // Watchdog timer

volatile byte eventFlag;
int led = 0;
int speaker = 1;
int button = 4;
int nr = 1;
int reset = 3;

ISR (PCINT0_vect) 
 {
  eventFlag = 1;
 }  // end of PCINT0_vect
 
 // watchdog interrupt
    ISR (WDT_vect) {
       wdt_disable();  // disable watchdog
    }  // end of WDT_vect
void setup() {
  pinMode(led, OUTPUT);
    digitalWrite(led, LOW);
    pinMode(speaker, OUTPUT);
    pinMode(button, INPUT);
    digitalWrite(button, HIGH);
    digitalWrite(reset, HIGH);
    pinMode(reset, OUTPUT);
    // pin change interrupt (example for D4)
    PCMSK  = bit (PCINT4);  // want pin D4 / pin 3
    GIFR  |= bit (PCIF);    // clear any outstanding interrupts
    GIMSK |= bit (PCIE);    // enable pin change interrupts 
  }  // end of setup

void goToSleepSpeaker(){

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  noInterrupts ();       // timed sequence coming up
  // clear various "reset" flags
  MCUSR = 0;
  // allow changes, disable reset, clear existing interrupt
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  WDTCR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  // pat the dog
  wdt_reset();
  sleep_enable ();       // ready to sleep
  interrupts ();         // interrupts are required now
  sleep_cpu ();          // sleep
  sleep_disable ();      // precaution
  power_all_enable ();   // power everything back on
}  // end of goToSleep


void goToSleepLed(){

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  ADCSRA = 0;            // turn off ADC
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  noInterrupts ();       // timed sequence coming up
  // clear various "reset" flags
  MCUSR = 0;
  // allow changes, disable reset, clear existing interrupt
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
  // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  WDTCR = bit (WDIE) | bit (WDP3);    // set WDIE, and 4 seconds delay
  // pat the dog
  wdt_reset();
  sleep_enable ();       // ready to sleep
  interrupts ();         // interrupts are required now
  sleep_cpu ();          // sleep
  sleep_disable ();      // precaution
  power_all_enable ();   // power everything back on
}  // end of goToSleep

void loop() {

      int state = digitalRead(button);
    
      if ( eventFlag == 1 ) {
        if ( nr == 1 && state == LOW) {
          state = digitalRead(button);
          while ( state == LOW ) {
            state = digitalRead(button);
            delay(10);
          }
          nr = 2;
        }
        if ( nr == 2 && state == LOW) {
          state = digitalRead(button);
          while ( state == LOW ) {
            state = digitalRead(button);
            delay(10);
          }
          nr = 3;
        }
        eventFlag = 0;
      }//////////////////////////////////  this part was for handling the push of a button

if ( nr == 1 ) {
      digitalWrite(speaker, HIGH);
      delay(1000);
      digitalWrite(speaker, LOW);
      goToSleepSpeaker();
}  
if ( nr == 2 ) {
      digitalWrite(led, HIGH);
      delay(350);
      digitalWrite(led, LOW);
      goToSleepLed();
}      
if ( nr == 3 ) {
      delay(100);
      digitalWrite(reset, LOW);
    }
}

I think I got it working by adding wdt_disable(); after the sleep functions ( goToSleepSpeaker() and goToSleepLights() ). Not sure still why this helped me. :slight_smile:

1 Like