Interrupts and Bouncy buttons. How to Solve??

Hey All,
I’d like to use the AttachInterrupt to enter a menu type mode when a button is pressed, interrupting a repeating pattern of LED’s blinking.

The problem I’m having is that the button bounces. I can’t put a delay to wait for teh button to become stable in the function that the interrupt calls, because the bouncing button even causes the delay function to be interrupted.

I’ve read that you can debounce a switch using a schmitt-trigger, but I don’t have any room on my board to add another IC unfortunately.

Is there a hardware or software method I can use to get this interrupt to work reliably?

it seems like it SHOULD be possible with software…

have the interrupt trigger when the button goes LOW and call a function with a delay in it. The delay waits 10MS to make sure that the button is stable LOW, then does some stuff.

Mike

Could you have the interrupt fire when the button first presses, then instead of callcing delay() for a period, DISABLE altogether interrupts for the smae amount of time? This would mean that the bouncing interrupts would be ignored, then you can re-enable interrupts in time to catch the next push.

Not sure how this would affect other bits of your code that may also rely on interrupts e.g. PWM. There is a lot of discussion somewhere on the forums in relation to this.

Could you have the interrupt fire when the button first presses, then instead of callcing delay() for a period, DISABLE altogether interrupts for the smae amount of time? This would mean that the bouncing interrupts would be ignored, then you can re-enable interrupts in time to catch the next push.

Not sure how this would affect other bits of your code that may also rely on interrupts e.g. PWM. There is a lot of discussion somewhere on the forums in relation to this.

Even better than this would be to disable only the interrupt tied to the button for a duration that’s longer than the bouncing period.

  • Ben

I don’t think you need to disable the interrupt, just recognize if you are waiting for a previous buttons bounce time. I think the following will work.

#define BOUNCE_DURATION 20 // define an appropriate bounce time in ms for your switches

volatile unsigned long bounceTime=0; // variable to hold ms count to debounce a pressed switch

void intHandler(){
// this is the interrupt handler for button presses
// it ignores presses that occur in intervals less then the bounce time
if(millis() > bounceTime)
{
// Your code here to handle new button press ?
bounceTime = millis() + BOUNCE_DURATION; // set whatever bounce time in ms is appropriate
}
}

Note, the attachInterrupt documentation says that millis() wont work in an interrupt handler. Looking at the millis() function in wiring .c, it appears it will return the most recent millis reading, but it will not be incremented while in the handler, which is ok for this solution

1 Like

Being a hardware sort of bloke I would simply put a capacitor across the push button. It’s not too critical but a 0.1uF usually does the trick. That way you solve the problem at source.

Being a hardware sort of bloke I would simply put a capacitor across the push button. It’s not too critical but a 0.1uF usually does the trick. That way you solve the problem at source.

Hi Mike, I guess if you are a hardware guy then soldering a capacitor would seem is easier than adding two lines of code :wink:

[quote
Hi Mike, I guess if you are a hardware guy then soldering a capacitor would seem is easier than adding two lines of code :wink:

Every time ;Dhttp://www.arduino.cc/yabbfiles/Templates/Forum/default/grin.gif

Being a hardware sort of bloke I would simply put a capacitor across the push button. It’s not too critical but a 0.1uF usually does the trick. That way you solve the problem at source.

I think this solution would depend on what your entire circuit looks like. Without a pre-specified R part of the RC filter, the timescale of your capacitor’s discharge (e.g. microseconds) could potentially be much shorter than the timescale over which the button bounces (e.g. milliseconds). Just something to watch out for.

  • Ben

Thanks for this elegant solution mem it works ace,
however I’m wondering if the button will stop being responsive once millis() overflows in under 10 hours? I’m guessing the solution is to set bounceTime back to 0 at some point in the script, just not sure where.

Mike

I don’t think you need to disable the interrupt, just recognize if you are waiting for a previous buttons bounce time. I think the following will work.

#define BOUNCE_DURATION 20 // define an appropriate bounce time in ms for your switches

volatile unsigned long bounceTime=0; // variable to hold ms count to debounce a pressed switch

void intHandler(){
// this is the interrupt handler for button presses
// it ignores presses that occur in intervals less then the bounce time
if(millis() > bounceTime)
{
// Your code here to handle new button press ?
bounceTime = millis() + BOUNCE_DURATION; // set whatever bounce time in ms is appropriate
}
}

Note, the attachInterrupt documentation says that millis() wont work in an interrupt handler. Looking at the millis() function in wiring .c, it appears it will return the most recent millis reading, but it will not be incremented while in the handler, which is ok for this solution

1 Like

To avoid the millis reset problem you could do something like this:

#define BOUNCE_DURATION 20   // define an appropriate bounce time in ms for your switches
 
volatile unsigned long bounceTime=0; // variable to hold ms count to debounce a pressed switch
 
void intHandler(){  
// this is the interrupt handler for button presses
// it ignores presses that occur in intervals less then the bounce time
  if (abs(millis() - bounceTime) > BOUNCE_DURATION)  
  {
     // Your code here to handle new button press ?
     bounceTime = millis();  // set whatever bounce time in ms is appropriate
 }
}

I think this solution would depend on what your entire circuit looks like. Without a pre-specified R part of the RC filter, the timescale of your capacitor’s discharge (e.g. microseconds) could potentially be much shorter than the timescale over which the button bounces

  • Ben

No the discharge time is almost instant because the switch pulling to ground shorts out the capacitor and discharges it. All you have to worry about then is the charge time set by the capacitor and the pull up resistor (or current supplied by the floating high input pin). This gives a time constant typically of 330uS (with a 3.3K pull up). Any bounce occurring discharges the capacitor and the time starts again. In my experience this is usually works. However looks like the fear of soldering has won out on this occasion. ::slight_smile:

  • Ben[/quote]
    However looks like the fear of soldering has won out on this occasion. ::)[/quote]

I don’t think there’s too many people on the arduino forum that have a fear of soldering. That being said… after trying a .1uF cap, I was still getting bouncing occasionally. Simply using a capacitor is also not recommended here (How to debounce a switch)