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.