(Here is finally a solution).
I'm using the following code on a ATtiny45 to assign an interrupt to a button press (pin #7, PB2, INT0). However the LED doesn't blink when the button is pressed, as if the interrupt is not working. Why?
Note: I'd like to use the least power when no interrupt happens, to have a current in the order of magnitude of ~ 1 µA, to run from batteries for years.
#include <avr/sleep.h>
void setup()
{
pinMode(4, OUTPUT); // LED
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP); // pin #7 = PB2
digitalWrite(4, HIGH); delay(100); digitalWrite(4, LOW); // LED blink, working here
}
void wake()
{
sleep_disable();
detachInterrupt(0);
digitalWrite(4, HIGH); // LED not working here when pressing the button
}
void loop()
{
sleep_enable();
ADCSRA = 0;
attachInterrupt(0, wake, CHANGE);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_cpu();
}
Note:
I'm using Arduino IDE with damellis' attiny, I also tried with Spence Konde's ATtinyCore but it's the same
In my real code, I have 3 buttons, on pin #5, #6, #7, so eventually I'd like to have interrupts for all these three pins.
I've read https://gammon.com.au/forum/?id=11497 but using
noInterrupts()
/interrupts()
did not change anything in my case.I've tried "Sketch J" from https://gammon.com.au/forum/?id=11497 but
EIFR = bit (INTF0);
gives anerror: 'EIFR' was not declared in this scope
(I'm compiling from Arduino IDE); probably this works on an ATmega but not ATtiny.
Edit: Here is a working code of deep sleep, with an interrupt when the pin #5 (PB0) changes...
#include <avr/interrupt.h>
#include <avr/sleep.h>
ISR(PCINT0_vect) {
if (digitalRead(0) == LOW)
digitalWrite(4, HIGH);
else
digitalWrite(4, LOW);
}
void setup() {
pinMode(4,OUTPUT); // LED
pinMode(0,INPUT_PULLUP);
pinMode(1,INPUT_PULLUP);
pinMode(2,INPUT_PULLUP);
ADCSRA = 0; // ADC disabled
GIMSK = 0b00100000; // General Interrupt Mask Register, / Bit 5 – PCIE: Pin Change Interrupt Enable / When the PCIE bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin change interrupt is enabled. Any change on any enabled PCINT[5:0] pin will cause an interrupt. The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI Interrupt Vector. PCINT[5:0] pins are enabled individually by the PCMSK0 Register. / see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
PCMSK = 0b00000111; // Pin-change interrupt for PB0, PB1, PB2
}
void loop() {
sleep_enable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_cpu();
}
...but for an unknown reason, if I add this code:
ISR(PCINT1_vect) {
if (digitalRead(1) == LOW)
digitalWrite(4, HIGH);
else
digitalWrite(4, LOW);
}
the pin-change interrupt for PB0 still works (PCINT0), but not the interrupt for PB1 (PCINT1). Why?
sei()
or so?