Header Ads

Chenillard à Leds - part 2

Dans le premier article "Chenillard à leds - part 1", quelques modèles d'animations tournaient boucle.
Dans cette seconde partie, j'ai ajouté un bouton (pin 2) permettant à l'utilisateur de sélectionner l'animation.
A chaque pression du bouton, l'animation change. A la dernière animation, on re-sélectionne la première lorsque le bouton est pressé.

Plan de montage




Quelques notes explicatives
  1. La lecture de l'état du bouton est fait comme décrit dans l'article "Entrée Bouton - Résistance pull-up, pull-down et déparasitage".
    Le code détecte le changement d'état.
  2. Le changement d'animation est effectuée lorsque le bouton est relâché.
    Cela se traduit par une logique similaire à:
    SI changement d'état bouton ET SI état bouton = bas ALORS changer d'animation
  3. Le changement d'animation est testé dans chaque routine d'animation à l'aide de la fonction animChanged() qui elle même s'appuie sur animBtnChanged() pour tester le changement d'état du bouton.
    Lorsqu'un changement d'animation est détecté, la routine d'animation arrête immédiatement son exécution.
  4. animChanged() change aussi la valeur de la variable currentAnim (via la fonction nextAnim() ).
    La variable currentAnim indique quelle animation doit être affichée.
  5. La fonction displayAnim() a pour seul utilité d'appeler la routine d'animation correspondante à la valeur de currentAnim.
    Les fonctions nextAnim() et displayAnim() sont volontairement mises l'une après l'autre car tout ajout d'une nouvelle animation imposera la modification de ces deux fonctions.
Le résultat

Le programme
source: Chenillard_2.pde

