Debouncing Push Buttons

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

Hi,
i am trying to debounce this momentary push buttons. How can this be done through software ?

I've one way which is to use a interrupt which detects edge changes( eg : 1 to 0 or 0 to 1) and also check whether are the last change was more than n seconds. And depending on a predefined n seconds to determine whether is it a genuine push of the button.

Is there any algorithm or way to do debouncing ?

cheers :roll:

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

theres a few methods, heres one I know the link of
http://www.avrtutor.com/tutorial...

uses a timer I think! :X

Ill see if I can find more and post back.

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

bckhor wrote:
Hi,
i am trying to debounce this momentary push buttons. How can this be done through software ?
...
Is there any algorithm or way to do debouncing ?

Yes.

http://www.mikrocontroller.net/a...

Peter

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

You have to use some sort of delay scheme if you're dealing with buttons.
If you use a rotary switch this can be avoided, but they are a bit more expensive...

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

thanks guys , ill have a look and try !
cheers

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

A really good tutorial on debouncing is at:
http://www.ganssle.com/debouncing.pdf
Best regards,
heinrichs.hj

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

coming back to using interrupts to determine the rising edge of the switchs. How much delay between edges should i use in order to determine whether the push of the button is a genuine one ?

Because i've seen many codes, they use x miliseconds. Is there a more robust way that doesn't use delay and can be used for generally any switches ?

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

Personally I'd only use the interrupt to wake the AVR from deep sleep but then, once awake, disable that interrupt source and poll the pin in a timer ISR to do the debounce.

Cliff

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

is there any adaptive approach ?

i thought of like
1.polling the switch to detect a change first
2. intialise a counter
3. poll the switch again
- if there is a change , go back to step 2
- else continue to decrement counter
4. when counter is 0 , switch is consider pressed.

is there any flaw in doing this technique of debouncing ?

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

Are you aware of the "debounce bible"?

http://www.ganssle.com/debouncin...

No point reinventing the wheel on an age old problem like debounce when someone has already done all the leg work for you!

Cliff

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

Usually/often/nearly always in my apps there will be a bunch of buttons and switches and input signals to gather and debounce on a continual basis. So most of us us a parallel method to do 8 or 16 at a time, and implement a kind of "pipeline" to do the equivalent of your "counting".

First, study the Ganssle paper given in the link earlier.

Then, do some searching here. (Yes Search is broken so use Google with "site:www.avrfreaks.net") Here are a couple of recent threads that have both danni's and my pet routines:
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

Lee

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

Switches bounce a couple of times for a couple of ms, so one algorithm would be read switch, if pushed, read again after 10ms, see if they agree. If the program ran about 10ms per loop, you could save the value and come back next pass and read the second time.

Imagecraft compiler user

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

clawson wrote:
Personally I'd only use the interrupt to wake the AVR from deep sleep but then, once awake, disable that interrupt source and poll the pin in a timer ISR to do the debounce.

That approach has worked well for me. You didn't mention it, but I imagine you give an sei() command after disabling the interrupts.

My PinChangeInterrupt-driven debouncing code looks like:

ISR(PCINT3_vect) {
  disable_pin_interrupts();
  sei();
  // perform polling using timer0 15ms ticks
  // timeout polling loop after 45 ms 
  // loop and update button status for all buttons
  // maintain states of PUSHED, NO_PUSH, MAYBE_PUSH, MAYBE_NO_PUSH
  // for each button
  // break loop for any change to PUSHED OR NO_PUSH status
  // store any pushed buttons in input buffer
  enable_pin_interrupts();
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevin,

Nope that's not quite what I meant as I don't like being inside the ISR that long - though I realise it's not such a problem if you sei().

I'd just have the (always ticking) timer interrupt watching the buttons and doing the stages of the debounce thing on each tick.

Then I'd only use the pin change interrupt for the wake up (and I'd have your disbale_pin_interrupts() in there) but the only time I'd ever call the enable_pint_interrupts() is just before the chip is put into deep sleep.

So it'll sleep away, a button will be pushed, cause the external interrupt (which is then immediately disabled) and now the thing is off and ticking again the timer stuff will take over to actually debounce the buttons.

Cliff

Last Edited: Wed. Mar 28, 2007 - 04:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, no, I'd never do a sequence such as you showed--hanging in an "unfinished" ISR for an indeterminate amount of time, re-enabling interrupts (stack effects!), re-enabling very likely causes a cascade 'cause the flag is very likely set for another go-round and you just nested yourself (ugly stack effects!).

Rather, the pin-change ISR is either empty, or merely disables itself. The only purpose is to wake the processor. Then, timers again take over and convenient tick times invoke switch raw state gathering and a multi-stage debounce.

Actually, if you are doing the "wake from sleep" thing there is one more thing that your ISR needs to do--sleep_disable(). The reason is that when you prepare to sleep the event could occur at any time before the processor actually starts sleeping--there is a race there. So I have all my wake-up ISRs disable the sleep_enable() and it is as if the processor actually has been awakened--it will fall right through the go_to_sleep() since sleep is disabled.

Lee

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

Cliff and Lee,

Thanks for the helpful thoughts. I think your suggestions to use the pinchangeinterrupt ISR just to wake the processor and get start the polling outside of the ISR is more robust than my approach.

I appreciate the wise suggestions.

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

cant you just use a resistor and a capasitor ?

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

Snovva, that's a very reasonable thoght. I think an RC filter would be fine. However, I'm debouncing 5 buttons. Seems more robust to avoid 10 discrete components and rather use some of the flash memory on this ATMega644 with some smart programming.

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

snovva wrote:
cant you just use a resistor and a capasitor ?

Do you have a schematic of that? I don't see how you could do it.

Go electric!
Happy electric car owner / builder

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

Sigh. Have >>any<< of you with questions followed the Ganssle link? I realize that ot was only posted twice in this thread, so I will put it here also:
http://www.ganssle.com/debouncin...

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

Quote:
Do you have a schematic of that? I don't see how you could do it.

Hello,

Page 12 in the link supplied shows an RC debouncer (the same link as someone else posted earlier).
http://www.ganssle.com/debouncin...
The charge/uncharging time is calculated using
t = R*C
if i'm not misstaken. The time t in seconds, resistance in Ohm and Capacitance in F. 10 - 20 ms should be ok. Some buttons come with a built in debouncer so that could be worth looking at. Also to protect against spikes you could put a diod from the point between R1 & R2 and connect the + to side of the diod to VCC.

Take a look at the document supplied and you should be ok!

/Gert

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

Quote:
Do you have a schematic of that?
There are quite a few on my website, I don't have to worry about penny pinching for a few resitors and caps :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

ahhh I see. but this is not JUST a resistor and cap! The original post only mentioned an RC.

Go electric!
Happy electric car owner / builder

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

Quote:
but this is not JUST a resistor and cap
Depending on which board you looked at there may be more bits than necessary for just debouncing, but the basic debouncing is done by the 100K resistors and 100nF (some have 1uF) caps in the input pins. The rest of the bits in some boards are there for special use but normally not fitted.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly