Buttons on separate interrupt pins work fine (triggered on FALLING), bouncing is handling by forcing a 80ms lockout period during which further presses are ignored. I like that solution for being lightweight.

My goal is to have 1 interrupt handle all events (buttons and other digital inputs). I don't want to depend on loop(), I wish to be free to use delay often rather than timer interrupts.
Most buttons execute an action when pressed, some, while pressed.

What I have now (just 2 buttons for now):


simulate this circuit – Schematic created using CircuitLab

void setup() {
  pinMode(17, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(3), wotHappnd, CHANGE);

boolean isDebouncing(){
  unsigned int now = millis();
  if(now - time_lastPressed > time_debounceLockout){
    time_lastPressed = now;
    return false;
  return true;

void wotHappnd(){
  boolean interruptFalling = digitalRead(3) == LOW;
  if(interruptFalling && isDebouncing()) return;
  // digitalRead the pins; do stuff

Internal pullups on all used pins.

My problem is that often (~4%), on interrupt, the interrupt pin is LOW all button pins are HIGH ("not pressed" - likely bouncing just as I read it). How to fix that?

Can't use delay during an interrupt; delayMicroseconds to wait for stable readout still feels inappropriate; a cap-based delay on the interrupt pin induces a period of floating. Prefer solutions in software or with no more than 1 extra component per input.

[edit] here's a claim that pin interrupts do some filtering already, which, if true, may make some solutions unreliable.

  • Can't you catch the button being pressed on the next bounce? Since the button bounces a few times, there should be one where it's LOW for long enough to catch. So in the code, you'll have to check if one of the buttons is pressed, before calling the isDebouncing function. – Gerben Jan 30 '17 at 21:33
  • @Gerben It's a common debounce for all buttons. Sufficient for me. So, you're suggesting I do digitalRead in a loop until I get a LOW somewhere? – kaay Jan 30 '17 at 21:41
  • No. Do two digital reads for the two buttons in the ISR. If both are high, do nothing. Otherwise execute the code you now have in the ISR. – Gerben Jan 30 '17 at 21:49
  • Oh. Still, is it certain that a bouncing button will trigger effloads of interrupts? I'm asking because I read somewhere (Electrical Engineering StackExchange?) that there is already some signal stability assurance done on interrupts in some microcontrollers, to prevent exactly that. Plus, I have no idea what impact the diodes or other connected pins may have here, if any. – kaay Jan 30 '17 at 22:03
  • 1
    I think you will find that in the end, thee best software debounced is none- a capacitor plus a resistor (or a terrible switch) will do wonders here. – dannyf Jan 30 '17 at 22:19

In the Isr, read the two pins and maintain their current status (UN debounced), and reset a counter.

In the main loop, increment that counter. If it is more than a certain number, it means that the current state of the key has been stable for a while - bounce no more.

Or Google Kuhn debounced. I wrote a blog page about that. If you want, I can post it later. The basic idea is the same.

  • Thanks of reminding me of Kuhn debounce. Too bad it needs polling in main loop, which I don't want to do. Polling without delay won't produce the same result... maybe polling on a timer interrupt? Hmm... – kaay Jan 30 '17 at 21:52
  • 1
    The approach I suggested is essentially the Kuhn debounced, without polling the buttons. Instead, you increment a counter as a way to detect stabilized buttons. – dannyf Jan 30 '17 at 22:05
  • Sorry, I misunderstood before. Still, what puts me off is dependence on the main loop being free of long delays. Also, any idea about what's in the 4th comment under the question? Won't there be fewer CHANGE interrupts than changes on the (non-interrupt) button pin? – kaay Jan 30 '17 at 22:17
  • 1
    There is no requirement for the main loop to have any delays, long Orr short – dannyf Jan 30 '17 at 22:21
  • Any solution using loop() needs loop() to NOT have long delays. Kuhn repeats 10 times per second. Arduino is a prototyping platform - perfection is reserved for later, and in the meantime I tune my signal generation using delay. – kaay Jan 30 '17 at 22:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.