This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Debounce Logic

I have done software debounce logic with 2/3 voter logic
and kindly verify the coding i don't no whether it is correct or not. Please help me

Coding:

void inputRoutine()
{
 uint16_t temp;
 InputP1_Temp=P1&0x00;
 for(Index1=0;Index1<MAXINPUTS;Index1++)
 {
    temp=debounce(Index1);
        if(temp==1)
        {
        Input_TableP1[Index1]=1;
        }
        else if(temp==0)
        {
                 Input_TableP1[Index1]=0;
        }
  }
}

/*****************
-- Debounce Port P1 --
*****************/

bit debounce(uint16_t IN_INDEX)
{
 uint16_t INDEX2,ONE=0,ZERO=0;
 char  TEMP,SHIFT_RESULT[3]=0x00;
  for(INDEX2=0;INDEX2<3;INDEX2++)
   {
                 TEMP= P1;
         SHIFT_RESULT[INDEX2]=(TEMP>>IN_INDEX)& 0x01;
                 delay_10micro_sec();
   }

   /* Comparision of 3 values retreived from same pin*/

   for(INDEX2=0;INDEX2<3;INDEX2++)
   {
        if(SHIFT_RESULT[INDEX2]==1)
                   ONE++;
        else if(SHIFT_RESULT[INDEX2]==0)
                   ZERO++;
   }
   return (ONE>ZERO);
}

With Thanks,
G.Karthik Ragunath

