Interrupteur poussoir et filtre anti rebonds

Un des problèmes classiques en électronique numérique est le phénomène de rebonds sur ouverture ou fermeture d’un interrupteur, d’un poussoir. Nous proposons ici de mettre en évidence le phénomène, puis de voir comment s’en affranchir par mise en place d’un filtre logiciel anti-rebonds.

Mise en évidence du phénomène de rebond

Considérons le montage suivant:

  • Un carte WeMos D1 mini;
  • Un poussoir entre masse et pin D3 (ce dernier ayant une résistance de pull up interne);
  • Une LED rouge entre pin D0 avec résistance entre 60Ω et 1700Ω intercalé.

Petit aparté sur la présence de la résistance. Elle est souvent omise dans les montages que l’on trouve alimenté par du 3.3V comme ici. Elle est pourtant nécessaire pour être sûr de ne pas claquer la LED.

Notre but est de changer l’état de la LED sur pression du poussoir.

Commençons pas le sketch simple suivant:

// constantes
const int buttonPin = D3;   // numéro du pin poussoir
const int ledPin = D0;      // numéro du pin led

// variables
int buttonState;            // lecture courante de l'état du poussoir
int ledState = LOW;         // état courant de la led

void setup() {
  // configure le pin LED en sortie
  pinMode(ledPin, OUTPUT);
  // configure le pin du poussoir en entrée et active la résistance de pull-up
  pinMode(buttonPin, INPUT_PULLUP);

  // éteind la led au démarrage
  digitalWrite(ledPin, ledState);
}

void loop() {
  // lit l'état courant du poussoir
  buttonState = digitalRead(buttonPin);

  // Si le poussoir est pressé, inverse l'état de la led
  // A cause de la résistance de pull up, l'état du poussoir est
  // inversé: état LOW lorsque le poussoir est passant (enfoncé).
  if (buttonState == LOW) {
    ledState = !ledState;
  }

  digitalWrite(ledPin, ledState);
}

Le téléverser sur la carte WeMos et utiliser le poussoir. L’état de la LED après pression et relâchement du poussoir est aléatoire, à cause du phénomène de rebond. Lorsque le poussoir est pressé, la transition à passant n’est pas franche : pendant quelques millisecondes l’état du poussoir va oscillé entre passant et non passant. Selon le moment où le sketch lit l’état du poussoir, le résultat ne sera pas identique.

Filtrage logiciel des rebonds

Le principe du filtrage logiciel est d’attendre quelques dizaines de ms avant de lire l’état du poussoir sur détection de transition.

Téléverser le sketch suivant sur le même montage que précédemment:

// constantes
const int buttonPin = D3;                 // numéro du pin poussoir
const int ledPin = D0;                    // numéro du pin led
const unsigned long debounceDelay = 20;   // temps de filtrage du bouton (en ms)

// variables
int buttonReading;          // lecture courante de l'état du poussoir
int buttonState;            // état stabilisé courant du poussoir
int ledState = LOW;         // état courant de la led

unsigned long lastDebounceTime = 0;  // dernière date de changement d'état du poussoir

void setup() {
  // configure le pin LED en sortie
  pinMode(ledPin, OUTPUT);
  // configure le pin du poussoir en entrée et active la résistance de pull-up
  pinMode(buttonPin, INPUT_PULLUP);

  // éteind la led au démarrage
  digitalWrite(ledPin, ledState);

  // initialise la lecture courante 
  buttonReading = digitalRead(buttonPin);
}

void loop() {
  // lit l'état courant du poussoir: si changement, réinitialise la période de filtrage
  // et mémorise la nouvelle valeur
  if (buttonReading != digitalRead(buttonPin)) {
    lastDebounceTime = millis();
    buttonReading = !buttonReading;
  }

  // Si la période de filtrage est passée
  if ((millis() - lastDebounceTime) > debounceDelay) {

    // si l'état courant du poussoir est différent du dernier état stabilisé
    if (buttonReading != buttonState) {
      buttonState = buttonReading;

      // si le poussoir est pressé, change l'état de la LED
      if (buttonState == LOW) {
        ledState = !ledState;
      }
    }
  }

  // passe la LED à l'état voulu
  digitalWrite(ledPin, ledState);
}

Le poussoir réagit maintenant comme souhaité: à chaque pression, l’état de la LED est inversée. Et le délai de 20ms avant lecture de l’état n’est absolument pas perceptible à l’utilisation.

La librairie Bounce2

Maintenant que le principe est compris, ainsi que la méthode pour s’en affranchir, nous aimerions bien avoir une librairie effectuant le travail de filtrage, afin de l’utiliser dans les sketchs et avoir un code plus facile à lire.

Cette librairie existe, il s’agit de Bounce2.

Pour l’installer, sous l’IDE Arduino, cliquer sur Croquis > Inclure une bibliothèque > Gérer les bibliothèques. Taper bounce dans le champ de recherche, sélectionner Bounce2 et Installer.

Le sketch précédent devient alors:

#include <Bounce2.h>

// constantes
const int buttonPin = D3;                 // numéro du pin poussoir
const int ledPin = D0;                    // numéro du pin led
const unsigned long debounceDelay = 20;   // temps de filtrage du bouton (en ms)

// variables
Bounce buttonBounce = Bounce();           // objet bouton filtré
int ledState = LOW;                       // état courant de la led

void setup() {
  // configure le pin LED en sortie
  pinMode(ledPin, OUTPUT);
  // configure le pin du poussoir en entrée et active la résistance de pull-up
  pinMode(buttonPin, INPUT_PULLUP);

  // éteind la led au démarrage
  digitalWrite(ledPin, ledState);

  // attache le poussoir à l'objet Bounce, et configure la durée de filtrage
  buttonBounce.attach(buttonPin);
  buttonBounce.interval(debounceDelay);
}

void loop() {

  // lit l'état courant du poussoir: si changement, réinitialise la période de filtrage
  // et mémorise la nouvelle valeur
  if (buttonBounce.update() && buttonBounce.read() == LOW) {
        ledState = !ledState;
  }

  // passe la LED à l'état voulu
  digitalWrite(ledPin, ledState);
}