{"id":77,"date":"2013-04-04T17:17:35","date_gmt":"2013-04-04T15:17:35","guid":{"rendered":"http:\/\/pila.fr\/wordpress\/?p=77"},"modified":"2014-06-24T12:19:11","modified_gmt":"2014-06-24T10:19:11","slug":"microcontroleurs-et-boutons-poussoirs-anti-rebonds-et-appui-long","status":"publish","type":"post","link":"https:\/\/pila.fr\/wordpress\/archives\/77","title":{"rendered":"Microcontr\u00f4leurs et boutons poussoirs : anti-rebonds et appui long"},"content":{"rendered":"<p>Si les boutons poussoirs sont des composants tr\u00e8s simples \u00e0 utiliser, ils poss\u00e8dent tout de m\u00eame un inconv\u00e9nient de taille, ils sont sujets aux <strong>rebonds<\/strong>, c&rsquo;est \u00e0 dire qu&rsquo;ils ont la d\u00e9sagr\u00e9able habitude de ne pas passer directement de leur \u00e9tat ouvert \u00e0 leur \u00e9tat ferm\u00e9. Pendant une dur\u00e9e g\u00e9n\u00e9ralement inf\u00e9rieure \u00e0 la milliseconde, il va en effet osciller plusieurs fois entre les deux \u00e9tats :<\/p>\n<div style=\"width: 546px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/pila.fr\/content\/MCU_button_debouncing\/bouncing_diagram.png\" alt=\"Illustration signal rebonds\" width=\"546\" height=\"166\" \/><p class=\"wp-caption-text\">Allure du signal obtenu lors de l&rsquo;appui sur un bouton poussoir.<\/p><\/div>\n<p>Si cela ne pose pas de probl\u00e8me pour des applications simples, par exemple allumer une LED, ou commander un relais par le biais d&rsquo;un transistor, cela en pose en revanche avec les circuits fonctionnant sur changement d&rsquo;\u00e9tat d&rsquo;un signal, ceux-ci risquant d\u2019interpr\u00e9ter chaque rebond comme un appui sur le bouton. je vous propose de d\u00e9couvrir plusieurs m\u00e9thodes pour \u00e9viter ces d\u00e9sagr\u00e9ments.<\/p>\n<p><!--more--><\/p>\n<h3 style=\"padding-left: 30px;\">Anti-rebonds mat\u00e9riel : circuit RC<\/h3>\n<p>La solution la plus simple pour s&rsquo;affranchir des probl\u00e8mes de rebonds, est d&rsquo;ins\u00e9rer le bouton dans un circuit RC :<\/p>\n<div style=\"width: 547px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/pila.fr\/content\/MCU_button_debouncing\/RC_debouncing_diagram.png\" alt=\"Illustration anti-rebond RC\" width=\"547\" height=\"202\" \/><p class=\"wp-caption-text\">Anti-rebonds simple \u00e0 base de circuit RC.<\/p><\/div>\n<ol>\n<li>A gauche se trouve le sch\u00e9ma typique pour g\u00e9n\u00e9rer un signal logique gr\u00e2ce \u00e0 un bouton poussoir. Soit le bouton est rel\u00e2ch\u00e9, et on retrouve la tension Vcc en sortie, \u00e0 travers la r\u00e9sistance. Soit le bouton est appuy\u00e9, et la sortie est reli\u00e9e \u00e0 la masse.<\/li>\n<li>Au milieu, c&rsquo;est un circuit RC basique. Le condensateur se charge \u00e0 travers la r\u00e9sistance, donc lors de la mise sous tension, la tension en sortie augmente progressivement jusqu&rsquo;\u00e0 atteindre Vcc.<\/li>\n<li>En combinant les 2 montages pr\u00e9c\u00e9dents, on obtient un bouton poussoir dot\u00e9 d&rsquo;un anti-rebonds. En effet, \u00e0 la mise sous tension, le condensateur se charge \u00e0 travers la r\u00e9sistance. Lors d&rsquo;un appui sur le bouton, le condensateur se d\u00e9charge instantan\u00e9ment \u00e0 travers ce dernier ( il faut donc veiller \u00e0 utiliser un condensateur de faible capacit\u00e9, moins d&rsquo;un \u00b5F, pour ne pas endommager le bouton ), mais ne peut pas remonter directement \u00e0 Vcc, car le condensateur se charge doucement \u00e0 travers la r\u00e9sistance. Donc, m\u00eame lors des rebonds, la tension en sortie reste tr\u00e8s proche de 0 V.<\/li>\n<\/ol>\n<p>Il faut toutefois choisir l&rsquo;ensemble r\u00e9sistance\/condensateur de fa\u00e7on judicieuse. La constance de temps du circuit (temps que met la tension en sortie pour remonter \u00e0 2\/3 de Vcc) vaut <strong>R*C<\/strong> o\u00f9 R est la valeur de la r\u00e9sistance et C celle du condensateur. Cette valeur doit \u00eatre grande devant la dur\u00e9e des rebonds (qui est de quelques ms) mais suffisamment faible pour que 2 appuis cons\u00e9cutifs n&rsquo;apparaissent pas comme un appui long. Pour r\u00e9pondre \u00e0 ces crit\u00e8res, 50ms, soit 0.05s semble \u00eatre une valeur tout \u00e0 fait correcte.<\/p>\n<p>On peut maintenant d\u00e9terminer les valeurs de R et C. R doit \u00eatre relativement grande ( sup\u00e9rieure \u00e0 1k\u03a9 ) pour limiter le courant qui circule \u00e0 travers le bouton lorsqu&rsquo;il est appuy\u00e9, et C doit \u00eatre suffisamment faible pour limiter les cons\u00e9quences de la d\u00e9charge du condensateur \u00e0 travers le bouton poussoir.<\/p>\n<p>Je choisi arbitrairement une valeur de C de 100 nF, car c&rsquo;est une valeur courante ( on utilise souvent des condensateurs non polaris\u00e9s de 100 nF plac\u00e9s \u00e0 cot\u00e9 des circuits int\u00e9gr\u00e9s de type CMOS pour lisser la tension d&rsquo;alimentation ). Il reste donc \u00e0 calculer R = 0.05\/C = 0.05\/0.0000001 = 500k\u03a9. La valeur courante de r\u00e9sistance la plus proche est de 470k\u03a9. Avec cette valeur, pour une tension d&rsquo;alimentation Vcc de 5v, l&rsquo;intensit\u00e9 traversant le bouton lorsqu&rsquo;il est appuy\u00e9, est proche de 10 \u00b5A, il n&rsquo;y a donc aucun risque d&rsquo;endommager le bouton. Il ne reste plus qu&rsquo;\u00e0 assembler le circuit, et le tour est jou\u00e9 \ud83d\ude09 .<\/p>\n<p>Cependant, si le bouton est destin\u00e9 \u00e0 \u00eatre connect\u00e9 \u00e0 un microcontr\u00f4leur, pourquoi ne pas int\u00e9grer l&rsquo;anti-rebonds directement dans le programme de ce dernier ? On s&rsquo;affranchirait ainsi de la place occup\u00e9e par le condensateur, et \u00e9ventuellement des co\u00fbts du condensateur, dans le cadre d&rsquo;un circuit produit \u00e0 grande \u00e9chelle.<\/p>\n<p><strong>Si l&rsquo;on utilise un bouton miniature, capable de supporter un tr\u00e8s faible courant, il faut alors rajouter une r\u00e9sistance ( 100\u03a9 environ ) en s\u00e9rie avec le bouton, pour limiter le courant qui y circule lors de la d\u00e9charge du condensateur.<\/strong><\/p>\n<h3>Anti-rebonds logiciel : approche simple<\/h3>\n<p>La solution la plus simple, est d&rsquo;attendre quelques millisecondes avant de relire l&rsquo;\u00e9tat du bouton :<\/p>\n<pre lang=\"c\">if( le bouton vient d \u00eatre appuy\u00e9){\r\n    effectuer l action n\u00e9cessaire\r\n    attendre quelques millisecondes\r\n}<\/pre>\n<p>Cependant, cette solution poss\u00e8de plusieurs inconv\u00e9nients : il faut tout d&rsquo;abord suivre l&rsquo;\u00e9tat du bouton en permanence pour d\u00e9tecter le moment o\u00f9 le bouton vient d&rsquo;\u00eatre appuy\u00e9 ( front descendant du signal ), sans quoi l&rsquo;action se r\u00e9p\u00e9tera tant que le bouton est maintenu appuy\u00e9. De plus, on ne diff\u00e9rencie par un appui bref d&rsquo;un appui maintenu. Je vous propose donc une autre solution bien plus compl\u00e8te, mais \u00e9galement un peu plus complexe.<\/p>\n<h3>Anti-rebonds logiciel : approche compl\u00e8te avec d\u00e9tection d&rsquo;appui long<\/h3>\n<p>Le code ci-dessous a \u00e9t\u00e9 \u00e9crit en C pour un microcontr\u00f4leurs PIC avec le compilateur PICC de hi-tech, mais il est portable tr\u00e8s facilement vers tout autre syst\u00e8me programmable en C :<\/p>\n<pre lang=\"c\">#define BUTTON_POLLING_INTERVAL 20          \/\/intervalles de lecture du bouton, en ms\r\n#define COUNT_DEBOUNCE 10                   \/\/dur\u00e9e maximale autoris\u00e9e de rel\u00e2chement du bouton (en nombre d'intervalles)\r\n#define COUNT_SHORT_PRESS 5                 \/\/dur\u00e9e mini d'un appui court (en nombre d'intervalles)\r\n#define COUNT_LONG_PRESS 50                 \/\/dur\u00e9e d'un appui long (en nombre d'intervalles)\r\n\r\nunsigned int releasedCount = 0;\r\nunsigned totalCount = 0;\r\n\r\n\/\/comptage du temps d appui et anti-rebonds\r\nwhile(totalCount&lt;COUNT_LONG_PRESS){\r\n    tempo(BUTTON_POLLING_INTERVAL);\r\n    if(BUTTONPIN){\r\n        releasedCount=0;\r\n        totalCount++;\r\n    }\r\n    else{\r\n        releasedCount++;\r\n    }\r\n    if(releasedCount&gt;=COUNT_DEBOUNCE){\r\n        break;\r\n    }\r\n}\r\n\r\n\/\/execution des actions apres appui\r\nif(totalCount==COUNT_LONG_PRESS){\r\n    \/\/inserer ici action appui long\r\n    while(BUTTONPIN);\r\n}\r\nelse if(totalCount&gt;COUNT_SHORT_PRESS){\r\n    \/\/inserer ici action appui bref\r\n}<\/pre>\n<ul>\n<li>BUTTONPIN correspond au nom de la broche du microcontr\u00f4leur \u00e0 laquelle le bouton est connect\u00e9.<\/li>\n<\/ul>\n<ul>\n<li>BUTTON_POLLING_INTERVAL correspond \u00e0 intervalle de temps s\u00e9parant 2 lectures de l&rsquo;\u00e9tat du bouton ( en ms ).<\/li>\n<\/ul>\n<ul>\n<li>COUNT_DEBOUNCE permet l&rsquo;anti-rebonds. Multipli\u00e9 par BUTTON_POLLING_INTERVAL, il donne le temps que le signal du bouton doit rester \u00e0 Vcc avant que le bouton soit consid\u00e9r\u00e9 comme rel\u00e2ch\u00e9.<\/li>\n<\/ul>\n<ul>\n<li>COUNT_SHORT_PRESS multipli\u00e9 par BUTTON_POLLING_INTERVAL indique la dur\u00e9e minimum de l&rsquo;appui sur le bouton avant de d\u00e9clencher l&rsquo;action \u00ab\u00a0appui bref\u00a0\u00bb.<\/li>\n<\/ul>\n<ul>\n<li>COUNT_LONG_PRESS multipli\u00e9 par BUTTON_POLLING_INTERVAL indique la dur\u00e9e d&rsquo;appui sur le bouton apr\u00e8s laquelle l&rsquo;action \u00ab\u00a0appui long\u00a0\u00bb est effectu\u00e9e.<\/li>\n<\/ul>\n<h5>Explication du fonctionnement<\/h5>\n<p>La partie majeure du code se situe dans la boucle \u00ab\u00a0while\u00a0\u00bb qui lit r\u00e9guli\u00e8rement l&rsquo;\u00e9tat du bouton. Le programme quitte la boucle si<\/p>\n<ul>\n<li>Le bouton est lu \u00ab\u00a0rel\u00e2ch\u00e9\u00a0\u00bb un nombre COUNT_DEBOUNCE de fois cons\u00e9cutives. On consid\u00e8re alors que le bouton est bien rel\u00e2ch\u00e9.<\/li>\n<li>Le bouton est rest\u00e9 appuy\u00e9 un nombre COUNT_LONG_PRESS de fois. On a alors atteint la dur\u00e9e de l&rsquo;appui long.<\/li>\n<\/ul>\n<p>Une fois cette boucle quitt\u00e9e, le programme regarde combien de fois le bouton a \u00e9t\u00e9 lu comme appuy\u00e9 :<\/p>\n<ul>\n<li>Si le bouton a \u00e9t\u00e9 lu appuy\u00e9 un nombre COUNT_LONG_PRESS de fois, qui correspond \u00e0 un appui long, il effectue l&rsquo;action correspondante \u00e0 un appui long.<\/li>\n<li>Sinon, si le bouton a \u00e9t\u00e9 appuy\u00e9 assez longtemps ( cette valeur est d\u00e9finie par COUNT_SHORT_PRESS ), il effectue l&rsquo;action correspondante \u00e0 un appui bref.<\/li>\n<li>Sinon, c&rsquo;est que le bouton n&rsquo;a pas \u00e9t\u00e9 appuy\u00e9, ou appuy\u00e9s de fa\u00e7on tr\u00e8s ponctuelle, alors le programme ne fait rien.<\/li>\n<\/ul>\n<p>Apr\u00e8s un appui long, le programme attend que le bouton soit rel\u00e2ch\u00e9 avant de continuer.<\/p>\n<p>On a donc un syst\u00e8me qui int\u00e8gre un anti-rebonds, et qui permet de diff\u00e9rencier un appui bref d&rsquo;un appui maintenu, et capable d&rsquo;agir en cons\u00e9quence. Ayant d\u00e9j\u00e0 utilis\u00e9 ce code, je vous conseille les valeurs suivantes pour optimiser son fonctionnement, et le confort d&rsquo;utilisation du bouton :<\/p>\n<ul>\n<li>BUTTON_POLLING_INTERVAL = 20<\/li>\n<li>COUNT_DEBOUNCE = 10<\/li>\n<li>COUNT_SHORT_PRESS = 5<\/li>\n<li>COUNT_LONG_PRESS = 50<\/li>\n<\/ul>\n<p>N&rsquo;h\u00e9sitez pas \u00e0 me faire part de vos questions ou remarques \ud83d\ude09<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Si les boutons poussoirs sont des composants tr\u00e8s simples \u00e0 utiliser, ils poss\u00e8dent tout de m\u00eame un inconv\u00e9nient de taille, ils sont sujets aux rebonds, c&rsquo;est \u00e0 dire qu&rsquo;ils ont la d\u00e9sagr\u00e9able habitude de ne pas passer directement de leur \u00e9tat ouvert \u00e0 leur \u00e9tat ferm\u00e9. Pendant une dur\u00e9e g\u00e9n\u00e9ralement inf\u00e9rieure \u00e0 la milliseconde, il &hellip; <\/p>\n<p><a class=\"more-link btn\" href=\"https:\/\/pila.fr\/wordpress\/archives\/77\">Lire la suite<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[31,33,22,32],"class_list":["post-77","post","type-post","status-publish","format-standard","hentry","category-electronique","tag-bouton","tag-microcontroleur","tag-pic","tag-rebonds","item-wrap"],"_links":{"self":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/77","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/comments?post=77"}],"version-history":[{"count":85,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/77\/revisions"}],"predecessor-version":[{"id":786,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/posts\/77\/revisions\/786"}],"wp:attachment":[{"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/media?parent=77"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/categories?post=77"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pila.fr\/wordpress\/wp-json\/wp\/v2\/tags?post=77"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}