Debounce pushbutton connected to uC

Thread Starter

nerdegutta

Joined Dec 15, 2009
2,684
I have circuit on a breadboard. It takes input from pushbuttons. The challenge I'm facing is the de-bouncing when pushing the button. I've tried different approaches with almost the same bad result.

I've tried with hardware de-bounce, software de-bounce and a combination of those, but I can't seem to find the right values.

When googling, these two circuits appears, but there are never any values on the resistors nor the capacitors.

So I have to ask:

How do I find the right values?

uC is running at 4MHz




..or is it the breadboard that is the problem, with "stray capitance". I'm going to make some PCBs for this project, will the de-bounce problem go away on a real PCB?
 

Attachments

tshuck

Joined Oct 18, 2012
3,534
Putting your circuit onto a soldered solution will not rid your button of contact bounce, sadly. It is a fact of life that must be overcome, and is inherent in all switches and buttons. Each button will have a different bounce (which is why you won't find values for your debounce circuits), though you may get lucky with similar buttons having close contact bounce.

This is a rather good explanation on the matter.(page 2 starts getting into dealing with the bounce...)

The way that I find what I need is to simply allow the button to bounce while observing the signal on an oscilloscope. Taking multiple measurements will lead you to a pretty good guess as to the maximum time the switch takes to settle into the new state(On=>Off & Off=>On). The minimum time to wait for re-sampling the input for a software implementation, in order to debounce, is given by the maximum time it takes for the button to settle into a new state. Add a little fudge-room and you should be good to go.
 

Thread Starter

nerdegutta

Joined Dec 15, 2009
2,684
Thanks. Was really clarifying.

I breadboarded figure 2, in the top post.
R3 = 4.7K
C2 = 0.1uF
This is the result:



Then I removed the R and the C:



The setting on the PC scope is the same, and I'm no expert using that, but it gave me a picture that hope I've found some usable values.
 

Attachments

JDT

Joined Feb 12, 2009
657
You should really be doing the de-bouncing in software.

If you are polling the input(s) on a regular basis then you can do the de-bouncing by assuming that if the switch appears closed every poll for a certain number of polls - it is closed. And similar for open.

You could use a timer to generate a regular interrupt that does switch polling.

Example: generate an interrupt every millisecond. In the interrupt routine check all your switches and buttons. If switch closed every interrupt for 32 interrupts - set it's state as "closed". For it to be open, wait for 32 continuous open polls.

This could be a routine that continually runs in the background.
 

Thread Starter

nerdegutta

Joined Dec 15, 2009
2,684
I tried with delay in software, from 10ms up to 100ms. Increased by 5ms. The hardware de-bounce works best. As for now, component count is no issue.

The interrupt idea has come to mind - and stayed there... :)

Guess I will try it out, at a later time. Next year, maybe.:)
 

atferrari

Joined Jan 6, 2004
4,771
I use software. Up to 45 msec. My routine works OK.

Never in life bothered with hardware debouncing, provided a micro was involved.
 
Last edited:

WBahn

Joined Mar 31, 2012
30,076
There are several ways to debounce a switch, depending on the switch.

The very first way I ever learned about (in a Physics Lab Course -- generally learned a lot more in the way of practical things in physics lab courses than EE lab courses, but more practical things in EE lecture courses than physics lecture courses, but overall thought they made great complements to each other) debouncing a switch works best for a SPDT switch. Use an RS latch (two cross coupled NAND gates or NOR gates) and tie the R input to one and the S input to the other. Resistively pull each input to the inactive level (HI for a NAND gate version and LO for a NOR gate version). Tie the two poles of the switch to the two inputs and the common to the active level (LO for NAND, HI for NOR). Virtually all SPDT switches are break-before-make, meaning that as you flip the switch the contact that you are breaking open will bounce for a bit but it will stop bouncing well before the other contact makes for the first time, after which it might bounce quite a bit. The latch will change state upon the first activation of a given input and it doesn't matter if that input bounces after that, as long as the other input doesn't bounce, which it won't because it's already done bouncing. Likewise, it doesn't matter if the current input bounces when you start to change state, as long as it finished before the first make on the other side.
 

WBahn

