Author Topic: what's your favorite switch debouncing method?  (Read 8476 times)

0 Members and 1 Guest are viewing this topic.

Offline slburrisTopic starter

  • Frequent Contributor
  • **
  • Posts: 542
  • Country: us
what's your favorite switch debouncing method?
« on: July 18, 2012, 02:57:25 pm »
I came across an article in this months Circuit Cellar talking about switch
debouncing, and it seemed overly complex to me.  Here's what I've done
in the past.

For a hardware based design, I feed a switch to the D input of a flip-flop
and continuously clock the FF at 50-100hz (obviously ground 1 input
of the switch and use a pull-up resistor on the other side of the switch which
goes to the FF).  Just pick the clock rate to have a period longer than it
takes the bouncing to die out.  Sure, there's a slight risk of metastability
issues, but you could just cascade a second FF on the output of the first
if you were really concerned about that.

In software, do something similar in that have a interrupt routine called
at 50-100hz, poll the switch, and put the result in memory somewhere.
Use the memory as the true state of the switch.

I've seen some hacks like putting capacitors across the switch, but that
just seems like a horrid design choice to me.

Any other good ways to do this?

Scott
 

Offline DaveW

  • Frequent Contributor
  • **
  • Posts: 284
  • Country: gb
    • WattCircuit
Re: what's your favorite switch debouncing method?
« Reply #1 on: July 18, 2012, 03:53:41 pm »
Use a changeover switch and feed into an RS latch is a preferred one for me, but for some reason I often have an RS latch left over. I do use the RC method, haven't had too many problems with it.
 

Offline andyg

  • Regular Contributor
  • *
  • Posts: 59
  • Country: au
    • gock.net
Re: what's your favorite switch debouncing method?
« Reply #2 on: July 18, 2012, 05:04:48 pm »
I remember using this post on Hackaday with all different debounce methods with sample code.

When i debounce in software, i have a systick timer running. I put the switches on a edge interrupt. Everytime ISR is triggered,  save the current systick somewhere and end of ISR, we check whether the "last trigger" time is within a defined debounce time period ago, if it is, then we know its bouncing, if it isn't then do whatever you normally would do with the switch.
 

Offline slateraptor

  • Frequent Contributor
  • **
  • Posts: 833
  • Country: us
Re: what's your favorite switch debouncing method?
« Reply #3 on: July 18, 2012, 06:07:24 pm »
For uC apps, I opt for soft debounce to minimize component count. Bounce tends to vary, so I usually toggle and probe the switch with an oscope or logic analyzer to get a rough idea of settling time, then adjust soft delay and debounce routine (depending on the app) accordingly. With memory, a timer, and level-driven interrupt, you can avoid unnecessary polling and clock dependencies, which is useful for optimizing computationally intensive apps.

For testing of simple state machines, I usually set up 2 NAND gates from a 74'00 (or whatever is convenient at the time) in a feedback loop with a SPDT switch and pull-up resistors driving the NAND gate inputs (see image below).



For devices with schmitt trigger inputs, lowpassing works fine too. You can also pick up debounce ICs if that floats your boat.
 

Offline Bored@Work

  • Super Contributor
  • ***
  • Posts: 3932
  • Country: 00
Re: what's your favorite switch debouncing method?
« Reply #4 on: July 18, 2012, 06:42:39 pm »
Undersampling from a timer.
I delete PMs unread. If you have something to say, say it in public.
For all else: Profile->[Modify Profile]Buddies/Ignore List->Edit Ignore List
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1641
  • Country: nl
Re: what's your favorite switch debouncing method?
« Reply #5 on: July 18, 2012, 07:29:12 pm »
A capacitor across the switch? Why not?
Well, you basically short the capacitor when you switch it, but whatever. :) A pull-up + small value capacitor works fine.

I don't always like software options, because using a timer for a simple hardware 'malfunction' sounds not worth it. I rather take care of it in hardware.
Of course I know that capacitors wont work if you're using a multiplexed set of buttons or a grid. Then undersampling is the option indeed.
 

Offline Bored@Work

  • Super Contributor
  • ***
  • Posts: 3932
  • Country: 00
