Il existe déjà différentes méthodes qui permettent d’économiser le nombre de broches utilisées sur un microcontrôleur, surtout si on utilise des petits microcontrôleurs comme les ATtiny, on est vite limité en nombre de broches. Des moyens, il en existe de toutes les formes, expander de I/O (avec protocole SPI ou I²C), registre à décalage, charlieplexing... etc.
Mais si on veut juste quelques broches de plus alors pourquoi pas faire plus simple !
Circuit électronique du principe :
on peut faire autrement et plus simplement en utilisant une broche à la fois comme entrée et sortie dans une application simple capteur-actionneur, où il suffit de lire un état (0/1) pour exécuter une action comme allumer une LED après avoir appuyé sur un bouton.
Évidemment, en liant directement un bouton et une LED sur la même broche, il peut avoir facilement conflit entre le signal retourné par le bouton et le signal envoyé à la LED, pour y remédier, on va ajouter une diode en aval de la partie capteur pour que quand on commande l’actionneur, le courant ne va pas entrer sur le capteur. Ce qui donc permet d’isoler partiellement les 2 parties.
Partiellement, car quand on appuie sur le bouton-poussoir la LED, va s’allumer d’un court instant (le temps d’un appui) même si ce n'est pas programmé pour le faire.
Mais si par exemple, on souhaite allumer la LED pendant 10 s après avoir appuyé sur le bouton-poussoir, le fait que la LED s’allume après l’appui ne pose pas vraiment de problème.
Bon tout ça, c’est beau, c’est facile, mais comment faire comprendre à la carte Arduino à quel moment elle doit lire la broche et à quel moment elle doit y écrire ? Puisque sur Arduino comme les autres cartes, il faut toujours configurer les broches en entrée ou sortie et pas les 2 sens en même temps.
Partie programme Arduino :
D’habitude, on configure les broches utilisées en entrée ou en sortie avec l'instruction pinMode() dans la fonction setup(), mais comme cette dernière à l’inverse de la fonction loop(), s'exécute qu’une seule fois à l'exécution du programme, on pourra pas à la fois configurer la broche utilisée en entrée pour lire l’état renvoyé par le bouton et la configurer en sortie pour allumer la LED.
C’est pour ça qu’on va mettre la direction de la broche plutôt sur la fonction loop(), où on peut la changer à volonté !
Et pour ce faire, on va d'abord commencer par voir le fonctionnement du programme : après avoir appuyé sur le bouton, la LED va s’allumer pendant 2 secondes puis s'éteindre.
Dans la fonction loop(), on va commencer par configurer la broche en entrée (INPUT) puis on va lire cette broche et enfin on test si le bouton est appuyé. Si c’est le cas, on va configurer cette broche en sortie et on va allumer la LED pendant 2 secondes.
À travers cet organigramme, on peut voir que quand les 2 secondes seront écoulées (pendant ce temps, la broche est en sortie.), la broche redevient en entrée. Si le bouton n’est pas appuyé alors la broche reste toujours en entrée.
Maintenant qu’on a vu le fonctionnement du programme, on peut commencer à l’écrire :
Exemple d'utilisation
Cette méthode est plus utile pour de simples applications comme pour signaler sur la LED un activement d’une action sur une autre broche.
Je l’ai utilisé sur un petit projet où le bouton a pour fonction d’activer un clignotement d’une autre LED pendant 10 secondes et la LED sur la broche D8 permettra de signaler que le clignotant est bien activé ou que l’appui sur le bouton a bien était pris en compte en restant allumé.
Pour ça on garde le même montage vue précédemment et on ajoute une LED supplémentaire sur la broche D3 qui va assurer le clignotement.
À l’appui sur le bouton, le clignotant est activé pendant 10 s et la LED reste allumée tant que ça clignote.
À noter qu'à l’appui sur le bouton, ça renvoie 0 V puisque le bouton est monté en pull up.
Partie programme :
pour le programme, on garde la même chose, on modifie la fonction allumer_Led2s() pour que la Led_indicateur soit allumée tant que l’autre LED clignote et on ajoute la nouvelle LED sur la broche D3 qui va clignoter pendant 10 secondes.
J’ai ajouté un else sur le test qui permet de laisser les LEDs éteintes tant que le bouton n’est pas appuyé. Car le circuit du bouton qui est en pull up renvoie un état haut (5v) si il n’est pas appuyé et l’inverse s'il est appuyé, cet état haut va se diriger vers la broche D8 et en même temps alimenter la Led_Clignotant ce qui permet de l’allumer légèrement (car le courant renvoyé par le bouton est lié à la fois sur la LED et la broche D8).
On peut utiliser un bouton monté en pull down qui va renvoyer un état bas (0 V) quand il n’est pas appuyé, mais ça revient au même, car quand on appuie sur le bouton la Led, va s’allumer même si elle n'est pas programmée pour le faire.
Donc quel que soit le type de circuit de bouton utilisé, ça peut se corriger avec quelques lignes de codes comme on l’a fait ici.
Rappel sur les 2 configuration d’un bouton :
Résultat :
j’ai utilisé ici un shield bouton-led que j’ai réalisé moi-même, ça me permet de gagner du temps sur des branchements répétitifs. Pour les boutons, ils sont montés en pull up. Donc ils renvoient un état bas à l’appui.
Sans la condition else qui fait éteindre les LEDs s'il n'y a pas appui sur le bouton. On peut voir que la LED s’allume bien légèrement.
Alors que quand on met la condition, tout reste éteint tant que le bouton n’a pas était appuyé.
Et quand on appuie, la LED s’allume avec une luminosité plus forte :
https://www.youtube.com/watch?v=59KbhmUhgS8
La LED qui s’allume en bleu est la Led_Indicateur et celle qui s’allume en orange est la Led_Clignotant.
À noter qu’avant la fin des 10 secondes la Led_Indicateur s'éteint avant la Led_Clignotant et cela est dû à la fonction délai (delay) qui se trouve entre les 2 instruction de l'extinction des 2 LEDs. Si on avait utilisé la fonction millis(), il y aurait pas cette différence puisque celle-ci fait pas arrêter le fonctionnement du microcontrôleur.