Pin Change Interrupts debounce
-
Hi,
MY GW is flooded with messages as I am using pin change interrupt.
How do I debounce it please? sleep() does not workISR (PCINT0_vect) { // handle pin change interrupt for D8 to D13 here } // end of PCINT0_vect ISR (PCINT1_vect) { // handle pin change interrupt for A0 to A5 here } // end of PCINT1_vect ISR (PCINT2_vect) { // handle pin change interrupt for D0 to D7 here } // end of PCINT2_vect void setup () { // pin change interrupt (example for D9) PCMSK0 |= bit (PCINT1); // want pin 9 PCIFR |= bit (PCIF0); // clear any outstanding interrupts PCICR |= bit (PCIE0); // enable pin change interrupts for D8 to D13 }
-
@alexsh1 debounce must be done in the loop. The ISRs must execte quickly, so no debouncing can be done there.
-
@mfalkvidd Ok, thank you. How exactly do I do that? I cannot use sleep() to debounce as it will be interrupted.
-
@alexsh1 how to do it would depend entirely on how the node is supposed to function. Could you describe what triggers the interrups and how you would like them to be handled?
-
This is the most of the loop function I have apart from sleep.
if (IRQHigh) { send(msg.set("1")); IRQHigh = false; }
-
@alexsh1 how about adding global variables for all interrups like this
volatile unsigned long lastInterruptD1 = 0; volatile unsigned long lastInterruptD2 = 0; ...
and inside the ISRs set the corresponding variable to millis() like this
lastInterruptD1 = millis();
and in loop have a series of
if(lastInterruptD1 != 0 && millis()-lastInterruptD1 > DEBOUNCE_MS){ lastInterruptD1 = 0; // Do whatever the interrupt does here }
You could use an array instead of individual variables to make the code cleaner, especially if you want to cover a lot of pins. Which board/Arduino are you using?
-
@mfalkvidd it is a custom made board using atmega328p-au with sensebender bootloader running at 8Mhz and 3.3V.
I'll try the above, however, does millis() work while sleeping?
-
@alexsh1 it will return the last value, but it will not increment. That's one of the reasons ISRs should exit quickly.
-
@mfalkvidd
Want to share what I found in case others have a similar issue.const unsigned long debounceTime = 50; volatile bool ir_selector_pressed = false; ISR (PCINT2_vect) { // handle pin change interrupt for D0 to D7 here static unsigned long previousStateChangeMillis = 0; static bool previousPinState = HIGH; bool pinState = digitalRead(SELECTOR_BTN); if (pinState != previousPinState) { // ignore pin changes of pins other than SELECTOR_BTN if (pinState == LOW) { // only falling events if ((millis() - previousStateChangeMillis) > debounceTime) { // debounce ir_selector_pressed = true; } } previousPinState = pinState; previousStateChangeMillis = millis(); } }```
-
Another way to debounce is to stop interrupts in loop, sleep for say 20 seconds and then resume interrupts.
-
@alexsh1 this is in general a bad idea, as it will also stop eg reception of serial data and incoming packages (when using message queuing).
-
@yveaux you mean stopping interrupts?
-
@alexsh1 yup
-
@yveaux What is the best way to do it please?
-
@alexsh1 The easiest way would probably use a debounce-library.
These normally aren't using interrupts, but you have to question yourself if you really need interrupts in your case.I don't have any readymade, tested code which uses interrupts and debounces switches.
-
@yveaux said in Pin Change Interrupts debounce:
@alexsh1 The easiest way would probably use a debounce-library.
I'll look into that. Thank you