Re: what's your favorite switch debouncing method?
« Reply #6 on: July 18, 2012, 08:11:27 pm »
because using a timer for a simple hardware 'malfunction' sounds not worth it.

One hardware timer can handle many other tasks in its timer interrupt, occasionally sampling keys and encoders being a tiny job on the side. And since I typically need a kind of system clock I anyhow have a timer running.

And malfunction? Nothing in the real world is perfect.
I delete PMs unread. If you have something to say, say it in public.
For all else: Profile->[Modify Profile]Buddies/Ignore List->Edit Ignore List
 

Offline ejeffrey

  • Super Contributor
  • ***
  • Posts: 3719
  • Country: us
Re: what's your favorite switch debouncing method?
« Reply #7 on: July 18, 2012, 08:24:39 pm »
Changeover switch with some sort of digital latch is the 'best' way for things that need accurate timing (limit switches and so forth), but for UI buttons scanning with an MCU is the cheapest and easiest way to go, and it is usually necessary anyway -- for instance if you are doing matrix multiplexing to reduce your pin count.

RC filters are OK, but I would generally prefer one of the above options.  Maybe if you have a button directly controlling a relay coil or something it is a good solution.  For uses in analog circuits contact bounce often isn't even a problem.
 

Offline free_electron

  • Super Contributor
  • ***
  • Posts: 8517
  • Country: us
    • SiliconValleyGarage
Re: what's your favorite switch debouncing method?
« Reply #8 on: July 18, 2012, 08:34:57 pm »
Cap across switch , feed into schmittrigger input of cpu / fpga to clean up signal.

In fpga i use  a 3 bit shift register clocked at slow clock . (like 100Hz ) only 111 and 000 toggle change a 4th  flipflop. This gives then the 'clean signal . Then i apply an edge detector on that, which brings this into the main clockdomain.

In cpu's i always code a system 'tick'. This tick happens at 1 or 2mS interval. The tick handler checks the key state and places flags. It also decrements values
The keyhandler is a statemachine.