Parents Reply Children
  • Yes, I'm defending Erik too here.

    Any solution that takes multiple samples of an input and produces a filtered output is affected by the time strata. It doesn't matter if the time strata comes from a timer, or is a "best case" busy-loop. Any code change that may affect the size of the time strata may affect the function and requires the code to be retested.

    A busy-loop requiring two or three consecutive samples to be identical can be too fast just because of additional compiler optimization. Or can become too slow because a code change results in a background ISR starting to consume a relevant percentage of the total processor capacity. A timer is least likely to randomly change speed - and when the processor load gets so high that you can't service every timer tick then you normally have bigger problems than just properly debouncing the keyboard.

    I normally name the variables used by the timer functions so they specify the tick period or tick frequency (depending on how the variables are used) of the involved timer.

    When I change the frequency of a timer (by changing a define) I then also visit the timer ISR and renames all variables updated by the ISR.

    A variable "keyboard_deboucne_10ms_ticks" may get renamed to "keyboard_debounce_5ms_ticks" which forces me to verify all code that accesses this variable. Most of the time, it is enough to change the variable name on these other locations too, since they normally gets their assigned values computed from the same define that specified the timer period or timer frequency.

  • [I was bored, again...]

    This works just fine for debouncing mechanical contacts. This example uses eight samplings and is not exactly a 'majority vote' type, but rather a filter type.

    This algorithm is not a new or original one. I don't remember where I got it, but its been around for a while...

    ////////////////////////////////////////////////////////////////////////////
    //                                                                        //
    //      #define the world according to C                                  //
    //                                                                        //
    ////////////////////////////////////////////////////////////////////////////
    #define LEADING_ZERO    0x7F    // 0111.1111 Used to caputure new-assertions
    
    #define ALL_ONES        0xFF    // 1111.1111 Used to detect a 'held' state
    
    #define LOCK_INPUT      (P1_0)  // Ref: hardware definition of the button
    #define BEEP_INPUT      (P1_1)  // Ref: hardware definition of the button
    
    #define LOCK_ASSERTED   0       // Asserted means a logic low (0 volts)
    #define BEEP_ASSERTED   0       // Asserted means a logic low (0 volts)
    
    #define BUTTON_LOCK     1       // For the switch/case construct to access
    #define BUTTON_BEEP     2       //  or select the state of the button
    
    #define SARDINE         0           // NOTE: after studying  this fish, it
    #define ERIK            (!SARDINE)  //  is basically impossible to hurt a
                                        //  sardine's feelings: a hearty fish
                                        //  that can handle the humor (!Humour).
    
    #define TRUE            (ERIK)      // per erik
    #define FALSE           (!ERIK)     // per others
    
    
    ////////////////////////////////////////////////////////////////////////////
    //                                                                        //
    //      Allocate the 'global' data-stores                                 //
    //                                                                        //
    ////////////////////////////////////////////////////////////////////////////
    bit Lock_Signal;    // TRUE == Asserted Signal
    bit Beep_Signal;    // TRUE == Asserted Signal
    
    bit New_Lock;       // TRUE == Newly asserted & Sticky
    bit New_Beep;       // TRUE == Newly asserted & Sticky
    
    
    /*
    **======================================================================
    **      Scan_Buttons
    **======================================================================
    **
    **  Read in each bit and shift it into a data-store.  This shall form
    **  a stream of bits representing the 1's and 0's as the signal is
    **  asserted--complete with the debouncing of the signal:
    **
    **  Stream:      0001110101000111111111111111111111
    **
    **  The byte value  '11010100' as the stream passed through it.
    **
    **  Check for the value of 7Fh where the leading zero represents the
    **  'off' state (or one of the last non-asserted value), and the
    **  111.1111 part represents a 'steady-state' assertion.
    **
    **  When this is captured (the 7Fh) it occurs once during the sampling
    **  of the stream and represents a fresh signal assertion.  When the value
    **  is FFh, then it is a continuously asserted signal.
    **
    **            0001110101000111111111111111111111
    **                      00011111
    **                       00111111
    **                        01111111  = 7Fh = match (newly pressed)
    **                         111111111      = on    (statically held)
    **                          111111111     = on    (statically held)
    **
    **  This requires this routine to be called at an interval which
    **  can provide the timing resolution expected for system operations.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      <void>
    **  Parameters Returned:    <void>
    **  Notes:
    **          1) This is expected to be in an ISR called from a time-base
    **
    **          2) This algorithm is common and well known (nothing origional)
    **
    **          3) The lack of new-lines and open/close braces were
    **             imposed due to the easy addition/deletion of 'buttons'
    **
    **----------------------------------------------------------------------
    */
    void Scan_Buttons( void )
    {
        /*------------------------------------------------------------------.
        ; 8-bits of data store for each signal is used for the shifting     ;
        ; process.  8 x (call interval) = max detect time.                  ;
        '------------------------------------------------------------------*/
        static u8 lock_byte = 0x00; // (legit use of 'at-file-scope')
        static u8 beep_byte = 0x00; //
    
        /*------------------------------------------------------------------.
        ;  Read in the buttons (Signal is #def'd as a port I/O pin)         ;
        '------------------------------------------------------------------*/
        if( LOCK_INPUT ^ (!LOCK_ASSERTED) ) lock_byte |= 1;
        if( BEEP_INPUT ^ (!BEEP_ASSERTED) ) beep_byte |= 1;
    
        /*------------------------------------------------------------------.
        ; Detect the first edge of signal assertion: declare a new signal   ;
        ;-------------------------------------------------------------------;
        ; We are looking for the front 0 followed by the 1's: 0111.1111     ;
        '------------------------------------------------------------------*/
        if( lock_byte == LEADING_ZERO ) New_Lock = TRUE; // These are sticky-
        if( beep_byte == LEADING_ZERO ) New_Beep = TRUE; // bits (reset manually)
    
        /*------------------------------------------------------------------.
        ; Check for static state signal                                     ;
        ;-------------------------------------------------------------------;
        ; We are looking for all 1s.  A static set of 1s = pressed for XmS  ;
        '------------------------------------------------------------------*/
        if( lock_byte == ALL_ONES ) Lock_Signal = TRUE; else Lock_Signal = FALSE;
        if( beep_byte == ALL_ONES ) Beep_Signal = TRUE; else Beep_Signal = FALSE;
    
        /*------------------------------------------------------------------.
        ; Shift them for next iteration                                     ;
        '------------------------------------------------------------------*/
        lock_byte  <<=  1;
        beep_byte  <<=  1;
    }
    
    
    

  • [continued]

    /*
    **======================================================================
    **      Check_Button            [ ACCESSOR ]
    **======================================================================
    **
    **  Checks if the signal selected is asserted by simply accessing the
    **  Button_Scan assigned data-stores.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      (u8) button number #defined
    **  Parameters Returned:    (bit) TRUE = Asserted
    **  Notes:
    **          1) The lack of new-lines and open/close braces were
    **             imposed due to the easy addition/deletion of 'buttons'
    **
    **          2) Doesn't return TRUE upon detection of a new assertion.
    **             (modify if you need that included)
    **
    **----------------------------------------------------------------------
    */
    bit Check_Button( u8 button )
    {
        u8   pressed;
    
        pressed  = FALSE; // although assigned in the switch( ), ensure it here
    
        /*------------------------------------------------------------------.
        ; If the selected input is TRUE, return TRUE (else FALSE)           ;
        '------------------------------------------------------------------*/
        switch( button )
        {
            case BUTTON_LOCK: if( Lock_Signal == TRUE ) pressed = TRUE; break;
            case BUTTON_BEEP: if( Beep_Signal == TRUE ) pressed = TRUE; break;
    
            default:
                        pressed = FALSE;
                break;
        }
    
        /*------------------------------------------------------------------.
        ; (bit) { TRUE | FALSE }                                            ;
        '------------------------------------------------------------------*/
        return( pressed );
    }
    
    
    /*
    **======================================================================
    **      main
    **======================================================================
    **
    **  The Ultra-Lame main-line routine to illustrate the [very common]
    **  debounce algorithm.
    **
    **----------------------------------------------------------------------
    **
    **  Parameters Passed:      <void>
    **  Parameters Returned:    <void>
    **  Notes:
    **
    **      This was extracted from prior artwork and NOT compiled,
    **      so if this doesn't compile without errors, I don't care: its
    **      an example of the algorithm and its usage.  This algorithm
    **      as worked for me in the past, so it might work for you.
    **
    **----------------------------------------------------------------------
    */
    void main( void )
    {
        bit     button; // for testing the state of the button
    
        /*------------------------------------------------------------------.
        ;  Initialize the system's states                                   ;
        '------------------------------------------------------------------*/
        Lock_Signal = FALSE;
        Beep_Signal = FALSE;
    
        New_Lock    = FALSE;
        New_Beep    = FALSE;
    
        /*------------------------------------------------------------------.
        ;  Do it forever                                                    ;
        '------------------------------------------------------------------*/
        while( GOD_PARTICLE != FOUND  )
        {
            /*--------------------------------------------------------------.
            ;  This is typically put into a timer ISR for a predictable dt  ;
            '--------------------------------------------------------------*/
            Delay_X_mS( KEYBOARD_DEBOUNCE_5mS_TICKS ); // you do the routine
    
            Scan_Buttons( );
    
            /*--------------------------------------------------------------.
            ;  Is there somebody at the door?                               ;
            '--------------------------------------------------------------*/
            button = Check_Button( BUTTON_BEEP );
    
            if( button != FALSE )
            {
                beep( );    // Wake up the sentry
            }
    
            /*--------------------------------------------------------------.
            ;  If they are to be 'buzzed in' then do it.                    ;
            '--------------------------------------------------------------*/
            button = Check_Button( BUTTON_LOCK );
    
            if( button != FALSE )
            {
                Unlock( );  // Button must be held while opening door
            }
            else
            {
                Lock( );    // make sure it returns to the secured position
            }
        }
    }
    
    
    
    /*===========================================================================
    *       END OF MODULE ( Debounce_Example.C )
    ===========================================================================*/
    

    (if you do find errors, please let me know).

    --Cpt. Vince Foster
    2nd Cannon Place
    Fort Marcy Park, VA

  • hmmmm...you know...there is a lot to be said for a resistor and a cap next to the switch!

    R

  • A resistor and a cap will change the behaviour. But if the input pin doesn't have schmitt-trigger, then the bounces can still get the filtered signal to vary enough to make the input signal toggle multiple times between low and high.

    As a matter of fact - all uses of external RC filters should be avoided unless the input has hysterese. Not only can you get multiple toggles, you can also get the input to consume a lot of power when floating in the dead zone between a logic high and a logic low.

    Besides: A software bug can be corrected by a firmware update. A hw problem - such as too high/low value on a component - is very hard to compensate for. You may have to send the unit in for modification.

    The important thing here is that most mechanical switches are quite easy to debounce since the bounce time is short in relation to the expected number of switch activations/second. And since the debounce is so easy to do in software, there is no real need to figure out ways to let the hardware help.

  • As a matter of fact - all uses of external RC filters should be avoided unless the input has hysterese.
    one more reason to avoid RC filters is that it slows down the input. Many moons ago (before the micro, with a mini) I did some investigation on RC filtering and found that (for this particular app, how general I do not know) sufficient RC filtering made the thingy fail to respnd to the "fastest fingers"

    And since the debounce is so easy to do in software, there is no real need to figure out ways to let the hardware help.
    I second that opinion

    Erik