/*
 * Chenillard 2 pour Leds branchées sur Pin 6 -> 13 (8 leds)
 * Bouton (pull-down) sur Pin 2 permet de changer modèles d'animation
 */
 
 int NbrLed = 8; // nbre de Leds dans le tableau
 int ledPins[] = { 6,7,8,9,10,11,12,13 };  // Tableau contenant les Pins pour les leds
 
 int pinAnimBtn = 2; // Bouton (pull-down) pour changer d'animation
 int animBtnState;   // Etat du bouton d'animation
 
 byte currentAnim = 0; // Animation actuellement affichée
                       // Change a chaque fois que le bouton est pressé
 
 int interval = 80; // Interval entre deux actions LEDS, 80 ms
 
 void setup(){
   // Activer les pins pour les leds en sortie
   for( int i=0; i<NbrLed; i++ )
     pinMode( ledPins[i], OUTPUT );
   // Activer bouton animation
   pinMode( pinAnimBtn, INPUT );
   animBtnState = digitalRead( pinAnimBtn );
   // Animation par defaut
  currentAnim = 0; 
 }
 
 void loop(){
   displayAnim();
 }
 
 // ==============================================================
 //     Controle bouton "change animation"
 // ==============================================================
  
 int lecture1, lecture2;
 boolean resultat = false;
 
 // Vérifie si l'état du bouton a changé (enfoncé ou relaché)
 //
 boolean animBtnChanged(){
   lecture1 = digitalRead( pinAnimBtn );
   // Si pas changement état --> continuer programme
   if( lecture1 == animBtnState )
     return false;
   // Changement état bouton détecté --> deparasitage de lecture
   delay( 10 );
   lecture2 = digitalRead( pinAnimBtn );
   // Si parasite --> continuer le programme
   if( lecture1 != lecture2 )
     return false;
   // Evaluer le changement d'état
   resultat = ((lecture1 == lecture2) && (lecture1 != animBtnState) );
   // Mémoriser le nouvel état
   if( resultat )
     animBtnState = lecture1;
   return resultat; 
 }
 
 // Retourne vrai lorsque l'animation a changée
 //  (lorsque le bouton pinAnimBtn est relaché).
 // Sélectionne aussi l'animation suivante.
 boolean animChanged(){
   // si pas changement etat bouton --> continuer programme.
   if( !animBtnChanged() )
     return false;
   // Changer d'animation seulement quand le bouton est relaché.
   if( animBtnState != LOW )
     return false;
          
   // Eteind toutes les leds (comme ca, pas de problèmes 
   //    si changement en milieu d'animation)
   allLedOff();
   // Change d'animation
   nextAnim();
   return true;
 }
 
 // ==============================================================
 //     Controle du cycle des animations
 // ==============================================================
 // Change d'animation en modifiant la variable d'animation
 //
 void nextAnim(){
   // Passer à l'animation suivant
   currentAnim++;
   // Si plus d'animation, repasser à la première
   if( currentAnim > 5 )
     currentAnim = 0;
 }

 // Affiche l'animation currentAnim
 // ps: le controle du bouton "changer anim" et 
 //     changement d'animation sont fait par les 
 //     routine d'animations (via animChanged).
 void displayAnim(){
    switch( currentAnim ){
      case 0: OnOffAll();
              break;
      case 1: OnOffEachAtTheTime_LtoR();
              break;
      case 2: OnOffEachAtTheTime_RtoL();
              break;
      case 3: GraduatedOnOff_LtoR();
              break;
      case 4: GraduatedOnOff_RtoL();
              break;
      case 5: K2000();
              break;
   }
 } 
 
 // Eteind toutes les leds
 void allLedOff() {
   for( int i=0; i<NbrLed; i++ )
     digitalWrite( ledPins[i], LOW );
 }
 
 // ==============================================================
 //     Modèle d'Animation
 // ==============================================================
 
 // Allume puis éteind toutes les leds en meme temps
 // 8 fois (pcq 8 leds).
 //
 void OnOffAll(){
   for( int iTime=0; iTime<NbrLed; iTime++ )
     for( int iOnOff=0; iOnOff<2; iOnOff++ ) {
       for( int i=0; i<NbrLed; i++ )
         if( iOnOff == 0 ) // Allumer au premier passage  
           digitalWrite( ledPins[i], HIGH );
         else // Eteindre au deuxième passage
           digitalWrite( ledPins[i], LOW );
       if( animChanged() )
         return;
       delay( interval ); 
     }
 }
 
 // Allume puis éteind chaque led, chaque led a son tour.
 // De gauche à droite
 void OnOffEachAtTheTime_LtoR(){
   for( int i=0; i<NbrLed; i++ ){
     digitalWrite( ledPins[i], HIGH );
     delay( interval );
     digitalWrite( ledPins[i], LOW );
     if( animChanged() )
       return;
     delay( interval );
   }
 }

 void OnOffEachAtTheTime_RtoL(){
   for( int i=NbrLed-1; i>=0; i-- ){
     digitalWrite( ledPins[i], HIGH );
     delay( interval );
     digitalWrite( ledPins[i], LOW );
     if( animChanged() )
       return;
     delay( interval );
   }
 }
 
 // allume toutes les leds une par une puis les éteinds
 // De Gauche à Droite
 void GraduatedOnOff_LtoR(){
   for( int i=0; i<NbrLed; i++ ) {
     digitalWrite( ledPins[i], HIGH );
     if( animChanged() )
       return;
     delay( interval );  
   }
   for( int i=0; i<NbrLed; i++ ) {
     digitalWrite( ledPins[i], LOW );
     if( animChanged() )
       return;
     delay( interval );  
   }
 }

 // allume toutes les leds une par une puis les éteinds
 // De Gauche à Droite
 void GraduatedOnOff_RtoL(){
   for( int i=NbrLed-1; i>=0; i-- ) {
     digitalWrite( ledPins[i], HIGH );
     if( animChanged() )
       return;
     delay( interval );  
   }
   for( int i=NbrLed-1; i>=0; i-- ) {
     digitalWrite( ledPins[i], LOW );
     if( animChanged() )
       return;
     delay( interval );  
   }
 }

 // Allume et éteind les leds à la façon K2000
 // Un aller retour complet
 void K2000(){
   for( int i=0; i<NbrLed; i++) {
      // Allume uniquement la led, la précédente et la suivante
      // éteind toutes les autres.
      for( int iBrowser=0; iBrowser<NbrLed; iBrowser++ ) 
        if( iBrowser==(i-1) || iBrowser==(i+1) || iBrowser==i )
          digitalWrite( ledPins[iBrowser], HIGH );
        else
          digitalWrite( ledPins[iBrowser], LOW );
     if( animChanged() )
       return;
      delay( interval );
   }

   for( int i=NbrLed-1; i>=0; i--) {
      // Allume uniquement la led, la précédente et la suivante
      // éteind toutes les autres.
      for( int iBrowser=0; iBrowser<NbrLed; iBrowser++ ) 
        if( iBrowser==(i-1) || iBrowser==(i+1) || iBrowser==i )
          digitalWrite( ledPins[iBrowser], HIGH );
        else
          digitalWrite( ledPins[iBrowser], LOW );
     if( animChanged() )
       return;
      delay( interval );
   }
   
   // eteind les deux dernières led
   digitalWrite( ledPins[0], LOW );
   digitalWrite( ledPins[1], LOW );
}