Joined Mar 31, 2012
30,076
If you are going into a MCU I would just do it in software. I don't think I've ever had to debounce for more than 50ms. Now, at least in my routines, the 50ms is not from the first detected transition, but from the last. Usually what I do it make the equivalent of a retriggerable one-shot (and you can use the same idea in hardware if you would like, but there's really no point if you can do it in software). Basically my logic goes something like this:

Rich (BB code):
WHILE (forever)
{
   ...
   IF (state == input)
      count = COUNT_RESET;
   else
      count = count - 1;
   IF (count == 0)
      state = ~state;
   ...
}
 

MrChips

Joined Oct 2, 2009
30,823
I usually put the switch on the GND side and use a pullup resistor or the MCU internal weak pullup. No capacitor. In software I take a reading followed by a second reading 50ms approx. later. Both readings must be the same before it is accepted. Otherwise, continue to take readings 50ms apart until both are the same.

In a typical low power application, the MCU is in sleep mode and hence interrupt on key change is used to wake up the MCU. After that hardware or software delay can be used. Further keyswitch interrupts are not necessary. More often than not, I am scanning a keypad or multiple switches hence software delays are already inherent in the scanning process.
 

Thread Starter

nerdegutta

Joined Dec 15, 2009
2,684
Thanks guys.

So, with an uC, software de-bouncing is preferred. Fewer components, less soldering. I'll really have to look into that.


So...

I got a question from the GF. Can you help making dinner? You've been sitting at the computer since 05:30, and now it's 15:44..

I think I better do that.

Happy new year, guys, and thanks for the input.
 

MMcLaren

Joined Feb 14, 2010
861
I have circuit on a breadboard. It takes input from pushbuttons. The challenge I'm facing is the de-bouncing when pushing the button. I've tried different approaches with almost the same bad result.
Can you describe the "bad result" you're getting, please? Could there be a problem be with your switch state logic, like detecting a single "new press" state, rather than actual switch bounce?
 
Last edited:

bertus

Joined Apr 5, 2008
22,278
Hello,

With the microchip pickit2 I got a CD with some examples.
There are C and ASM examples fro debounce:

For ASM this is given:
Rich (BB code):
;******************************************************************************
;Software License Agreement                                         
;                                                                    
;The software supplied herewith by Microchip Technology             
;Incorporated (the "Company") is intended and supplied to you, the  
;Company’s customer, for use solely and exclusively on Microchip    
;products. The software is owned by the Company and/or its supplier,
;and is protected under applicable copyright laws. All rights are   
;reserved. Any use in violation of the foregoing restrictions may   
;subject the user to criminal sanctions under applicable laws, as   
;well as to civil liability for the breach of the terms and         
;conditions of this license.                                        
;                                                                    
;THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,  
;WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED  
;TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A       
;PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,  
;IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR         
;CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.       
; *******************************************************************
; PICkit 2 Lesson 5 - Switch Debounce
;
; This shows one method to debounce switches.  
; Samples the line every 1mS, and waits for 5 in a row before
; acting on the change of state.
;
; *******************************************************************
; * See Low Pin Count Demo Board User's Guide for Lesson Information*
; *******************************************************************
; * NOTE: The PIC16F690 requires the AC162061 header for debugging  *
; *******************************************************************
     
#include <p16F690.inc>
     __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)

     cblock     0x20
Delay               ; Assign an address to label Delay1
Display             ; define a variable to hold the diplay
LastStableState     ; keep track of switch state (open-1; closed-0)
Counter
     endc
     
     org 0
Start:
     bsf       STATUS,RP0          ; select Register Page 1
     movlw     0xFF
     movwf     TRISA               ; Make PortA all input
     clrf      TRISC               ; Make PortC all output

     bcf       STATUS,RP0          ; address Register Page 2
     bsf       STATUS,RP1     
     movlw     0xF7                ; PortA3 pin is digital
     movwf     ANSEL
     bcf       STATUS,RP0          ; address Register Page 0
     bcf       STATUS,RP1
     
     clrf      Display
     clrf      PORTC
     movlw     1
     movwf     LastStableState     ; Assume the Switch is up.
     clrf      Counter
MainLoop:
     btfsc     LastStableState,0
     goto      LookingForUp
LookingForDown:
     clrw                          ; assume it's not, so clear
     btfss     PORTA,3             ; wait for switch to go low
     incf      Counter,w           ; if it's low, bump the counter
     movwf     Counter             ; store either the 0 or incremented value
     goto      EndDebounce
     
LookingForUp:
     clrw                          ; assume it's not, so clear
     btfsc     PORTA,3             ; wait for switch to go low
     incf      Counter,w
     movwf     Counter

