what's your favorite switch debouncing method? - Page 1
Forum section: electronics / general

author: slburris
author_rank: Frequent Contributor
timestamp: July 18, 2012, 02:57:25 pm
content: I came across an article in this months Circuit Cellar talking about switchdebouncing, and it seemed overly complex to me. Here's what I've donein the past.For a hardware based design, I feed a switch to the D input of a flip-flopand continuously clock the FF at 50-100hz (obviously ground 1 inputof the switch and use a pull-up resistor on the other side of the switch whichgoes to the FF). Just pick the clock rate to have a period longer than ittakes the bouncing to die out. Sure, there's a slight risk of metastabilityissues, but you could just cascade a second FF on the output of the firstif you were really concerned about that.In software, do something similar in that have a interrupt routine calledat 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 thatjust seems like a horrid design choice to me.Any other good ways to do this?Scott

author: DaveW
author_rank: Frequent Contributor
timestamp: July 18, 2012, 03:53:41 pm
content: 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.

author: andyg
author_rank: Regular Contributor
timestamp: July 18, 2012, 05:04:48 pm
content: I remember usingthis post on Hackadaywith 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.

author: slateraptor
author_rank: Frequent Contributor
timestamp: July 18, 2012, 06:07:24 pm
content: 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.

author: Bored@Work
author_rank: Super Contributor
timestamp: July 18, 2012, 06:42:39 pm
content: Undersampling from a timer.

author: hans
author_rank: Super Contributor
timestamp: July 18, 2012, 07:29:12 pm
content: 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.

author: Bored@Work
author_rank: Super Contributor
timestamp: July 18, 2012, 08:11:27 pm
content: Quote from: hans on July 18, 2012, 07:29:12 pmOne 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.

author: ejeffrey
author_rank: Super Contributor
timestamp: July 18, 2012, 08:24:39 pm
content: 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.

author: free_electron
author_rank: Super Contributor
timestamp: July 18, 2012, 08:34:57 pm
content: 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 valuesThe 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:procedure systick using interrupt 5 ' 1 tick ever 1mSif debouncecounter >0 thendecr debouceccounterelseif key=keyhandled thenkey=nokeyend ifif key = nokey thenif p1.0 = 0 then key = keyleftif p1.1 = 0 then key = keyupif p1.2 = 0 then key = keyrightif p1.3 = 0 then key = keydownif p1.4 = 0 then key = keyenterif key <> nokey then debouncecounter = debounceintervalend ifend proceduremainloop: while 1if (key<>nokey) then ' if there was a key :if (key <> keyhandled) then ' and we haven't handled it :blablable ' handle keypresskey = keyhandled ' mark key as handled so systick can resume keyboard opsend ifend ifend ifend whilehow does this work :At given intervals :- if we are in debouncemode ( the deboucnecounter is larger than zero ) : decrement and exitsince 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 debouncecounterThe 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 writeled1state = ledoff ( ledoff is a constant set to '0' )in the inthandler add this code :Code:if led1state >0 thenif led1cntr=0 thenled1cntr = led1state ' load the counter with interval stored in led1statep2.1= not p2.1 ' toggle p2.1 that has the led on itelseled1cntr= led1cntr-1 ' decrement counterend ifelsep2.1=0 ' turn off ledend ifif 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.

author: Lukas
author_rank: Frequent Contributor
timestamp: July 18, 2012, 08:36:12 pm
content: 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.

author: blackdog
author_rank: Frequent Contributor
timestamp: July 18, 2012, 08:37:33 pm
content: Hi i use the following schematics for debouncingwww.bramcam.nl/Debounce.JPGChange the capacitor if you use it for a rotary encoder, lower value...Kind regartsBram

author: bingo600
author_rank: Super Contributor
timestamp: July 19, 2012, 10:07:03 am
content: Quote from: Lukas on July 18, 2012, 08:36:12 pmI 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#newhttp://www.mikrocontroller.net/topic/164194#newMatrixhttp://www.mikrocontroller.net/topic/6491#newAnd the "Classic Doc is here "http://www.ganssle.com/debouncing.htm/Bingo

author: Psi
author_rank: Super Contributor
timestamp: July 19, 2012, 10:20:20 am
content: If it's a simple mcu project and repeats are ok then i put a delay in, like soCheck if button pressedCode:if ((ButtonDown=true) && (BtnFlag=0)){BtnFlag=10;DoButtonEvent();}In my main timer event under the 2 millisecond sectionCode: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.