Anti-rebonds

Généralités

Les dispositifs de commutation mécaniques comme les interrupteurs ou les boutons poussoirs, de par leur conception, ont tendance à délivrer une série d’impulsions parasites quand on les actionne.

Ci-dessous figure un oscillogramme relevé aux bornes d’un interrupteur que l’on actionne. On voit bien que le passage de l’état fermé à l’état ouvert n’est pas franc.

bounces

Même si ces états intermédiaires — apelés rebonds — ne sont pas détectables à l’échelle humaine, ils le sont pour les circuits électroniques et seront donc considérés comme autant d’ouvertures ou fermetures de circuits. Ceci peut avoir des conséquences plus ou moins graves au niveau des dispositifs que ces interrupteurs, boutons poussoirs…​ commandent. Ex. : diminution de la durée de vie d’un relais (si celui-ci a un temps de réponse en accord avec la fréquence des rebonds c.-à-d. quelques ms).

Solution logicielle

L’élimination des rebonds passe souvent par une solution matérielle (→ circuit RC, trigger de Schmitt).

Cependant, outre le fait que cette solution matérielle rend le circuit électronique plus complexe et donc plus cher à fabriquer, elle autorise aussi moins de souplesse qu’une solution logicielle.

De toute façon, qu’elle soit matérielle ou logicielle, il vaudra toujours mieux se référer à des solutions éprouvées qu’à chercher par soi-même à éliminer ces rebonds car cela n’est pas aussi facile qu’il n’y parait.

La solution logicielle présentée dans la librairie Arduino DebounceInput link donne, selon son auteur, de bons résultats.

Elle s’inspire de l’algorithme présenté dans l’article Elegant debouncing solution with software Schmitt trigger emulation link

Contrairement aux idées reçues, on recommande de ne pas détecter le changement d’état d’un interupteur ou bouton poussoir via une broche d’interruption d’un processeur car ceci peut amener à consommer du temps machine inutilement.

Always avoid connection of mechanical contacts to interrupt inputs unless the contacts undergo hardware debouncing. Otherwise, the contacts may bounce dozens of times, unnecessarily consuming processor-machine cycles. The software routine reads the inputs only every 4 msec and thus imposes additional filtering on the inputs.
— Elio Mazzocca
Contact-debouncing algorithm emulates Schmitt trigger

