Getting Pin Change Interrupts working together with Timer interrupts / sleep(XX ms) on Arduino Pro Mini
-
@Joost as documented it can be roughly 8 seconds off on avr. When an avr is set to sleep for 8 seconds (the maximum watchdog sleep time) and it is woken by an interrupt, it will not know how much time is remaining and always return the same time remaining.
Try sleeping for a minute, then interrupt after 1 second and after half a minute. The remaining time should be different.@Yveaux & others:
So this works great! Here is an example sketch to get Pin Change Interrupts working together with timer-based sleep(). There will be identification of the triggered pin as well as discrimination between rising and falling edge. To test, just add a jumper wire to pin A1 or/and A2 to a Arduino Pro Mini and short it to Ground to wake the Arduino out of a timed sleep() (a connected Radio, here a RFM95, is needed to get the sketch started).#include <Arduino.h> #define MY_RADIO_RFM95 #include <MySensors.h> volatile int isrcounter = 0, timercounter=0; volatile char PinRegLast, ChangedPin, PinRegister; volatile boolean isr_interrupted; uint32_t remainingSleepTime = 0; ISR(PCINT1_vect) { PinRegister = PINC; ChangedPin = PinRegister ^ PinRegLast; PinRegLast = PinRegister; _wokeUpByInterrupt = 0xFE; isr_interrupted=true; isrcounter++; } void setup() { noInterrupts(); PCICR |= 0b00000011; // Enables Ports B and C Pin Change Interrupts PCMSK1 |= 0b00000110; //PCINT9 & PCINT10 = A1 & A2 PCIFR = B00000001; // Reset Interruptflag pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP); PinRegister = PINC; interrupts(); Serial.begin(38400); } void presentation() {} void loop() { noInterrupts(); if ( isr_interrupted ) { isr_interrupted = false; switch (ChangedPin){ case (1 << PINC1): if (~PinRegister & (1 << PINC1)) { Serial.print("Interrupted / Woken up by Pin A1, remaining sleep() time: "); remainingSleepTime = getSleepRemaining(); Serial.println( remainingSleepTime );} else { Serial.println("Falling edge of Pin A1"); } break; case (1 << PINC2): if (~PinRegister & (1 << PINC2)) { Serial.print("Interrupted / Woken up by Pin A2, remaining sleep() time: "); remainingSleepTime = getSleepRemaining(); Serial.println( remainingSleepTime );} else { Serial.println("Falling edge of Pin A2"); } break; default: break; interrupts(); } } else { interrupts(); Serial.println("Timer wake up / Loop"); timercounter++; } Serial.print(" "); Serial.print(" ISR Counter: ");Serial.print(isrcounter); Serial.print(" Timer counter: "); Serial.println(timercounter); sleep((uint32_t) 60*1000); }Thanks a lot! Joost
-
@Joost I like your solution to be able to use other pins as pin change interrupts together with Timer interrupts in the MySensors library.
I did use the default sleep function of MySensors with the foreseen D1 and D2 pins where D1 is already taken by the radio, so only D2 is usable for custom use.
See https://www.mysensors.org/download/sensor_api_20#sleeping -
I think this is the same thing as you were trying to accomplish.
Sleep for 6 minutes or when interrupted. I have a reed switch on pin 2
pinMode(REED_SWITCH, INPUT); // set the reed switch digital pin as input //digitalWrite(REED_SWITCH, HIGH); pinMode(REED_SWITCH, INPUT_PULLUP);sleep(digitalPinToInterrupt(REED_SWITCH), CHANGE, 360000); //3600000 hour