Silly Debounce Question

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
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:

<from: http://www.rentron.com/Myke6.htm

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


Re: Silly Debounce Question
Quoted text here. Click to load it

Here's an excellent collection of articles on debouncing techniques:
http://www.ganssle.com/debouncing.pdf

http://www.ganssle.com/articles/adbounce.htm

Re: Silly Debounce Question
Quoted text here. Click to load it

Grene,

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

http://www.dattalo.com/technical/software/pic/debounce.html

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




Re: Silly Debounce Question
A small capacitor across the switch will often do. Try 1uF to start
with and just experiment.


Re: Silly Debounce Question
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?


Re: Silly Debounce Question
Quoted text here. Click to load it

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

-Martin



Re: Silly Debounce Question
Quoted text here. Click to load it

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 groups.google.com, don't use
 the broken "Reply" link at the bottom of the article.  Click on
We've slightly trimmed the long signature. Click to see the full one.
Re: Silly Debounce Question
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.


Re: Silly Debounce Question
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
                       counterDE%PRESS_COUNT;  //this keeps held button
from overflowing
                     heldDown();
              end if;
    elseif button=0 and lastState = 1 then
            counter = 0;
           lasState = 0;
     end if








}


Re: Silly Debounce Question

Quoted text here. Click to load it

Determining "too soon" is the real art.

Quoted text here. Click to load it



Re: Silly Debounce Question
Quoted text here. Click to load it

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

Steve
http://www.fivetrees.com



Site Timeline