Silly Debounce Question

I currently have a circuit which displays a count on 4 7-segment displays. Push the up button, count increments, push the down count decreases. I'm trying to add functionality so that a tap of the button counts once, but holding the button causes fast counting.

The press and hold works just fine, but the "tap" causes multiple counts (as if it were not debounced at all). By adjusting Delay and Rate I can get it to "count too much, a little less" but it's still not the clean tap = 1 count, hold = lots a count I am looking for. I've tried adding delays in the macro and in my program loop to no avail. Any ideas?

PIC running at 32.768 KHZ, so I know thats part of the issue with only an 8 bit counter, but isn't there a way to make this bad boy work with a delay somewhere?

The code I have found (that almost works) is as follows:

Button Port, Pin, Downstate, Delay, Rate, Variable, Targetstate, Address Where: Port, Pin - the Button Pin (ie "PORTA, 0") and can be defined with a "#define" Statement Downstate - The State When the Button is Pressed Delay - The number of iterations of the Macro code before the "address" is jumped to (to 127). If Set to 0, then Jump if "targetstate" met without any debouncing. If Bit 7 of "Delay" is set, then no auto-repeats Rate - After the Initial jump to "address", the number of cycles (to

127) before autorepeating. Targetstate - The state ("1" or "0") to respond to. Address - The Address to Jump to when the Button is pressed or Auto-repeats

The Macro itself probably looks quite complex at first glance:

Button macro Port, Pin, Downstate, Delay, Rate, Variable, Targetstate, Address local ButtonEnd incf Variable, w ; Increment the Counter Variable if ((Downstate == 0) && (Targetstate == 0))||((Downstate == 1) && (Targetstate == 1)) btfsc Port, Pin ; If Low, then Valid Pin else btfss Port, Pin ; If High, then Valid Pin endif clrw ; Not Pressed, Clear the Counter movwf Variable ; Save the Counter Value movlw Delay & 0x07F subwf Variable, w ; Button Debounced? btfsc STATUS, Z goto Address ; If Equal, then "Yes" if ((Delay & 0x080) != 0) ; Is Autorepeat used? btfsc STATUS, C decf Variable ; No - Decrement if > "Delay" else btfss STATUS, C goto ButtonEnd ; Less than Expected - End xorlw Rate ; At the Autorepeat Point yet? btfsc STATUS, Z goto ButtonEnd ; No - Keep Incrementing movlw Delay ; Yes, Reset back to the Original Count and Repeat movwf Variable goto Address endif ButtonEnd ; Macro Finished endm

Reply to
Loading thread data ...

Here's an excellent collection of articles on debouncing techniques:

formatting link

formatting link

Reply to
Richard H.

A small capacitor across the switch will often do. Try 1uF to start with and just experiment.

Reply to

Thank you for your feedback. I think I need to clarify my problem. My original code worked great, and I had a debounce routine that detected button presses great. The problem was with my old approach I had to wait until the button was released before I considered the button debounced. When I went back to add the "press and hold" functionality I knew I needed a new method for debouncing.

The code above is logically working. (I can get less "bounce" by adjusting RATE and DELAY but the code only uses 7 bits for its counter (which probably worked great at 4kHz but at 32kHz its just not enough. I was trying to modify the macro to slow it down a bit. The problem is when I try to add a delay, I don't get the expected result. I either get slow response followed by fast counting (because the switch is still held down during the sampling even on a tap). I'm starting to think I might not be able to do this with a delay, and should modify the macro to use a 16 bit counter instead. Thoughts?

Reply to

Don't think switch or debounce. Think low-pass filter. FIR with thresholding on the output.


Reply to

In the absence of any quotes I assume an ordinary signalling switch controlling an input pin level.

Sounds like an excellent way to weld the contacts and induce early failure. 1 uF is far too high, and there should always be a current limiting resistor.

"If you want to post a followup via, don't use
 the broken "Reply" link at the bottom of the article.  Click on 
 Click to see the full signature
Reply to


have a look also at the excellent material from Scott Dattalo:

formatting link

I used the shown "parallel" tecnique in many different projects. A clever idea.

Reply to
Antonio Pasini

Er, no, don't. That's a really bad idea, for many reasons.


formatting link

Reply to
Steve at fivetrees

You need a very small switch contacts if they weld with 12.5 uJ energy pulse. A small resistance is an improvement. As for capacitor size since there has been no indication of circuit impedences and debounce time, your assertion is just guesswork.

Reply to

holy makerel, these are all way too complicated. Try this.. Just an ugly hack, but you can see. dont bother with the hardware debouncing.

counter=0; lastState=0; while(1) { sleep(1); //or delay some other method, so you dont check too soon. If button = 1 and lastState = 0 then //newly pressed lastState=1 elseif button =1 and lastState=1 then //debounced!! counter=counter+1; if counter < DEPRESS_COUNT singleIncrement() else counter=DEPRESS_COUNT; //this keeps held button from overflowing heldDown(); end if; elseif button=0 and lastState = 1 then counter = 0; lasState = 0; end if

Reply to

Determining "too soon" is the real art.

Reply to
Richard Henry

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.