EndDebounce:
     movf      Counter,w           ; have we seen 10 in a row?
     xorlw     5
     btfss     STATUS,Z     
     goto      Delay1mS
     
     comf      LastStableState,f   ; after 10 straight, reverse the direction
     clrf      Counter
     btfss     LastStableState,0   ; Was it a key-down press?
     goto      Delay1mS            ; no: take no action
     
     incf      Display,f           ; if it's the down direction, 
     movf      Display,w           ; take action on the switch
     movwf     PORTC               ; (increment counter and put on display)
     
Delay1mS:
     movlw     .71                 ; delay ~1000uS
     movwf     Delay
     decfsz    Delay,f             ; this loop does 215 cycles
     goto      $-1          
     decfsz    Delay,f             ; This loop does 786 cycles
     goto      $-1
     goto      MainLoop
     end
For C this is given:
Rich (BB code):
#include <pic.h>
/*  cDebounce.c - Debounce Button Input on RA3

This Program polls the button at RA3 and changes the state of
  RA5 after the press has been debounced.  Use a 20 ms debounce
  period.

RA3 - Button Connection
RA4 - LED Positive Connection
RA5 - LED Negative Connection

myke predko
04.11.07

*/

__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
  & UNPROTECT & BORDIS & IESODIS & FCMDIS);

int i;

const int Twentyms = 1150;      //  Declare a Constant for 20 ms Delay

main()
{

    PORTA = 0x3F;               //  All Bits are High
    CMCON0 = 7;                 //  Turn off Comparators
    ANSEL = 0;                  //  Turn off ADC
    TRISA4 = 0;                 //  Make RA4/RA5 Outputs
    TRISA5 = 0;

    while(1 == 1)               //  Loop Forever
    {
        i = 0;                  //  Wait 20 ms for Button Up
        while (i < Twentyms)
        {
            if (0 == RA3)       //  Button Down/Start over
            {
                i = 0;
            }
            else                //  Button Up/Increment Count
            {
                i = i + 1;
            }  //  fi
        }  // elihw

        NOP();
        i = 0;                  //  Wait 20 ms for Button Down
        while (i < Twentyms)
            if (1 == RA3)       //  Button Up/Start over
                i = 0;
            else                //  Button Down/Increment Count
                i = i + 1;

        RA5 = RA5 ^ 1;          //  Toggle RA5 to Turn ON/OFF LED

    }  //  elihw
}  //  End cDebounce
I hope this will give you an idea how to debounce in software.

All info can also be downloaded as the code examples of the low pin count board.

Bertus
 

John P

Joined Oct 14, 2008
2,026
People let switch debouncing be a bugaboo, and it's trivial. Use the right procedure, and you don't even have to think about it.

The switch needs a pullup which can be internal to the processor, or an added part. I suppose you could invert this, and connect the switch to Vcc with a pulldown resistor, but it doesn't affect the logic.

Then all the processor needs to do is read the switch at an interval that's known to be longer than the maximum contact bounce time. 50msec, or 20 times/sec would be long enough for just about any switch. It doesn't matter whether the switch gets read before or after or during its period of uncertainty, the processor will never see anything but a single transition. It really is that simple.
 

MMcLaren

Joined Feb 14, 2010
861
I agree with John. Gannsle talks about both switch bounce and noise in his paper, however, if you're not using the equipment in an electrically noisy environment there's no need for a low pass filter (multiple samples at shorter intervals spanning the debounce period). All that's necessary to debounce a switch is to sample it at some interval greater than the switch bounce time. In my experience, this could be anywhere from 8 to 25 msecs, or more. Longer periods are ok as long as you understand some users perceive switches as sluggish with as little as 50 msec of debounce time.

That said, when compared to debouncing a switch, I believe switch state logic and switch state management is a more interesting problem. For example, simple switch state logic can be used to filter out all but a "new press" state while ignoring the "still pressed", the "new release", and the "still released" switch states. In a simple form for a single switch, switch logic might look like this;

Rich (BB code):
  #define newpress ((porta.0 == 1) && (swold.0 == 0))
  #define newrelease ((porta.0 == 0) && (swold.0 == 1))

  while(1)
  { delay_ms(20);            // 20 msec debounce/sample interval
    if(newpress)             // if sw0 (RA0) "new press"
    { swold.0 = 1;           // update switch state latch
      portb.0 ^= 1;          // toggle LED on RB0
    }                        //
    if(newrelease)           // if sw0 (RA0) "new release"
      swold.0 = 0;           // update switch state latch
  }
