Ce programme regroupe sur un même arduino plusieurs programmes d’animations lumineuses dont chacun a fait l’objet d’un article : feu tricolore, chenillard et enseigne de magasin. Vous trouverez dans ces articles quelques bases de la programmation ainsi que l’utilisation des DEL, mais aussi les exemples en vidéo.
Multi-animations lumineuses
. Par :
, ,
DIFFICULTÉ :
Pour quel arduino ?
Le code est écrit pour un arduino uno, il sera toutefois plus difficile de le transcrire pour un autre type d’arduino, vu que les branchements de chaque DEL influent sur le code. La déclaration des broches de sortie n’a pas été faite au tout début du programme. Nous utilisons des boucles pour simplifier la programmation.
Précaution
Comme vous le savez, un Arduino tant Uno que Mega accepte un maximum de 200 mA en consommation sur toutes les broches ensemble. Etudions donc la consommation de courant de ce montage qui est limitée à 200 mA pour la carte Uno. Le feu tricolore allume deux DEL en même temps (il consomme donc 40 mA), le chenillard n’allume qu’une seule DEL à la fois (il consomme 20 mA), l’enseigne lumineuse peut allumer toutes les DEL en même temps ; elle consomme donc 120 mA et la consommation totale des trois montages peut être de 180 mA, ce qui est très proche des possibilités du module !
Cela passe, mais si vous voulez garder une petite marge de sécurité, la solution la plus simple consiste à limiter le courant à 15 mA par DEL pour l’enseigne de commerçant qui consomme le plus. C’est la solution que j’ai adoptée ; les résistances sont égales à 150 ohms pour les DEL des feux et du chenillard, et à 220 ohms pour les DEL de l’enseigne.
Cette résistance dépend bien sûr de la DEL utilisée. Il faudra donc se reporter à la Datasheet de celle-ci pour calculer la valeur de la résistance associée. Une autre manière consiste à employer une résistance avec une valeur supérieure. Se reporter à l’article : Fonctionnement et pilotage d’une DEL
Comment les assembler ?
En général, les programmes commandant des DEL utilisent la fonction delay() qui est une fonction bloquante. En effet, le microcontrôleur ne peut rien faire d’autre pendant que delay() s’exécute.
2 manières de faire s’offrent donc à nous :
- nous pouvons soit utiliser la fonction
millis()
afin de remplacerdelay()
. Pour cela, un réarrangement du code est nécessaire - soit nous gardons la fonction
delay()
. En effet, L’allumage ou l’extinction d’une DEL est quasiment instantané. Il suffira donc de régler correctement l’enchaînement pour obtenir le même effet désiré. Nous verrons plus en détail dans le paragraphe concerné.
Programme regroupant les animations avec la fonction millis()
Branchements
Code
Le code ci-après est à recopier dans l’interface de l’IDE d’arduino. Il y a même un bouton télécharger à la fin.
/* Programme pour arduino uno par G. Marty Novembre 2013 Licence GNU GPLv3 Multi-programme pour feu tricolore, enseigne et chenillard avec fonction millis Schéma de branchement : => feu vert 1 et 2 sur broche 0 et 1, orange 1 et 2 sur 2 et 3 et rouge 1 et 2 sur 4 et 5 => Chenillard sur les broches de 6 à 11 : 6 LED => Enseigne sur les broches analogiques de 14 à 19 soit de A0 à A5 */ // Déclaration des broches de feu const int feu_vert = 0; const int feu_orange = 2; const int feu_rouge = 4; // Il n'y a pas besoin de déclarer les variables des autres broches. // Déclaration des différentes variables utilisées pour flécher les différentes étapes byte i; // Variable utilisée pour les boucles. // Cela évite de déclarer cette variable à chaque fois dans la boucle for. // Pour le feu tricolore byte etat_temps_feu = 0; // pour comptabiliser le nombre de fois où la valeur de temps // choisie s'écoule. boolean feu = 0; // pour gérer la route où le feu doit fonctionner : 0 ou 1 dans le cas // 'un croisement où 2 ou 4 feux (fonctionnant 2 par 2) sont présents // Pour le chenillard byte broche_chenillard = 6; // gérer l'état des broches du chenillard en fonction // d'une incrémentation byte etat_temps_chenillard = 0; // compter le nombre du temps de 50ms passées // Pour les animations de l'enseigne byte etat_temps_enseigne= 0; // compter le nombre du temps de 50ms passées byte compteur_tour_enseigne = 0; // compter le nombre de boucles passées byte broche_enseigne = 14; // gérer la broche de sorties lors des répétitions long aleatoire; // gérer l'aléatoire dans le choix des animations byte compte_LED_restantes = 5; // pour l'animation 3 // Déclaration des différents variables pour stocker le temps de l'arduino unsigned long temps_feu = 0; // pour le feu tricolore unsigned long temps_chenillard = 0; // pour le chenillard i.e. feux dans les virages unsigned long temps_enseigne = 0; // pour l'enseigne void setup() // Déclaration des broches du feu, du chenillard et de l'enseigne en boucle { for (i=0 ; i<12 ; i++) { } for(i=14 ; i < 20 ; i++) { } // Mise des valeurs de base sur les broches : LOW à part les feux rouges for (i=0 ; i<4 ; i++) { } for (i=6 ; i<12 ; i++) { } eteindre_enseigne(); // entre 1 et 4 non inclus } // Boucle du programme void loop() { // Etape de condition pour le feu. Si le temps passé est supérieur à 2s, // on exécute le code après sinon on continue le loop. { etat_temps_feu++; // On incrémente le compteur pour les 2s fonction_feu(etat_temps_feu); // On exécute la fonction du feu en fonction // du compteur // remettre à zéro la condition du if précédent } // Etape de condition pour le chenillard. Si le temps passé est supérieur à 50ms, // on exécute le code après sinon on continue le loop. // de 50 et 500ms { etat_temps_chenillard++; // On incrémente le compteur pour les 50ms fonction_chenillard(etat_temps_chenillard); // On exécute la fonction du chenillard // en fonction du compteur // sorte remettre à zéro la condition du if précédent } // Etape de condition pour l'enseigne Si le temps passé est supérieur à 50ms, // on exécute le code ci-après { etat_temps_enseigne++; // On incrémente pour les 50ms passées switch(aleatoire) // on sélectionne l'animation que le random a défini. { // chaque animation est stockée dans une fonction case 1: enseigne1(etat_temps_enseigne); break; case 2: enseigne2(etat_temps_enseigne); break; case 3: enseigne3(etat_temps_enseigne); break; } } } // Définition des différentes fonctions /* Définition de la fonction du feu. L'allumage des LED se fait en fonction du temps passé 2s pour feu rouge et orange et 10s pour le feu vert soit 5 tours. Pour changer de feu qui doit faire le cycle, on échange la valeur booléane feu. */ void fonction_feu(byte x) { switch(x) { case 1: break; case 6: break; case 7: etat_temps_feu = 0; // On remet à zéro pour refaire le cycle de la fonction feu = !feu; // on échange de croisement break; } } /* Définition de la fonction du chenillard en fonction du compteur commençant par 5, le compteur définissant aussi la broche de sortie pour l'allumage des différentes LED toutes les 50ms puis un retour au début du cycle après 500ms soit 10 cycles */ void fonction_chenillard(byte t) { switch(t) { case 1: break; case 4: break; case 5: broche_chenillard++; if (broche_chenillard == 12) // arrivée au bout du chenillard { etat_temps_chenillard = 6; // pour établir un délai entre chaque chenillard broche_chenillard = 6; // on remet à zéro pour une nouvelle boucle de // chenillard après attente } else { etat_temps_chenillard = 0; // on remet à zéro pour un changement // d'allumage/extinction de LED } break; case 20: // pour patienter un peu 750ms etat_temps_chenillard = 0; break; } } /* Définition des fonctions des animations de l'enseigne 3 fonctions au total */ // 1ère animation : clignotement de l'ensemble des LED 3 fois void enseigne1(byte z) { switch(z) { case 1: // allumage des LED for (i=14 ; i < 20 ; i++) { } break; case 11: // extinction des LED eteindre_enseigne(); break; case 20: // pour patienter un peu 500ms compteur_tour_enseigne++; // on incrémente le compteur de tours etat_temps_enseigne =0; // on remet à zéro pour une nouvelle boucle if (compteur_tour_enseigne==3) // si 3 tours exécutés { compteur_tour_enseigne = 0; // on remet à zéro le compteur // ne reste pas 1 } break; } } // 2ème animation : chenillard exécuté 2 fois void enseigne2(byte t) { switch(t) { case 1: break; case 4: break; case 5: broche_enseigne++; // incrémentation de la broche pour changer de LED etat_temps_enseigne = 0; // RAZ pour revenir au début de la boucle if (broche_enseigne == 20) // quand le chenillard est fini { broche_enseigne = 14; // RAZ des broches pour revenir au début du chenillard compteur_tour_enseigne++;// Incrémentation du compteur } if (compteur_tour_enseigne == 2) // si 2 chenillards faits { compteur_tour_enseigne = 0; // RAZ du compteur etat_temps_enseigne = 6; // pour faire patienter } break; case 25: etat_temps_enseigne = 0; break; } } // 3ème animation : chenillard de gauche à droite avec cumul des LED sur la droite // et extinction de gauche à droite void enseigne3(byte u) { switch(u) { case 1: break; case 4: // Ensemble de conditions si fausses la boucle continue if (compteur_tour_enseigne == compte_LED_restantes) // tour complet { compte_LED_restantes--; // décrémentation des LED restantes à allumer pour // faire un tour moins complet etat_temps_enseigne = 0; // RAZ pour refaire la boucle broche_enseigne = 14; // RAZ de la broche de sortie compteur_tour_enseigne = 0; // RAZ des tours if (compte_LED_restantes == 0) // les 5 dernières LED sont allumées { broche_enseigne = 19; // On met à 19 pour l'extinction etat_temps_enseigne = 97; // On sort de la boucle } } else // On recommence le tour pour faire une boucle complete { broche_enseigne++; // On change de broche etat_temps_enseigne = 0; // On remet à 0 le temps compteur_tour_enseigne++; // On comptabilise le tour } break; case 100: break; case 103: broche_enseigne--; // on décrémente pour éteindre les LED if (broche_enseigne == 13) // Extinction de toutes les LED faites { etat_temps_enseigne = 104; // on fait sortir de cette boucle } else { etat_temps_enseigne = 97; // on continue l'extinction } break; case 114: // pour faire patienter // RAZ de toutes les valeurs utilisées etat_temps_enseigne = 0; compteur_tour_enseigne = 0; broche_enseigne = 14; compte_LED_restantes = 5; break; } } // Extinction des LED de l'enseigne void eteindre_enseigne() { for(i=14 ; i < 20 ; i++) { } }
Programme regroupant les animations avec la fonction delay()
Explications
La fonction delay() est bloquante, ce qui signifie que le microcontrôleur ne peut rien faire d’autre pendant l’exécution de delay(), Or, l’allumage ou l’extinction d’une DEL est quasiment instantané (quelques microsecondes) ; ces actions très rapides sont à intercaler entre d’autres actions. On peut régler les feux lorsque c’est nécessaire et pour cela, il faut se fixer une unité de base de temps. Le plus simple est de prendre une seconde et de choisir que le chenillard soit lancé toutes les secondes. Avant chaque lancement du chenillard, on manipule une DEL de l’enseigne, selon la séquence choisie (cette fois on ne fait plus appel aux fonctions). La première séquence de l’enseigne est le cumul sur la gauche ; lorsqu’elle est terminée, le temps écoulé est de 22 secondes. Il est alors temps de faire passer à l’orange le feu qui était vert. La durée du feu orange, dure le temps de la séquence 2 (clignotement de l’ensemble des DEL de l’enseigne deux fois). Lorsque la séquence 2 est terminée, le feu doit passer au rouge. On lance alors la dernière séquence de l’enseigne (l’extinction de la gauche vers la droite), ce qui permet la temporisation du chauffard ; puis l’autre feu passe au vert, et un deuxième cycle recommence à l’identique pour le feu B1.
Bien sûr, il ne faut pas oublier de lancer le chenillard toutes les secondes. La fonction « chenillard » a été créée pour cela. Chaque DEL s’allumant 50 ms (T2), la durée totale du chenillard est de 300 ms (6 fois T2). Pour le déclencher toutes les secondes, on introduit un délai égal à 700 ms (T1).
En choisissant T1 = 700 ms et T2 = 50 ms, le chenillard est lancé toutes les secondes, la durée du vert est de 22 s, celle de l’orange de 4 s et celle du rouge 27 s (22 + 4 + 1 qui est la temporisation du chauffard).
Maintenant que vous connaissez les astuces pour commander les trois animations, vous pouvez remarquer, sur la vidéo, qu’on voit bien que c’est le rythme de l’enseigne qui fixe le rythme des feux. Ceci est dû au fait que les trois animations sont proches l’une de l’autre sur la breadboard. Une fois que les animations seront en place sur votre réseau, cela ne se remarquera plus, car l’observateur fixera une animation à la fois, en fonction des saynètes que vous développerez.
Branchements
Code
/*------------------------------------------------------- Programme pour arduino uno par C. Bézanger Novembre 2013 Licence GNU GPLv3 Ce programme fait fonctionner une enseigne lumineuse, un chenillard et des feux tricolores, en même temps. Six LED rouges sont reliées aux sorties 2 à 7 et forment l'enseigne. Six LED jaunes sont reliées aux sorties 8 à 13 et forment le chenillard. Les sorties analogiques sont utilisées comme sorties numériques et sont numérotées 14 à 19. Les sorties 14 à 16 forment le feu A1. Les sorties 17 à 19 forment le feu B1. T2 est la durée d'un flash du chenillard en ms. La durée du chenillard est 6 fois T2 en ms. Pour que le chenillard soit déclenché toutes les secondes, il faut que (T1 + 6 fois T2) soit égal à 1000 ms En jouant sur T1 et/ou T2, on dynamise le rythme Par exemple, pour T1 = 700 et T2 = 50, on a : Vert : 22 secondes Orange : 4 secondes Rouge : 27 secondes (car temporisation du chauffard 1 sec) --------------------------------------------------------*/ // Initialisation des variables const byte A1V = 14 ; const byte A1O = 15 ; const byte A1R = 16 ; const byte B1V = 17 ; const byte B1O = 18 ; const byte B1R = 19 ; const int T1 = 700 ; // Fixe le rythme de déclenchement du chenillard const int T2 = 50 ; // Durée du flash du chenillard // T1 + 6 fois T2 doit être égal à 1000 ! void setup () { // Initialisation de toutes les lignes en sortie for (byte i = 2 ; i <= 19 ; i++) { } // Extinction de toutes les LED au départ for (byte j = 2 ; j <= 19 ; j++) { } // Allumage de A1V et B1R } // Fonction loop void loop () { // Début de cycle ; le feu A1 est vert et le feu B1 est rouge // L'enseigne cumule vers la gauche for (byte n = 0 ; n <= 5 ; n++) { for (byte m = 2 ; m <= (7 - n) ; m++) { chenillard () ; } } chenillard () ; // On est à 22 secondes // Feu A1 passe à orange // Enseigne clignote dans sa totalité deux fois for (byte j = 1 ; j <= 2 ; j++) { for (byte k = 2 ; k <= 7 ; k++) { } chenillard () ; for (byte l = 2 ; l <= 7 ; l++) { } chenillard () ; } // On est à quatre secondes // Feu A1 passe au rouge // Enseigne s'éteint de la gauche vers la droite // Le temps nécessaire pour cela constitue la temporisation du chauffard for (byte i = 7 ; i >= 2 ; i--) { } chenillard () ; // On est à une seconde, le rouge a donc duré 22 + 4 + 1 = 25 sec // Feu B1 passe au vert // Le feu A1 est rouge et le feu B1 est vert // L'enseigne cumule vers la gauche for (byte n = 0 ; n <= 5 ; n++) { for (byte m = 2 ; m <= (7 - n) ; m++) { chenillard () ; } } chenillard () ; // Feu B1 passe à l'orange // Enseigne clignote dans sa totalité deux fois for (byte j = 1 ; j <= 2 ; j++) { for (byte k = 2 ; k <= 7 ; k++) { } chenillard () ; for (byte l = 2 ; l <= 7 ; l++) { } chenillard () ; } // Feu B1 passe au rouge // Enseigne s'éteint de la gauche vers la droite // Le temps nécessaire pour cela constitue la temporisation du chauffard for (byte i = 7 ; i >= 2 ; i--) { } chenillard () ; // Feu A1 passe au vert // Le feu A1 est vert, le feu B1 est rouge, le cycle peut recommencer } void chenillard () { // Boucle pour faire flasher les LED du chenillard, durée 300 ms for (byte i = 8 ; i <= 13 ; i++) { } return ; }