Lire le monde : boutons et capteurs
Ce que ce chapitre apporte
- Lire l'état d'une entrée numérique, et expliquer pourquoi une entrée non reliée rend n'importe quoi.
- Choisir entre une résistance de tirage externe et INPUT_PULLUP, et prévoir la valeur lue au repos et à l'appui.
- Détecter un appui plutôt qu'un état, et compter les appuis sans être trompé par les rebonds.
- Convertir une lecture analogique en tension, et une tension en lecture.
- Ramener une lecture à une autre échelle avec map, en connaissant ses arrondis et ses limites.
Écrire sur une broche est facile : la carte impose 5 V ou 0 V, et la LED obéit. Lire est plus délicat, parce que le monde physique ne se présente pas proprement. Une entrée que rien ne relie flotte et rend n'importe quoi, un bouton qui se ferme rebondit pendant quelques millisecondes, un capteur délivre une tension continue qu'il faut ramener à un nombre. Ce chapitre traite ces trois difficultés, dans l'ordre où elles surviennent.
Une entrée numérique
digitalRead(broche) rend HIGH ou LOW selon la tension présente sur la broche. Sur l'Uno alimentée en 5 V, une tension supérieure à environ 3 V est lue HIGH, une tension inférieure à environ 1,5 V est lue LOW.
Une entrée est flottante quand rien ne la relie à une tension définie. Elle se comporte alors comme une antenne : les parasites, la proximité d'une main, le voisinage d'un fil suffisent à faire changer sa lecture.
Le montage naïf, un bouton entre la broche et le 5 V, produit exactement cette situation. Bouton enfoncé, la broche est à 5 V et lit HIGH. Bouton relâché, elle n'est plus reliée à rien, et sa lecture est indéfinie : elle peut rester haute, retomber, osciller.
La résistance de tirage
La solution consiste à relier la broche, au repos, à une tension connue, à travers une résistance assez forte pour que le bouton l'emporte quand il est enfoncé.
| Montage | Au repos | Bouton enfoncé | Configuration |
|---|---|---|---|
Résistance de 10 kΩ vers GND, bouton vers 5V | LOW | HIGH | pinMode(2, INPUT) |
Résistance interne vers 5 V, bouton vers GND | HIGH | LOW | pinMode(2, INPUT_PULLUP) |
Le second montage est le plus employé : il n'ajoute aucun composant, la résistance étant intégrée au microcontrôleur. Il a une contrepartie, qui trompe systématiquement la première fois : la logique est inversée. Un bouton enfoncé se lit LOW.
Un état n'est pas un appui
Compter les appuis semble simple : incrémenter un compteur quand le bouton est enfoncé. Mais loop() s'exécute des milliers de fois par seconde, et un appui humain dure un dixième de seconde. Tester l'état fait donc compter des centaines d'appuis pour une seule pression.
Ce qu'il faut détecter, c'est le changement d'état : le moment où la lecture passe de relâché à enfoncé. On garde pour cela la lecture précédente, et l'on compare.
Les rebonds
Ce programme compte encore trop, et la raison est mécanique. Quand deux lames métalliques se touchent, elles rebondissent pendant quelques millisecondes : le contact s'établit, se rompt, s'établit de nouveau. Chaque rebond est un vrai changement d'état, que le programme compte comme un appui.
delay(50) juste après avoir compté un appui paraît régler le problème : les rebonds de l'appui tombent pendant la pause. Mais le bouton rebondit aussi quand on le relâche, et ces rebonds-là produisent un nouveau front, compté comme un second appui. Une simulation d'un seul appui avec rebonds donne ainsi 2 au lieu de 1.
La méthode fiable ne se fie pas au premier changement : elle n'accepte un nouvel état que s'il est resté stable pendant un délai fixé, à l'appui comme au relâchement.
Ce programme compte un appui par pression, quels que soient les rebonds, et ignore une impulsion parasite plus courte que 30 ms. Il n'emploie aucun delay : il ne bloque jamais le reste du programme, ce que le chapitre 7 généralise.
Une entrée analogique
Un capteur de température, de lumière, un potentiomètre ne délivrent pas deux états mais une tension continue. Les broches A0 à A5 la mesurent.
analogRead(broche) convertit la tension présente, entre 0 et 5 V, en un entier de 0 à 1023. Le convertisseur travaille sur 10 bits, soit 1024 valeurs possibles.
La convention employée dans ce parcours fait correspondre 5 V à la valeur maximale :
Un palier représente donc environ 4,9 mV : c'est la plus petite variation de tension que la carte puisse distinguer. Une lecture de 512 correspond à 2,50 V, une lecture de 768 à 3,75 V.
Le potentiomètre est le capteur le plus simple : ses deux extrémités vont au 5 V et à la masse, son curseur à A0, et tourner le bouton fait varier la tension du curseur de 0 à 5 V.
Changer d'échelle avec map
Il faut souvent ramener une lecture à une autre échelle : de 0 à 1023 vers 0 à 255 pour piloter une LED, ou vers un pourcentage. map fait cette règle de trois.
map calcule en entiers et tronque : map(768, 0, 1023, 0, 255) rend 191, alors que le calcul exact donne 191,4. Elle ne borne pas non plus son résultat : une valeur hors de l'échelle de départ donne une valeur hors de l'échelle d'arrivée, map(1100, 0, 1023, 0, 255) rendant 274. Quand l'entrée peut sortir de sa plage, constrain ramène le résultat dans les bornes.
Exercices type
Un bouton relie la broche 2 à la masse, configurée en INPUT_PULLUP. Que lit digitalRead au repos, bouton enfoncé, et que lirait-elle en INPUT simple ?
Au repos, la résistance interne tire la broche vers le 5 V : HIGH. Bouton enfoncé, la broche est reliée à la masse : LOW. La logique est inversée par rapport à l'intuition.
En INPUT simple, aucune résistance ne tire la broche au repos : elle flotte, et sa lecture est indéfinie. Le programme peut sembler fonctionner un moment, puis réagir à un appui fantôme quand on approche la main.
Un programme incrémente un compteur dès que digitalRead(2) == LOW. Un appui d'un dixième de seconde fait monter le compteur de plusieurs milliers. Pourquoi, et quelle est la correction ?
Le programme compte un état, pas un appui. loop() tourne des milliers de fois pendant que le bouton est enfoncé, et chaque tour ajoute 1.
La correction compare la lecture courante à la précédente, et ne compte que le passage de HIGH à LOW. Pour ne pas être trompé par les rebonds, ce changement n'est accepté que si la lecture est restée stable une trentaine de millisecondes, à l'appui comme au relâchement.
Un potentiomètre donne une lecture de 768. Quelle tension cela représente-t-il, et que rend map(768, 0, 1023, 0, 255) ?
La tension vaut V.
map calcule et tronque : elle rend 191. Diviser la lecture par 4, un raccourci fréquent, rendrait 192 : les deux méthodes diffèrent d'une unité, ce qui est sans conséquence pour une luminosité, mais pas pour une comparaison à un seuil exact.
Pourquoi un delay(50) placé juste après le comptage d'un appui ne suffit-il pas à supprimer les rebonds ?
La pause absorbe les rebonds qui suivent l'appui. Mais le contact rebondit aussi au relâchement : la lecture repasse brièvement à l'état enfoncé, ce qui fait un nouveau front, compté comme un nouvel appui.
Une seule pression est alors comptée deux fois. La méthode par état stable règle les deux cas à la fois, puisqu'elle attend que la lecture ait cessé de bouger avant d'accepter un changement, dans un sens comme dans l'autre.
Vérification
1.Une broche configurée en INPUT n'est reliée à rien. Que rend digitalRead ?
2.Avec INPUT_PULLUP et un bouton relié à la masse, que lit-on bouton enfoncé ?
3.Pourquoi un bouton mécanique produit-il plusieurs changements d'état pour un seul appui ?
4.Quelle tension correspond à une lecture de 512 ?
5.Combien de valeurs différentes analogRead peut-elle rendre ?
6.Que rend map(1100, 0, 1023, 0, 255) ?
La méthode
- Donner un état de repos à toute entrée numérique :
INPUT_PULLUPavec un bouton vers la masse, ou une résistance de tirage externe. - Écrire la table des états avant le code : ce qui se lit au repos, ce qui se lit à l'appui.
- Détecter les changements, et non les états, dès qu'il s'agit de compter ou de basculer.
- Exiger la stabilité d'une lecture avant de l'accepter, au lieu de s'en remettre à un
delay. - Convertir sur une valeur connue : 512 donne 2,50 V ; vérifier le calcul avant de brancher le capteur.
- Borner avec
constraintout résultat demapdont l'entrée peut sortir de sa plage.
Synthèse
digitalReadrendHIGHau-dessus d'environ 3 V,LOWen dessous d'environ 1,5 V.- Une entrée flottante rend une valeur indéfinie ; une résistance de tirage lui donne un état au repos.
INPUT_PULLUP: pas de composant à ajouter, bouton vers la masse, enfoncé se litLOW.- Compter des appuis, c'est détecter un changement d'état, pas un état.
- Les contacts rebondissent : un changement n'est accepté que s'il reste stable une trentaine de millisecondes, à l'appui comme au relâchement.
analogReadrend de 0 à 1023 pour 0 à 5 V :tension = lecture × 5 / 1023.mapcalcule en entiers, tronque, et ne borne pas son résultat.
Mettre en pratique
Conversion analogique, fréquence d'une boucle, résistance de tirage.
- Ce que lit un convertisseurNiveau 3
- La fréquence d'un clignotementNiveau 2
- L'état d'une entrée avec résistance de tirageNiveau 3