LOCODUINO

Multi-animations lumineuses

.
Par : Christian, Dominique, Guillaume

DIFFICULTÉ :

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.

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 remplacer delay(). 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

Figure 1
Figure 1
Montage sur platine d’essai

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

Figure 2
Figure 2
Montage complet

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 ;
}

3 Messages

  • Multi-animations lumineuses 11 décembre 2015 11:22, par alanya

    Encore une super idée à exploiter sur nos réseaux.
    Bravo aussi pour vos autres montages dont notamment l’animation "fête forraine" qui me donne des idées

    Répondre

  • Multi-animations lumineuses 23 décembre 2016 13:43, par meyer Joël

    Bonjour,
    Depuis des semaines je m’impregne de tout ce qui touche à l’Aduino pour faire tourner ma cervelle,à 71 ans. J’ai fait des études dans l’armée de l’air en France, mes parents divorcaient et ne pouvaient pas me payer d’autres etudes. J’étais électronicien specialiste en radar de bord.
    Epousant une belge prof qui ne pouvait pas travailler en France à cette époque j’ai rompu mon contrat pour venir travailler à la SABCA, près de Charleroi et toujours dans l’aviation. J’ai fait une carrière complète pour devenir responsable du service d’inspection au sein du contrôle de qualité. À part les deux premières années je n’ai plus fait d’électronique durant les 40 années suivantes. Je pense qu’avec Arduino je peux tout reprendre à zéro. Je souhaiterais créer un club au sein de l’ecole primaire de mon village, le train miniature me servant de fil conducteur pour motiver les enfants. Auriez vous quelques conseils à me prodiguer ? J’aimerais entrer en contact avec une personne de votre environnement pour me guider dans cette démarche.Je vous remercie d’avance pour toute l’attention que vous porterai à ce projet un peu fou.Bien à Vous.Meyer Joël. Belgique

    Répondre

  • Multi-animations lumineuses 23 décembre 2016 19:43, par Dominique

    Bonjour Joël,

    Votre projet est tout à fait louable et je partage avec vous cette envie d’apprendre aux plus jeunes la construction et la programmation de l’Arduino dans des applications ferroviaires.

    Mais ce n’est pas le bon endroit pour démarrer cette discussion : inscrivez-vous sur le Forum dans la section "Présentez-vous" et nous ferons tout pour vous aider.

    Cordialement

    Répondre

Réagissez à « Multi-animations lumineuses »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Projets »

Les derniers articles

Les articles les plus lus