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++)
{
pinMode(i, OUTPUT);
}
for(i=14 ; i < 20 ; i++)
{
pinMode(i, OUTPUT);
}
// Mise des valeurs de base sur les broches : LOW à part les feux rouges
for (i=0 ; i<4 ; i++)
{
digitalWrite(i, 0);
}
digitalWrite(4, 1);
digitalWrite(5, 1);
for (i=6 ; i<12 ; i++)
{
digitalWrite(i, 0);
}
eteindre_enseigne();
aleatoire=random(1, 4); // attribution à la variable d'un nombre
// 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.
if (millis() - temps_feu > 2000) // Utilisation d'un temps de 2s multiple de 2 et 10
{
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
temps_feu = millis(); // On stocke la nouvelle valeur du temps pour en quelque sorte
// 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.
if (millis()-temps_chenillard > 50) // Utilisation d'un temps de 50ms multiple
// 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
temps_chenillard = millis(); // On stocke la nouvelle valeur du temps pour en quelque
// 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
if ((millis() - temps_enseigne) > 50 )
{
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;
}
temps_enseigne = millis();
}
}
// 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:
digitalWrite(feu_rouge + feu, 0); // On éteint le feu rouge
digitalWrite(feu_vert + feu, 1); // On allume le feu vert
break;
case 6:
digitalWrite(feu_vert + feu, 0); // On éteint le feu vert
digitalWrite(feu_orange + feu, 1); // On allume le feu orange
break;
case 7:
digitalWrite(feu_orange + feu, 0); // On éteint le feu orange
digitalWrite(feu_rouge + feu, 1); // On allume le feu rouge
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:
digitalWrite(broche_chenillard, 1);
break;
case 4:
digitalWrite(broche_chenillard, 0);
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++)
{
digitalWrite(i, 1);
}
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
aleatoire = random(1, 4); // on change d'animation si aleatoire
// ne reste pas 1
}
break;
}
}
// 2ème animation : chenillard exécuté 2 fois
void enseigne2(byte t)
{
switch(t)
{
case 1:
digitalWrite(broche_enseigne, 1); // Allumage de la LED
break;
case 4:
digitalWrite(broche_enseigne, 0); // Extinction de la LED
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;
aleatoire = random(1, 4);
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:
digitalWrite(broche_enseigne, 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
{
digitalWrite(14, 1); // On allume la dernière LED
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
{
digitalWrite(broche_enseigne, 0); // On éteint la LED
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:
digitalWrite(broche_enseigne, 0); // On éteint la LED
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
aleatoire = random(1, 4); // choix d'une animation au hasard
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++)
{
digitalWrite(i, 0);
}
}
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++)
{
pinMode (i, OUTPUT) ;
}
// Extinction de toutes les LED au départ
for (byte j = 2 ; j <= 19 ; j++)
{
digitalWrite (j, LOW) ;
}
// Allumage de A1V et B1R
digitalWrite (A1V, HIGH) ;
digitalWrite (B1R, HIGH) ;
}
// 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++)
{
digitalWrite (m, HIGH) ;
delay (T1) ;
chenillard () ;
digitalWrite (m, LOW) ;
}
digitalWrite ((7 - n), HIGH) ;
}
delay (T1) ;
chenillard () ;
// On est à 22 secondes
// Feu A1 passe à orange
digitalWrite (A1V, LOW) ;
digitalWrite (A1O, HIGH) ;
// Enseigne clignote dans sa totalité deux fois
for (byte j = 1 ; j <= 2 ; j++)
{
for (byte k = 2 ; k <= 7 ; k++)
{
digitalWrite (k, LOW) ;
}
delay (T1) ;
chenillard () ;
for (byte l = 2 ; l <= 7 ; l++)
{
digitalWrite (l, HIGH) ;
}
delay (T1) ;
chenillard () ;
}
// On est à quatre secondes
// Feu A1 passe au rouge
digitalWrite (A1O, LOW) ;
digitalWrite (A1R, HIGH) ;
// 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--)
{
digitalWrite (i, LOW) ;
delay (T1/6) ;
}
chenillard () ;
// On est à une seconde, le rouge a donc duré 22 + 4 + 1 = 25 sec
// Feu B1 passe au vert
digitalWrite (B1R, LOW) ;
digitalWrite (B1V, HIGH) ;
// 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++)
{
digitalWrite (m, HIGH) ;
delay (T1) ;
chenillard () ;
digitalWrite (m, LOW) ;
}
digitalWrite ((7 - n), HIGH) ;
}
delay (T1) ;
chenillard () ;
// Feu B1 passe à l'orange
digitalWrite (B1V, LOW) ;
digitalWrite (B1O, HIGH) ;
// Enseigne clignote dans sa totalité deux fois
for (byte j = 1 ; j <= 2 ; j++)
{
for (byte k = 2 ; k <= 7 ; k++)
{
digitalWrite (k, LOW) ;
}
delay (T1) ;
chenillard () ;
for (byte l = 2 ; l <= 7 ; l++)
{
digitalWrite (l, HIGH) ;
}
delay (T1) ;
chenillard () ;
}
// Feu B1 passe au rouge
digitalWrite (B1O, LOW) ;
digitalWrite (B1R, HIGH) ;
// 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--)
{
digitalWrite (i, LOW) ;
delay (T1/6) ;
}
chenillard () ;
// Feu A1 passe au vert
digitalWrite (A1R, LOW) ;
digitalWrite (A1V, HIGH) ;
// 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++)
{
digitalWrite (i, HIGH) ; // allume la LED sur broche i
delay (T2) ; // durée du flash 50 millisecondes
digitalWrite (i, LOW) ; // éteint la LED
}
return ;
}