Debounce pushbutton connected to uC

Discussion in 'General Electronics Chat' started by nerdegutta, Dec 31, 2012.

  1. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    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


    [​IMG]

    ..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?
     
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    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.
     
    nerdegutta likes this.
  3. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    Thanks. Was really clarifying.

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

    [​IMG]

    Then I removed the R and the C:

    [​IMG]

    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.
     
  4. JDT

    Well-Known Member

    Feb 12, 2009
    658
    85
    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.
     
  5. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    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.:)
     
  6. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    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: Dec 31, 2012
  7. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    Care to share?
     
  8. WBahn

    Moderator

    Mar 31, 2012
    17,763
    4,800
    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.
     
  9. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    Thanks, but it's not a SPDT. It's similar to this:

    [​IMG]
    And I don't have NAND or NOR gates.
     
  10. WBahn

    Moderator

    Mar 31, 2012
    17,763
    4,800
    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:

    Code ( (Unknown Language)):
    1.  
    2. WHILE (forever)
    3. {
    4.    ...
    5.    IF (state == input)
    6.       count = COUNT_RESET;
    7.    else
    8.       count = count - 1;
    9.    IF (count == 0)
    10.       state = ~state;
    11.    ...
    12. }
    13.  
     
    nerdegutta likes this.
  11. MrChips

    Moderator

    Oct 2, 2009
    12,449
    3,363
    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.
     
    nerdegutta likes this.
  12. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    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.
     
  13. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    Like the other good posts, I do it in firmware.
    Good luck.
     
  14. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    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: Dec 31, 2012
  15. bertus

    Administrator

    Apr 5, 2008
    15,648
    2,348
    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:
    Code ( (Unknown Language)):
    1.  
    2. ;******************************************************************************
    3. ;Software License Agreement                                        
    4. ;                                                                    
    5. ;The software supplied herewith by Microchip Technology            
    6. ;Incorporated (the "Company") is intended and supplied to you, the  
    7. ;Company’s customer, for use solely and exclusively on Microchip    
    8. ;products. The software is owned by the Company and/or its supplier,
    9. ;and is protected under applicable copyright laws. All rights are  
    10. ;reserved. Any use in violation of the foregoing restrictions may  
    11. ;subject the user to criminal sanctions under applicable laws, as  
    12. ;well as to civil liability for the breach of the terms and        
    13. ;conditions of this license.                                        
    14. ;                                                                    
    15. ;THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,  
    16. ;WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED  
    17. ;TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A      
    18. ;PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,  
    19. ;IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR        
    20. ;CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.      
    21. ; *******************************************************************
    22. ; PICkit 2 Lesson 5 - Switch Debounce
    23. ;
    24. ; This shows one method to debounce switches.  
    25. ; Samples the line every 1mS, and waits for 5 in a row before
    26. ; acting on the change of state.
    27. ;
    28. ; *******************************************************************
    29. ; * See Low Pin Count Demo Board User's Guide for Lesson Information*
    30. ; *******************************************************************
    31. ; * NOTE: The PIC16F690 requires the AC162061 header for debugging  *
    32. ; *******************************************************************
    33.      
    34. #include <p16F690.inc>
    35.      __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
    36.  
    37.      cblock     0x20
    38. Delay               ; Assign an address to label Delay1
    39. Display             ; define a variable to hold the diplay
    40. LastStableState     ; keep track of switch state (open-1; closed-0)
    41. Counter
    42.      endc
    43.      
    44.      org 0
    45. Start:
    46.      bsf       STATUS,RP0          ; select Register Page 1
    47.      movlw     0xFF
    48.      movwf     TRISA               ; Make PortA all input
    49.      clrf      TRISC               ; Make PortC all output
    50.  
    51.      bcf       STATUS,RP0          ; address Register Page 2
    52.      bsf       STATUS,RP1    
    53.      movlw     0xF7                ; PortA3 pin is digital
    54.      movwf     ANSEL
    55.      bcf       STATUS,RP0          ; address Register Page 0
    56.      bcf       STATUS,RP1
    57.      
    58.      clrf      Display
    59.      clrf      PORTC
    60.      movlw     1
    61.      movwf     LastStableState     ; Assume the Switch is up.
    62.      clrf      Counter
    63. MainLoop:
    64.      btfsc     LastStableState,0
    65.      goto      LookingForUp
    66. LookingForDown:
    67.      clrw                          ; assume it's not, so clear
    68.      btfss     PORTA,3             ; wait for switch to go low
    69.      incf      Counter,w           ; if it's low, bump the counter
    70.      movwf     Counter             ; store either the 0 or incremented value
    71.      goto      EndDebounce
    72.      
    73. LookingForUp:
    74.      clrw                          ; assume it's not, so clear
    75.      btfsc     PORTA,3             ; wait for switch to go low
    76.      incf      Counter,w
    77.      movwf     Counter
    78.  
    79. EndDebounce:
    80.      movf      Counter,w           ; have we seen 10 in a row?
    81.      xorlw     5
    82.      btfss     STATUS,Z    
    83.      goto      Delay1mS
    84.      
    85.      comf      LastStableState,f   ; after 10 straight, reverse the direction
    86.      clrf      Counter
    87.      btfss     LastStableState,0   ; Was it a key-down press?
    88.      goto      Delay1mS            ; no: take no action
    89.      
    90.      incf      Display,f           ; if it's the down direction,
    91.      movf      Display,w           ; take action on the switch
    92.      movwf     PORTC               ; (increment counter and put on display)
    93.      
    94. Delay1mS:
    95.      movlw     .71                 ; delay ~1000uS
    96.      movwf     Delay
    97.      decfsz    Delay,f             ; this loop does 215 cycles
    98.      goto      $-1          
    99.      decfsz    Delay,f             ; This loop does 786 cycles
    100.      goto      $-1
    101.      goto      MainLoop
    102.      end
    103.  
    For C this is given:
    Code ( (Unknown Language)):
    1.  
    2. #include <pic.h>
    3. /*  cDebounce.c - Debounce Button Input on RA3
    4.  
    5. This Program polls the button at RA3 and changes the state of
    6.   RA5 after the press has been debounced.  Use a 20 ms debounce
    7.   period.
    8.  
    9. RA3 - Button Connection
    10. RA4 - LED Positive Connection
    11. RA5 - LED Negative Connection
    12.  
    13. myke predko
    14. 04.11.07
    15.  
    16. */
    17.  
    18. __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
    19.   & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    20.  
    21. int i;
    22.  
    23. const int Twentyms = 1150;      //  Declare a Constant for 20 ms Delay
    24.  
    25. main()
    26. {
    27.  
    28.     PORTA = 0x3F;               //  All Bits are High
    29.     CMCON0 = 7;                 //  Turn off Comparators
    30.     ANSEL = 0;                  //  Turn off ADC
    31.     TRISA4 = 0;                 //  Make RA4/RA5 Outputs
    32.     TRISA5 = 0;
    33.  
    34.     while(1 == 1)               //  Loop Forever
    35.     {
    36.         i = 0;                  //  Wait 20 ms for Button Up
    37.         while (i < Twentyms)
    38.         {
    39.             if (0 == RA3)       //  Button Down/Start over
    40.             {
    41.                 i = 0;
    42.             }
    43.             else                //  Button Up/Increment Count
    44.             {
    45.                 i = i + 1;
    46.             }  //  fi
    47.         }  // elihw
    48.  
    49.         NOP();
    50.         i = 0;                  //  Wait 20 ms for Button Down
    51.         while (i < Twentyms)
    52.             if (1 == RA3)       //  Button Up/Start over
    53.                 i = 0;
    54.             else                //  Button Down/Increment Count
    55.                 i = i + 1;
    56.  
    57.         RA5 = RA5 ^ 1;          //  Toggle RA5 to Turn ON/OFF LED
    58.  
    59.     }  //  elihw
    60. }  //  End cDebounce
    61.  
    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
     
    nerdegutta likes this.
  16. John P

    AAC Fanatic!

    Oct 14, 2008
    1,634
    224
    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.
     
  17. MMcLaren

    Well-Known Member

    Feb 14, 2010
    759
    116
    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;

    Code ( (Unknown Language)):
    1.  
    2.   #define newpress ((porta.0 == 1) && (swold.0 == 0))
    3.   #define newrelease ((porta.0 == 0) && (swold.0 == 1))
    4.  
    5.   while(1)
    6.   { delay_ms(20);            // 20 msec debounce/sample interval
    7.     if(newpress)             // if sw0 (RA0) "new press"
    8.     { swold.0 = 1;           // update switch state latch
    9.       portb.0 ^= 1;          // toggle LED on RB0
    10.     }                        //
    11.     if(newrelease)           // if sw0 (RA0) "new release"
    12.       swold.0 = 0;           // update switch state latch
    13.   }
    14.  
    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;

    Code ( (Unknown Language)):
    1.  
    2.   while(1)
    3.   { delay_ms(20);            // 20 msec debounce/sample interval
    4.  /*                                                                *
    5.   *  K8LH Parallel Switch State Logic (with "new press" filter)    *
    6.   *                                                                *
    7.   *  swnew  ___---___---______  invert active lo switches          *
    8.   *  swold  ____---___---_____  switch state latch                 *
    9.   *  swnew  ___-__-__-__-_____  changes, press or release          *
    10.   *  swnew  ___-_____-________  filter out 'release' bits          *
    11.   *                                                                */
    12.     swnew = ~porta;          // sample active lo switches
    13.     swnew ^= swold;          // changes, press or release
    14.     swold ^= swnew;          // update switch state latch
    15.     swnew &= swold;          // filter out 'release' bits
    16.  
    17.     if(swnew.0)              // if sw0 (RA0) "new press"
    18.       portb.0 ^= 1;          // toggle LED on RB0
    19.  
    20.     if(swnew.1)              // if sw1 (RA1) "new press"
    21.       portb.1 ^= 1;          // toggle LED on RB1
    22.   }                          //
    23.  
    If you're using PIC assembly language, the parallel switch state logic uses all of 5 instructions;

    Code ( (Unknown Language)):
    1.  
    2. ;************************************************************
    3. ;  main loop                                                *
    4. ;************************************************************
    5. ;
    6. ;  K8LH Parallel Switch State Logic (with "new press" filter)
    7. ;
    8. ;  swnew    ___---___---_______   invert active lo switches
    9. ;  swold    ____---___---______   switch state latch
    10. ;  swnew    ___-__-__-__-______   changes, press or release
    11. ;  swnew    ___-_____-_________   filter out 'release' bits
    12. ;  
    13. loop
    14.         DelayCy(20*msecs)       ; 20 msec debounce interval
    15.         comf    PORTA,W         ; sample active lo switches
    16.         xorwf   swold,W         ; changes, press or release
    17.         xorwf   swold,F         ; update switch state latch
    18.         andwf   swold,W         ; filter out 'release' bits
    19.         movwf   swnew           ; save any "new press" bits
    20. ;
    21.  
    Cheerful regards... Mike
     
    Last edited: Dec 31, 2012
    nerdegutta likes this.
  18. ramancini8

    Member

    Jul 18, 2012
    442
    118
    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.
     
  19. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    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.
     
  20. nerdegutta

    Thread Starter Moderator

    Dec 15, 2009
    2,517
    785
    When button is pressed, the uC register multiple highs.:rolleyes:

    What is FF?

    Thanks a lot guys.

    I'll be checking out software interrupt debouncing.
     
Loading...