For example : ( assuming 'input low' is a keypress , and only one key is pressed at a time. i don't do multikey intefaces .)

Code: [Select]
procedure systick using interrupt 5  ' 1 tick ever 1mS
  if debouncecounter >0 then
    decr debouceccounter
  else
    if key=keyhandled then
       key=nokey
    end if
    if key = nokey then
   
       if p1.0 = 0 then key = keyleft
       if p1.1 = 0 then key = keyup
       if p1.2 = 0 then key = keyright
       if p1.3 = 0 then key = keydown
       if p1.4 = 0 then key = keyenter
   
       if key <> nokey then debouncecounter = debounceinterval    
    end if
end procedure

mainloop: while 1
   if (key<>nokey)  then             ' if there was a key :
       if (key <> keyhandled) then   ' and we haven't handled it :
          blablable                  ' handle keypress
          key = keyhandled           ' mark key as handled so systick can resume keyboard ops
       end if  
   end if    
  end if
end while

how does this work :

At given intervals :
- if we are in debouncemode ( the deboucnecounter is larger than zero ) : decrement and exit
  since the system tick is 1000 times per second you could load the debounceinterval with 500. This would give 1/2 second key-repeat.

- If i am NOT in debouncemode ( counter is zero ) :
   - First check that the last key was handled by the user interface.
     The user interface marks key as 'keyhandled' if so.
     If the key is 'handled' : set the key to 'nokey' so the scanning system is now unlocked for processing
   - if the key is not handled ( key still has a value different from 'nokey' ) : don't scan. useless as the previous keystroke is still in the buffer
   - if the key is 'nokey' we can scan or poll inputs.
   - if a key is detected : store the key value in 'key' , and load the debouncecounter

   The main program doesn't deal with the keyboard . It only checks the value of  'key'
   If key is set to 'nokey' : skip and go do something else. there is nothing to do.
   If there is a key : process keystroke and set key to 'keyhandled' : this will 'unlock' the keypad scanner when it is time.
   
 this mechanism has several advantages :
 
  - it debounces keys without stalling the main program
  - it has an autorepeat equal to 'debounceinterval'
  - the key is queued. scanning stops until the main program has processed the current key.

You can use this without interrupts (saves stack space) . if your main program is an endless loop you can simply call this at the begin of the loop and put a fixed 1mS delay at the end of the loop. that has the same effect.

for example :

in the main program : the led needs to toggle at 1/2 second interval :
   led1state=blink_500   ( blink_500 is a constant set to '500' )
 
if i don't need the led to blink anymore i write
  led1state = ledoff ( ledoff is a constant set to '0' )

in the inthandler add this code :
Code: [Select]
  if led1state >0 then
    if led1cntr=0 then
       led1cntr = led1state  ' load the counter with interval stored in led1state
      p2.1= not p2.1          ' toggle p2.1 that has the led on it
   else
      led1cntr= led1cntr-1 ' decrement counter
  end if
 else
   p2.1=0   ' turn off led
end if

if i need the led to blink faster :
led1state = led_250 ( constant set to 250 )

in the interval handler you can do trickery like blink led's or other time-driven things.
« Last Edit: July 18, 2012, 08:45:14 pm by free_electron »
Professional Electron Wrangler.
Any comments, or points of view expressed, are my own and not endorsed , induced or compensated by my employer(s).
 

Offline Lukas

  • Frequent Contributor
  • **
  • Posts: 412
  • Country: de
    • carrotIndustries.net
Re: what's your favorite switch debouncing method?
« Reply #9 on: July 18, 2012, 08:36:12 pm »
In the german µC.net forum, Peter Danneger's debouncing routines (http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29) are often recommended.
 

Offline blackdog

  • Frequent Contributor
  • **
  • Posts: 739
  • Country: nl
  • Please stop pushing bullshit...
Re: what's your favorite switch debouncing method?
« Reply #10 on: July 18, 2012, 08:37:33 pm »
Hi i use the following schematics for debouncing


www.bramcam.nl/Debounce.JPG
Change the capacitor if you use it for a rotary encoder, lower value...

Kind regarts
Bram
« Last Edit: July 18, 2012, 08:42:32 pm by blackdog »
Necessity is not an established fact, but an interpretation.
 

Offline bingo600

  • Super Contributor
  • ***
  • Posts: 1989
  • Country: dk
Re: what's your favorite switch debouncing method?
« Reply #11 on: July 19, 2012, 10:07:03 am »
In the german µC.net forum, Peter Danneger's debouncing routines (http://www.mikrocontroller.net/articles/Entprellung#Timer-Verfahren_.28nach_Peter_Dannegger.29) are often recommended.

I second that one , and so does other ..

I seem to remember ..."2-bit barrelshifter" -"through running timer (no prog lockup)"
http://hackaday.com/2010/10/13/open-call-send-us-your-debounce-code/

Peters original posts here (use google xlate)
http://www.mikrocontroller.net/topic/tasten-entprellen-bulletproof#new
http://www.mikrocontroller.net/topic/164194#new

Matrix
http://www.mikrocontroller.net/topic/6491#new
And the "Classic Doc is here " http://www.ganssle.com/debouncing.htm

/Bingo
« Last Edit: July 19, 2012, 10:12:52 am by bingo600 »
 

Offline Psi

  • Super Contributor
  • ***
  • Posts: 9951
  • Country: nz
Re: what's your favorite switch debouncing method?
« Reply #12 on: July 19, 2012, 10:20:20 am »
If it's a simple mcu project and repeats are ok then i put a delay in, like so

Check if button pressed
Code: [Select]
if ((ButtonDown=true) && (BtnFlag=0))
{
    BtnFlag=10;
    DoButtonEvent();
}

In my main timer event under the 2 millisecond section
Code: [Select]
if (BtnFlag != 0) BtnFlag--;

If repeats have to be blocked then it's just a matter of storing the previous state and triggering on the edge.
It's also trivial to have separate button event code for a press vs a hold.
« Last Edit: July 19, 2012, 10:29:07 am by Psi »
Greek letter 'Psi' (not Pounds per Square Inch)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf