Debounce on an external interrupt.

OK, be gentle, I'm completely new to electronics and microcontrollers. :)

I've followed the example for Debounce, and it works just fine. But what my project needs is to count the number of times an external interrupt is triggered. I set up my sketch to simply increment a counter each time the interrupt was triggered, (testing with a push button - will switch to photo-interrupter for actual project), and in the main loop send this counter out to the serial port when it changes. This should give me a reading that increments by 1 each time the button is pushed, but it varies. Sometimes it gives two counts per push, sometimes the interval is greater than 1, etc. My assumption is that I have bounce, but since millis() doesn't work in an interrupt function, I don't know how to cure this.

Will a photo-interrupter suffer the same bounce issues as a simple push button?

Hi Dave,

You should be ok with a photo-interrupter, give it a try. In the unlikely event that it does bounce there are some hardware things you can do, but I would expect you won't need to resort to that.

Thanks mem! Unfortunately I have to wait for my photo-interrupter to arrive, and I'm impatient! :(

What kind of hardware things are you suggesting? Simple components, or an extra IC kinda thing? Just curious, and trying to expand my limited knowledge. :)


If you called it prudently, why wouldn’t millis() work in an interrupt handler? I can certainly see how you would want to avoid a call to delay() or repeated calls to millis(), but it seems to me that code like this would work:

void my_interrupt()
  static unsigned long last_millis = 0;
  unsigned long m = millis();
  if (m - last_millis < 200)
   { // ignore interrupt: probably a bounce problem }
   { // do pushbutton stuff }
  last_millis = m;

The millis() function, after all, is just performing a simple calculation based on a counter. That counter will never be updated during the interrupt, but it should be correct upon entry into it.


I tried it, not exactly as you have listed, but by calling millis() just once in the interrupt function, and it didn't help. I don't have the exact code I tried, so I may have been doing something wrong. Off to give it a go with your code! Thanks!!

Oh, and I found a photo-interrupter to try, but it's signal voltage only seems to be 1.5V, and it's not triggering the interrupt.

Try to make your interrupt routine as short as possible. In particular, avoid calling Serial.print from within the interrupt itself, as this adds enormous delays. I have found that a good strategy is to simply set a couple of flags or variables in the interrupt routine and then "process" this information in the "normal" loop code later.

Good luck!


Thanks Mikal! My interrupt was originally just 'counter++;' I tried using millis() and had the last_millis variable declared globally. (I think, like I said, I didn't keep the code.)

I've used your code suggestion and it works, within the limitations of the pushbutton*. So now I can rule out the code and the microcontroller, and concentrate on a better trigger. But this was only a test bed and I'll use a photo-interrupter when I go live.

Thanks again to you both for your help!


*The problem with the pushbutton I was using is that if I had the attachInterrupt mode set to RISING, (as I want it to be), and held the button in for any length of time, then releasing the button would also trigger the interrupt, because now the bounce is happening well after the delay. If I set it to CHANGE this was no longer a problem, (and I could divide my count by 2), but it was possible to put slight brief pressure on the switch, not enough for it to click. This would then beat the 200 mS bounce and I'd get one count instead of 2. Neither of these is a real problem for my application, just thought I'd throw it out there as an FYI for anyone else who might dig this up at a later date.

You can debounce using a resistor and capacitor, here is one way to do it

BTW, millis() returns a counter that is incremented by timer0 interrupts. So a loop that calls millis from within an interrupt handler will always return the same value because the Arduino environment is set up to disable interrupts from within an interrupt handler. But if you store the millis value on each interrupt call you could get the debounce code to work that way.

edit, I see you got it working while I was composing my reply :)

Thanks for the link mem. I’m going to add it to my list of things I should know as I delve deeper and deeper into this stuff. I’m hooked!!