When you press the switch on RA0 the LED on RB0 is toggled. You can keep the switch pressed as long as you like since we are ignoring the "still pressed" state where RA0 == 1 and swold.0 == 1.

Using that code for multiple switches could be tedious. Fortunately, you can use relatively simple parallel switch state logic to perform the same task for multiple switches on the same port. Here's an example;

Rich (BB code):
  while(1)
  { delay_ms(20);            // 20 msec debounce/sample interval
 /*                                                                *
  *  K8LH Parallel Switch State Logic (with "new press" filter)    *
  *                                                                *
  *  swnew  ___---___---______  invert active lo switches          *
  *  swold  ____---___---_____  switch state latch                 *
  *  swnew  ___-__-__-__-_____  changes, press or release          *
  *  swnew  ___-_____-________  filter out 'release' bits          *
  *                                                                */
    swnew = ~porta;          // sample active lo switches
    swnew ^= swold;          // changes, press or release
    swold ^= swnew;          // update switch state latch
    swnew &= swold;          // filter out 'release' bits

    if(swnew.0)              // if sw0 (RA0) "new press"
      portb.0 ^= 1;          // toggle LED on RB0

    if(swnew.1)              // if sw1 (RA1) "new press"
      portb.1 ^= 1;          // toggle LED on RB1
  }                          //
If you're using PIC assembly language, the parallel switch state logic uses all of 5 instructions;

Rich (BB code):
;************************************************************
;  main loop                                                *
;************************************************************
;
;  K8LH Parallel Switch State Logic (with "new press" filter)
; 
;  swnew    ___---___---_______   invert active lo switches
;  swold    ____---___---______   switch state latch
;  swnew    ___-__-__-__-______   changes, press or release 
;  swnew    ___-_____-_________   filter out 'release' bits
;   
loop
        DelayCy(20*msecs)       ; 20 msec debounce interval
        comf    PORTA,W         ; sample active lo switches
        xorwf   swold,W         ; changes, press or release
        xorwf   swold,F         ; update switch state latch
        andwf   swold,W         ; filter out 'release' bits
        movwf   swnew           ; save any "new press" bits
;
Cheerful regards... Mike
 
Last edited:

ramancini8

Joined Jul 18, 2012
473
No debounce circuit can be relied on 100% because people will play all kinds of games with the switch or switch charasteristics change with age. The only debounce circuit that works close to every time all the time is a low pass filter calculated to have a time constant much longer than the bounce time followed by a hystersis gate. The FF works most of the time, but if a short bounce occurs the FF might not lock up thus yielding a double pulse. The filter alone works some times, but the slow rising edge is suceptable to noise riding on the filter output causing multiple pulses. Software debounce circuits work most of the time, but again, you must control the signal until all the bounce has gone away. One advantage of the software debounce is cost.
 

takao21203

Joined Apr 28, 2012
3,702
No debounce circuit can be relied on 100% because people will play all kinds of games with the switch or switch charasteristics change with age. The only debounce circuit that works close to every time all the time is a low pass filter calculated to have a time constant much longer than the bounce time followed by a hystersis gate. The FF works most of the time, but if a short bounce occurs the FF might not lock up thus yielding a double pulse. The filter alone works some times, but the slow rising edge is suceptable to noise riding on the filter output causing multiple pulses. Software debounce circuits work most of the time, but again, you must control the signal until all the bounce has gone away. One advantage of the software debounce is cost.
Then use a software lowpass? It is very easy to implement via interrupts.

No calculation takes place. You simply set the minimum cycle time to some 10 miliseconds.

If the cycle time is minimum 30 miliseconds, how is it possible to play tricks with it? There is capacitor.
 

Thread Starter

nerdegutta

Joined Dec 15, 2009
2,684
Can you describe the "bad result" you're getting, please? Could there be a problem be with your switch state logic, like detecting a single "new press" state, rather than actual switch bounce?
When button is pressed, the uC register multiple highs.:rolleyes:

The FF works most of the time, but if a short bounce occurs the FF might not lock up thus yielding a double pulse.
What is FF?

Thanks a lot guys.

I'll be checking out software interrupt debouncing.
 
Top