Liens

  • 👍 Vidéo de M.Hortolland sur les rebonds en sortie d’interrupteurs ou de boutons-poussoirs et sur le moyen pour les supprimer sur un microcontrôleur PIC

  • 👍 Debouncing and Throttling Explained Through Examples link

    → Article qui illustre 2 techniques d’anti-rebonds (debounce vs. throttle) dans le domaine du développement web

  • Contact-debouncing algorithm emulates Schmitt trigger link

    Listing 1
    debounce.asm
    /*************************************************************************
    **                         **
    **       THE ULTIMATE SOFTWARE DEBOUNCER        **
    **                         **
    ** Program: debounce.asm                  **
    ** Version: 1.0                        **
    ** Date:    5/5/2005                   **
    ** Author:  Elio Mazzocca                 **
    ** E-mail:  jnz9876@adam.co.uk                  **
    **                         **
    ** micro used: ATmega8 with internal 4 MHz oscillator       **
    ** assembled with: AVR Studio 4.0               **
    ** Timer0 interrupt period: 4 mSEC              **
    **                         **
    ** Description: This is a 1st order recursive digital filter      **
    **    with Schmitt trigger output that filters noisy     **
    **    digital inputs to ATmega8 microcontroller.      **
    **    The formula employed for the recursive filter:     **
    **                         **
    **    ynew = 1/4 xnew + 3/4 yold          **
    **                         **
    **    Formula for an inverting Schmitt trigger:    **
    **                         **
    **    if(ynew>hi) and (flag=0) then flag=1; vout=1;      **
    **    if(ynew<lo) and (flag=1) then flag=0; vout=0;      **
    **                         **
    ** Use:     The code is placed in Timer0 interrupt routine     **
    **    with a 4 mSEC period. The output of the trigger    **
    **    is continuously checked in the main program loop   **
    **    The interrupt routine checks the PORT bit and      **
    **    applies either 0 (keypress) or $3F to the digital  **
    **    filter, the output value is then applied to a      **
    **    Schmitt trigger with thresholds of 15, 240 for     **
    **    an effective "time constant" of 11 interrupts.     **
    **    Program requires 11 ints, 19/18 machine cycles,    **
    **         6 ints if schmitt threshold is $3C instead of $0F   **
    **                         **
    ** Input stimuli: pind0.sti                  **
    ** Output log:    portb.log                  **
    *************************************************************************/
    ;
    .NOLIST
    .INCLUDE "AvrAssembler2\appnotes\m8def.inc"
    .LIST
    
    ; Register defines
    
    .DEF  yold = R17        ; old/new filter output value, share same reg
    .DEF  tmp  = R18        ; new input to filter value/threshold reg
    .DEF    flag = R19
    .DEF    VOUT = R20
    
    .CSEG
    .ORG $0000
       rjmp  Reset
    
    .ORG OVF0addr
       rjmp  tim0_ovf    ; Timer0 overflow handler
    
    Reset:
       ldi   R16,  LOW(RAMEND)    ; Initiate Stackpointer
       out   SPL,  R16      ; for use by interrupts
       ldi   R16,  HIGH(RAMEND)
       out   SPH,  R16
    
       ldi   R16,  (1<<CS01)|(1<<CS00)  ; Fosc = 4 MHz
       out   TCCR0,   R16      ; set Timer/Counter0 Prescaler=64, int = 16x256 uSEC
    
       ldi   R16,  (1<<TOIE0)  ; set timer0 interrupt enable
       out   TIMSK,   R16      ; in the Timer Interrupt Mask Register
       ldi     R16,    (1<<TOV0)     ; clr pending interrupts
          out     TIFR,   R16
    
       ser   tmp
       out   DDRB, tmp      ; set PORTB = output
       clr   tmp
       out     DDRD,   tmp     ; set PORTD = input
       ser     tmp
       out     PORTD,  tmp     ; turn on PORTD pull-ups
    
       ldi   yold,   $FF    ;optional
       sei            ; enable interrupts
    loop:             ; main program loop
       sbrs    VOUT,   0    ; if schmitt out = 1
       rjmp  a1
       sbi     PORTB,  0    ; then set PORTB, bit 0 - LED on
       rjmp    loop
    a1:
       cbi     PORTB,  0    ; else clear PORTB, bit 0 - LED off
          rjmp    loop
    ;------------------------------------------------------------------------
    tim0_ovf:
          mov     tmp,    yold
       lsr     tmp
       lsr     tmp       ; tmp = 1/4 yold
       sub     yold,   tmp     ; 3/4 yold is in left in reg yold
       ldi     tmp,    $3F     ; re-use tmp register for xnew
       sbis    PIND,   0    ; if PIND bit 0 = 0, then input = 1/4 xnew
       clr     tmp
       add   yold,   tmp    ; yold same as ynew, saves 1 instruction/register !
    
    .UNDEF tmp           ; re-use tmp register as threshold reg.
    .DEF   thresh = R18
                   ; now apply filter output to schmitt trigger
       ldi     thresh, $0F     ; load lo thresh into threshold register
       sbrc  flag,   0         ; test bit 0 of flag register
       rjmp    s1
       cp      yold,   thresh
       brsh    s1
       sbr     flag,   (1<<0)     ; set bit 0 of register flag
       sbr     VOUT,   (1<<0)
    s1:
       swap    thresh       ; to test hi thresh, swap nibbles
       cp      yold,   thresh
       brlo    s2
       cbr     flag,   (1<<0)
       cbr     VOUT,   (1<<0)     ; clear bit 0 of register VOUT
    s2:
       reti           ; 19/18 (nokeypress/keypress) machine cycles
    ;------------------------------------------------------------------------
    .EXIT
  • debounce code link

    Article de la newsletter “The Embedded Muse” qui propose un code source en C pour gérer l’anti-rebond et qui s’inspire de celui de l’article précédent

  • Debouncing Switches link

🞄  🞄  🞄