ATtiny doesn't wake up from PWR_DWN on INT0 interrupt

Hi, the software below is working properly except one thing. The INT0 interrupt is being detected but it isn't enough to wake the up ATtiny24A. On the contrary, pin change interrupt can wake up the MCU.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

volatile uint8_t state; //1: idle     2: to be armed     3: armed/to be rang/ringing
volatile int armDelay = 60;
volatile int alarmDelay;
volatile int alarmDuration;

volatile int counter;

volatile bool flagBUT = false;
volatile bool flagPIR = false;
volatile bool flagTIM = false;

#define LEDButtonPin PA3
#define BuzzerPin PA4
#define AlarmPin PA5
#define PotEnablePin PA2
#define PIRPin PB2
#define ButtonPin PA6
#define pot_DEL_pin PA0
#define pot_DUR_pin PA1
#define FlashorPin PA7

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


void setup() {
  //Timer 1:
  TCCR1A = (0 << WGM11) | (0 << WGM10);
  TCCR1B = ((0 << CS10) | (0 << CS11) | (0 << CS12)) | (1 << WGM12) | (0 << WGM13) | (0 << ICNC1) | (0 << ICES1); //Set CTC by WGM = 0100

  TIMSK1 |= (1 << OCIE1A); //Timer/Counter1 Overflow interrupt is enabled
  OCR1A = 15624;

  //Pin Def:
  DDRA |= (1 << LEDButtonPin) | (1 << AlarmPin) | (1 << FlashorPin) | (1 << PotEnablePin) | (1 << BuzzerPin); //Set "A" output pins
  PORTA &= ~((1 << LEDButtonPin) | (1 << AlarmPin) | (1 << FlashorPin) | (1 << PotEnablePin) | (1 << BuzzerPin)); // Set the outputs LOW
  DDRA &= ~((1 << ButtonPin) | (1 <<  pot_DUR_pin)| (1 <<  pot_DEL_pin)); // Set "A" input pins
  DDRB &= ~((1 << PIRPin) | (1 << PB0) | (1 << PB1) | (1 << PB3)); // Set "B" input pins
  PORTB |= (1 << PB0) | (1 << PB1) | (1 << PB3); // Set internal pullups for "B" pins
  DIDR0 |= (1 << ADC0D); // Digital input 0 disable to save power
  DIDR0 |= (1 << ADC1D); // Digital input 1 disable to save power
  
  //Turn on pin change interrupt:
  sbi(GIMSK, PCIE0);
  PCMSK0 |= (1 << PCINT6);

  //Turn on dedicated PB2 interrupt:
  MCUCR |= ((1 << ISC01) | (1 << ISC00)); // Rising EDGE
  GIMSK |= (1 << INT0); //INT0

  sei(); //enable global interrupt
  cbi(ADCSRA, ADEN); //Switch ADC off

  Led (1);
  beep(1, 100);
  flagBUT = 0;
  state = 1;
}

ISR(PCINT0_vect) { // button interrupt
  if (digitalRead(ButtonPin) == 1) flagBUT = true;
}

ISR(INT0_vect) { // sensor interrupt
  flagPIR = true;
}

void loop() {
  if (flagBUT || flagPIR || flagTIM) {
    if (flagBUT) {
      delay(200);
      flagBUT = false;
      if (state == 1) state = 2;
      else state = 1;
    }

    switch (state) {
      case 1:
        timer(false);
        alarm(0);
        Led (1);
        beep(1, 100);
        flagTIM = false;
        break;

      case 2:
        counter = armDelay;
        timer(true);
        beep(1, 500);
        while (!flagTIM) {
          Led(1);
          delay(1000);
          if (flagBUT) return;
          Led(0);
          delay(1000);
          if (flagBUT) return;
        }
        flagTIM = false;
        PORTA |=  (1 << PotEnablePin);
        sbi(ADCSRA, ADEN); // Switch ADC on
        delay (100);
        alarmDelay = 10; //supposed to be ADC read but didn't work
        alarmDuration = 10; //supposed to be ADC read but didn't work
        cbi(ADCSRA, ADEN); //Switch ADC off
        PORTA &= (0 << PotEnablePin);
        beep(2, 100);
        state = 3;
        flagPIR = false;
        while(!flagPIR);//sleep();
        break;

      case 3:
        flagPIR = false;
        counter = alarmDelay;
        timer(true);
        beep(3, 80);
        while (!flagTIM) {
          Led(1);
          delay(200);
          Led(0);
          delay(200);
          if (flagBUT) return;
        }
        flagTIM = false;
        alarm(1);
        counter = alarmDuration;
        timer(true);

        while (!flagTIM) {
          //flash the flashor
          flashor(true);
          delay(100);
          flashor(false);
          delay(100);

          if (flagPIR) {
            counter = alarmDuration;
            flagPIR = false;
          }
          if (flagBUT) return;
        }
        flagTIM = false;
        alarm(0);
        beep(2, 100);
        sleep();
        break;
    }
  } else sleep();
}

ISR(TIM1_COMPA_vect)
{
  counter--;
  if (counter <= 0) {
    flagTIM = true;
    timer(false);
  }
}


void timer(bool command1) {
  if (command1)
  {
    TCNT1H = 0; TCNT1L = 0;
    TCCR1B |= (1 << CS11) | (1 << CS10);
    TCCR1B &= ~(1 << CS12); //set prescaler
  }
  else {
    TCCR1B &= ~((1 << CS10) | (1 << CS11) | (1 << CS12));
  }
}

void beep (uint8_t repeat, uint16_t interval) {
  for (int i = repeat; i > 0; i--) {
    PORTA |=  (1 << BuzzerPin);
    delay(interval);
    PORTA &= ~(1 << BuzzerPin);
    if (i > 1) delay(interval);
  }
}

void alarm(bool on_off) {
  if (on_off == 1) {
    PORTA |=  (1 << AlarmPin);
  } else {
    PORTA &= (0 << AlarmPin);
    flashor(false); // turn off flashor
  }
}

void flashor(bool on_off_2) {
  if (on_off_2) PORTA |= (1 << FlashorPin);
  else PORTA &= ~(1 << FlashorPin);
}

void Led (uint8_t  ledmode) {
  if (ledmode) PORTA |= (1 << LEDButtonPin);
  else PORTA &= (0 << LEDButtonPin);
}

void sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
  sleep_enable();
  sleep_mode(); //System sleep
  sleep_disable();
}

Let's focus on the relevant parts in the code:

//In the setup we have:
//Turn on pin change interrupt:
  sbi(GIMSK, PCIE0);
  PCMSK0 |= (1 << PCINT6);

  //Turn on dedicated PB2 interrupt:
  MCUCR |= ((1 << ISC01) | (1 << ISC00)); // Rising EDGE
  GIMSK |= (1 << INT0); //INT0

  sei(); //enable global interrupt

//In the loop we have:
while(!flagPIR);//sleep();
// works perfect if while loop is used but if I uncomment sleep part and delete while, MCU doesn't // wake up

//my interrupt vectors:
ISR(PCINT0_vect) { // button interrupt
  if (digitalRead(ButtonPin) == 1) flagBUT = true;
}

ISR(INT0_vect) { // sensor interrupt
  flagPIR = true;
}

There is also "pin change" interrupt which successfully wakes the MCU up, the only problem is with the INT0 (PB2) interrupt. Can you help me correctly configure the INT0 interrupt and make it wake the MCU up? Thanks.

Datasheet ATtiny24A

The rising or falling edge can't be detected on PWR_DWN this caused the problem. I'm having different problems now, I will create another thread if I can't solve it.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.