samedi 25 janvier 2014

Boutons sans rebond (bascules de Schmitt)

Supposons que vous désirez allumer et éteindre une LED au moyen d'un seul bouton poussoir:  la LED s'allumera si vous appuyez sur le bouton, et s'éteindra lorsque vous appuierez à nouveau sur le même bouton.

Toutefois, lors de la mise à l'essai de votre circuit, vous constatez que la LED réagit de façon aléatoire à vos commandes:  une fois sur deux, il ne se passe rien lorsque vous appuyez sur le bouton!

La raison:  votre bouton poussoir rebondit à la manière d'un ballon de basket.  Pendant une fraction de seconde, l'interrupteur se met successivement en état "fermé" et "ouvert" plusieurs fois de suite... Même si vous n'avez appuyé qu'une seule fois sur le bouton, le reste du circuit a reçu plusieurs signaux consécutifs en provenance de l'interrupteur.

Si votre bouton poussoir est relié à un microcontrôleur (Arduino, par exemple), la solution anti-rebond généralement préconisée est purement logicielle:  lorsque le microcontrôleur détecte que le bouton est pressé, on le fait attendre quelques dizaines de millisecondes, le temps que les rebonds soient terminés (voir le sketch fourni avec l'IDE Arduino:  Fichier - Exemples - 02.Digital - Debounce).

Mais je n'aime pas trop cette solution:  elle alourdit le code, et pour des raisons qui demeurent nébuleuses, je n'obtiens pas toujours des résultats impeccables lorsque je l'applique.  De plus, on n'a pas le choix de procéder autrement si le bouton actionne autre chose qu'un microcontrôleur (une bascule, par exemple).

Pour toutes ces raisons, j'ai assemblé un module comportant 6 boutons munis d'un circuit anti-rebond.  Chaque bouton est associé à un condensateur de 10 nanofarads et à une résistance de tirage ("pull up") de 10 kΩ.

Lorsque le bouton n'est pas enfoncé, aucun courant ne peut circuler dans la résistance et cette dernière n'est donc soumise à aucune différence de potentiel; le condensateur est chargé, puisqu'il est soumis à une différence de potentiel de 5 V (le signal de sortie est de 5 V).   Lorsqu'on appuie sur le bouton, le signal de sortie chute à 0, mais pas instantanément, car le condensateur doit d'abord se décharger.  Lors d'un rebond du bouton, le contact est trop bref pour que le condensateur ait le temps de se décharger et le signal de sortie n'a pas le temps de descendre à zéro.

Un problème demeure:  nous voulons quand même obtenir à la sortie un signal logique qui passe brusquement de 5 V à 0 V, et non un signal qui varie progressivement de 5 V à 0 V (la courbe de décharge est de forme exponentielle).  La solution:  une bascule de Schmitt.  Aussi longtemps que le signal de sortie du bouton est supérieur à un certain seuil, la sortie de la bascule de Schmitt sera à 0 V.  Et la sortie de la bascule de Schmitt passera soudainement à 5 V lorsque le signal de sortie du bouton descendra en-dessous du seuil.  De plus, la bascule de Schmitt est munie d'une hystérésis:  le seuil d'un signal décroissant est plus bas que celui d'un signal montant, pour éviter qu'un signal d'entrée très rapproché du seuil cause une instabilité à la sortie.



Les circuits intégrés CD40106 et 74C14 comportent 6 bascules de Schmitt, alors aussi bien y associer 6 boutons.  Mon circuit complet comporte donc un CD40106, 6 boutons poussoir, 6 résistances de 10K et 6 condensateurs de 10n.   Après avoir relié ensemble tous les 5 V, et relié ensemble tous les GND, le module comporte 8 connections vers l'Arduino:  5 V, GND et une sortie pour chacun des boutons.

J'ai testé mes 6 boutons sans rebond avec un Arduino et le sketch ci-dessous:  résultat impeccable.



Ma source d'inspiration principale pour ce projet:  How to debounce a switch using CMOS and TTL

Yves Pelletier (Twitter:  @ElectroAmateur)

1 commentaire:

  1. C'est génial. Il y a longtemps que je cherchais une solution à mon problème et je l'ai enfin trouvé. Merci

    RépondreSupprimer