debouncing switches with a timer interrupt?


Closed Thread
Results 1 to 28 of 28

Hybrid View

  1. #1
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    This would still require some kind of debouncing. The logic state can "bounce" a number of times when pressing a button
    Contact's debouncing should be solved with proper RC filter! If proper filtering is not possible an additional IF/THEN statement should reduce greatly the debouncing effect.

    Code:
    False        CON  0
    True         CON  1
    KEYPRESS  VAR portXx
    KeyFlag      VAR BIT
    Counter      VAR WORD
    
    LOOP:
    
    PAUSE 1
    
    IF KEYPRESS = False then
    
    IF KeyFlag = False Then
    Counter = Counter + 1
    KeyFlag = True
    ENDIF
    
    ELSE
    KeyFlag = False
    IF  KEYPRESS = False THEN  KeyFlag = True    ' re-checks the key logic state
    ENDIF
    .
    .
    .
    .
    .
    GOTO LOOP
    Al.
    Last edited by aratti; - 26th July 2010 at 00:01.
    All progress began with an idea

  2. #2
    Join Date
    Dec 2009
    Location
    Kalamazoo
    Posts
    42


    Did you find this post helpful? Yes | No

    Default

    thanks guys.

    i tried the capacitor method, and that did not work well. still skipping menu items.

    im using proteus simulation, and i tried every value of cap, 1000uf to 0.000001 uf., and everything in between.

    ill try integrate the software flag idea into the problem, and hope that it fixes it. thanks
    NAG CON WIFE!
    WIFE VAR MOOD

  3. #3
    Join Date
    Dec 2009
    Location
    Kalamazoo
    Posts
    42


    Did you find this post helpful? Yes | No

    Default still not functioning

    hi all
    i tried to implement the flag idea, but still the same result. menu item cycles through 3 to 6 items with one push of a button. here's the code snippet
    Code:
    RB_MainMenuLoop:
    ' BTN_PLUS is the Next Choice button
        PAUSE 1
          IF BTN_PLUS=0 THEN
          ;PAUSE 200
          IF FLAG_PLUS = 0 THEN
          bMenuPos=bMenuPos+1
          FLAG_PLUS = 1
          ELSE 
          FLAG_PLUS = 0
          IF BTN_PLUS = 0 THEN FLAG_PLUS = 1
          ;ENDIF
          IF bMenuPos>22 THEN
             bMenuPos=1
          ENDIF
          ENDIF
          Goto DisplayMainMenuLoop:
       ENDIF
    im beginning to think that debouncing is not the problem. is there any other way to skin this cat?
    NAG CON WIFE!
    WIFE VAR MOOD

  4. #4
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    Counter Var Byte

    RB_MainMenuLoop:
    ' BTN_PLUS is the Next Choice button

    PAUSE 1

    IF BTN_PLUS=0 THEN

    IF FLAG_PLUS = 0 THEN
    bMenuPos = bMenuPos + 1
    FLAG_PLUS = 1
    Counter = 0
    ENDIF

    ELSE
    Pause = 10
    Counter = Counter + 1
    IF Counter > 50 THEN FLAG_PLUS = 0 : Counter = 0
    ENDIF

    IF bMenuPos>22 THEN
    bMenuPos=1
    ENDIF

    Goto DisplayMainMenuLoop:

    ================================================== ===============

    Try this snippet and see how it works. You can tune the PAUSE 10 and Counter > 5, to better values to suite your need.

    Al.
    Last edited by aratti; - 30th July 2010 at 08:48.
    All progress began with an idea

  5. #5
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,648


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by DDDvvv View Post
    hi all
    i tried to implement the flag idea, but still the same result.
    Hi,

    You should understand debouncing NEED time, where ever this time comes from ( capacitor, timer ...)

    the idea of debouncing is :

    " Does the electrical state of pin still changes afer X milliseconds ??? "

    so, you can't get a correct answer before X milliseconds !!! - Obvious -

    But 200 ms is debouncing time for really poor quality switches, 20 ms can be obtained easily.

    note also switches " bounce " when closing its contact ... not when opening it !!!

    so, ... is it here THE good idea ???

    Further, May I tell you a real time timer might not be disturbed by a keypress ... - or your program is " not so good " ...

    the delay needed by the RTC to be updated is so far smaller than a key press action ...

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Consider using a switch state latch and relatively simple logic to sample your switches and detect the "new press" state while ignoring the other switch states. Here are the switch states;

    Code:
    swnew swold  switch state
      1     0    a "new press"
      1     1    still pressed
      0     1    a "new release"
      0     0    still released
    Sample the switches at a decent debounce interval (16 to 25 msecs) either in your main program loop or in a timer based interrupt service routine. You only need a few lines of code to implement the switch state logic for multiple switches (perhaps one of the PBP gurus can interpret the C code? Sorry!);

    Code:
    //  swnew  ____---____-----_____   new switch sample
    //  swold  _____---____-----____   switch state latch
    //  delta  ____-__-___-____-____   changes, press or release
    //  newhi  ____-______-_________   filter out release bits
    //
    
    while(1)                  //
    {                         //
      delay_ms(24)            // 24-msec debounce interval
      swnew = ~porta;         // sample active-lo switches
      swnew &= 0x0F;          // on RA3..RA0 pins
      swnew ^= swold;         // changes, press or release
      swold ^= swnew;         // update switch state latch
      swnew &= swold;         // filter out "new release" bits
      if(swnew)               // if any "new press" bits
      { beep();               // task a "new press" beep
      }
      
      if(swnew.0)             // if RB0 "new press"
      {                       //
      }                       //
    
      if(swnew.1)             // if RB1 "new press"
      {                       //
      }                       //
    }
    If you implement the method in an ISR you'll need to inclusive-or "swnew" with a "flags" register for your main program.

    Kind regards, Mike
    Last edited by Mike, K8LH; - 31st July 2010 at 01:57.

  7. #7
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    The code below was written to use a momentary pushbutton switch as an ON/OFF control.

    It is written to be used in a Timer interrupt routine.

    PowerOnDelayTimer is the number of interrupts that the button must be held before turning ON the unit.

    PowerOFFDelayTimer is the number of interrupts that the button must be held before turning OFF the unit

    SwitchUpDelayTimer is the number of interrupts that must expire before the button can be pushed again (useful when you don't want someone rapidly turning ON and OFF a piece of hardware).




    Code:
                IF !EnableSw THEN     ; Aliased pin, goes low when button pushed.
                     
                     IF SwitchFlag THEN ; Switch has been pushed, but prevously released.
                                                   
                       IF PowerSwitchCounter < 250 THEN 
                               PowerSwitchCounter = PowerSwitchCounter + 1  ; don't let it overflow
                       ENDIF 
                            
                                                  
                       IF PowerONstate = 0 THEN  ; Currently OFF
                           If PowerSwitchCounter >= PowerOnDelayTimer then           ; Turn on or off
                              Gosub PowerOn
                              SwitchFlag = 0
                              SwitchUpCounter = 0
                           ENDIF 
                        ELSE      ; Currently OFF
                           If PowerSwitchCounter >= PowerOffDelayTimer then  
                             GOSUB PowerOff
                              SwitchFlag = 0
                              SwitchUpCounter = 0
                          ENDIF
                       ENDIF
           
                    ENDIF
          
                ELSE
                    IF SwitchUpCounter < 250 THEN 
                          SwitchUpCounter = SwitchUpCounter + 1
                    ENDIF      
                    IF SwitchUpCounter > SwitchUpDelayTimer THEN 
                         SwitchFlag = 1          ; Switch has been released
                         PowerSwitchCounter = 0 
                    ENDIF      
               ENDIF
    Charles Linquist

  8. #8
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    I should state that SwitchFlag must be initialized to a non-zero value at the top of the program.
    Charles Linquist

  9. #9
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    I'd like to supplement Charles' fine example with an interrupt driven version of the "parallel switch state logic" example I posted earlier.

    This example uses a 1-msec timer driven interrupt "heart beat" which is perfect for toggling a piezo speaker at 500-Hz and it uses a simple counter to produce a 32-msec debounce/sample interval.

    Using a momentary switch to emulate a "toggle" switch (press to toggle from on-to-off or from off-to-on) can be accomplished directly by the driver by exclusive-or'ing the debounced "new press" bits with the "flags" switch flag bits variable. Main should test the switch flag bit and then clear it for "momentary" switches or simply test the switch flag bit for an emulated "toggle" switch.

    Code:
    void interrupt()                // 1-msec Timer 2 interrupts
    { 
      pir1.TMR2IF = 0;              // clear TMR2 interrupt flag
    //
    //  beep task (32-msec 500-Hz tone using 1-msec interrupts)
    //
      if(beep)                      // if beep task running
      { spkrpin ^= 1;               // toggle speaker pin and
        beep--;                     // decrement beep msec counter
      }
    //
    //  switch state management (multi-switch "parallel" logic)
    //
      if(--dbcount == 0)            // if 32-msec debounce interval
      { dbcount = 32;               // reset debounce timer and
        swnew = ~porta;             // sample active low switches
        swnew &= 0x0F;              // on RA3..RA0 pins
        swnew ^= swold;             // changes, press or release
        swold ^= swnew;             // update switch state latch
        swnew &= swold;             // filter out "new release" bits
        flags ^= swnew;             // toggle flag bits for 'main'
        if(swnew)                   // if any "new press" bits
          beep = 32;                // task a "new press" beep
      }
    }
    Code:
    //  in "main"
    
      while(flags.0)                // while sw0 (RA0) "on" (toggle), do this block
      {                             // until new sw0 press toggles flags.0 to "off"
        if(flags.1)                 // if sw1 (RA1) "new press" (momentary)
        { flags.1 = 0;              // turn off flag and
          ...                       // do something
        }
      }
    Last edited by Mike, K8LH; - 1st August 2010 at 01:04.

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts