Reliable button debouncing

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Up to now, I do button debouncing as shown below, but not reliable at all. I don't want increase the delay times, as it slow things down. Any other techniques that you can suggest? (I have seen hardware technique using electrolytic caps, basically to smooth out spikes, but I prefer the software approach.) Thanks!

if (bit_is_clear(BUTTON_INPUT_PORT, BUTTON2_PIN)) {
  _delay_ms(25);  // button debounce time

   // Check one more time.
   if (bit_is_clear(BUTTON_INPUT_PORT, BUTTON2_PIN)) {
     buttonPress = 1;  // button press detected
   }
}

// button lock delay
_delay_ms(100);

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This has lots of info -- http://www.ganssle.com/debouncing.pdf

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi unebonnevie,

instead of leaving the debounce time unused, you can check if the button is pressed in shorter time periods.
If it is pressed increment a counter. If the button seems not to be pressed clear the counter and restart counting.
If you overstep a specific value of the counter, than accept the button as pressed.
With this solution you will have a defined time where the press action must be at stable state.

The check time will always as short as possible, only dependent on the bouncing and your "check-for-stability"-time which is defined by the limit value of the counter.

( Instead of clearing the counter you can decrement it. This will increase the speed of the recognition, but you have no clear definition, when the button press should be accepted and it's more risky. )

A SUCCESSFUL day to all of you! ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think both Peter and Lee's solutions both use a timer interrupt to poll the button state. Try a search for "bounce peter lee" (all words) to find their "standard" solutions.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John,

Great minds - as I typed the above I was thinking "Peter, Lee... err ... Peters & Lee" - I guess only people who also know who Hughie Green was (http://en.wikipedia.org/wiki/Hughie_Green) will understand the relevance ;-)

Ciff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Peters & Lee

"Lee's Peter"? That would be a short tale.

I should keep a link to some of the more thorough debouncing threads. digging...
"debounce danni lee" is what I use.
The first hit has discussion, and links to prior:
https://www.avrfreaks.net/index.p...

Also https://www.avrfreaks.net/index.p...

You might have to keep digging back a few years to get code snippets. I remember one thread in particular had routines from several 'Freaks.

https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

Those links, and the links therein, should keep you busy for a while. ;)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, all! As usual, great help and suggestions!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a simple approach that may give you some ideas.

#define DBNC_CNT 100 /* pick a number that works */
if ( button_is_pressed() )
{
  int cnt = DBNC_CNT;
  while ( --cnt != 0 )
  {
    if ( !button_is_pressed() )
      cnt = DBNC_CNT;
  }
  Button_is_debounced = true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

"Lee's Peter"? That would be a short tale.

I might have a mind that is dirtier than your joke - but if I got the above right you almost perfected it, Lee. Shouldn't it be "a short tail... sort of...".

:D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Shouldn't it be "a short tail...

I did indeed leave that purposefully as an exercise for the reader.

And I did expect you to explore the ribald implications.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've debounced many ways - the latest one I just did for two buttons is as follows, and is not a new method...

Timer interrupt is used anyway for other reasons. For example 100Hz interrupt.

Debounce time choice: 1/20th second- nature of switches.

One up/down counter per switch, one byte each.
At each timer interrupt, if the button switch is closed (I/O port bit state) increment counter, else decrement counter. Do not increment past the debounce time choice, say, 1/20th second. Do not decrement if counter is zero.

Application level program checks counter, if zero then switch is closed. If > 0 but < debounce time count, switch may be bouncing and is ignored and checked later. If switch is == debounce time limit, switch is open. Or vice-versa for a norm. closed switch.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To add to stevech's method, if you your interrupt time and debounce time happen to be in a 1:8 ratio you can shift a 1 or 0 (current switch state) into the switch state variable. 0x00 means switch is closed, 0xFF switch is open, anything else, switch is bouncing. Can also do this with a 1:4 ratio by shifting in each bit twice.

Not better or worse, just a bit different.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One more question, mostly as a confirmation.

For AVR, which has internal pull-ups, I take that I don't need the 10k ohm pull-up for each of the buttons connected to the micro-controller's pins, correct? Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can omit the external 10k pull ups and enable the internal pull-ups, but there is a catch.

The internal pull-ups are not exact, they are something between 20k and 80k, but not less or not more.

It means that when you push a button, less current will flow through it.

As with every other component, pushbuttons have maximum rated current you may not safely exceed, but they may also have minimum ("wetting") current rating, which ensures that the contacts stay clean and do not oxidize and start to bounce even more.

If internal pull-ups are too weak to achieve the minimum current, you could put a capacitor there, which charges slowly but discharges rapidly, but then again the capacitor discharges only at one point and with large current if there is no resistor to limit it, so it may actually eat up the pushbutton metal, so if there is a capacitor, there should also be a limiting resistor, which is a nice filter.

But putting a resistor and capacitor is pointless if they can be omitted by putting a single pull-up resistor which can source the minimum wetting current.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The arkum-sparkum of live-current switching isn't the only contact-cleaning mechanism. Switch contacts that combine a "wiping" action with their make/break cycles will self-clean also. Or, just get yourself some nice mercury-wetted switches...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used the method as posted in the first post on several occasions and it has worked fine every time for me.

On first glance, your 25mS delay seems very low! The last two projects I worked on had a delay of 100mS - 150mS.

I got to this value by starting low and increasing the value until the bounce was gone and the action of the button felt correct. Around 100mS delay allows for quite rapid input into a 4x4 keypad. (gives you around half a second to tap in a four digit code).

Of course, the actual value will depend on the type of button.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Special_D wrote:
I have used the method as posted in the first post on several occasions and it has worked fine every time for me.

On first glance, your 25mS delay seems very low! The last two projects I worked on had a delay of 100mS - 150mS.

I got to this value by starting low and increasing the value until the bounce was gone and the action of the button felt correct. Around 100mS delay allows for quite rapid input into a 4x4 keypad. (gives you around half a second to tap in a four digit code).

Of course, the actual value will depend on the type of button.

I'll give it a try, increasing a little more time with my approach. So far, I have tried dani's method and the one from the PDF document, nothing works so far. Need to look into it.