Article Arduino de LR 798 (janvier 2014)

Toutes les discussions sur l'Arduino !

Modérateur : MOD

Guillaume22
Papotier
Messages : 145
Enregistré le : dim. 29 sept. 2013, 09:20

Re: Article Arduino de LR 798 (janvier 2014)

Message par Guillaume22 » jeu. 16 janv. 2014, 15:34

Allez hop, une autre façon de faire un feu tricolore sur 2 routes, le cablage est différent mais cela reste dans la même veine :
Si vous changez le branchement à vous de changer les variables (qui servent dans le loop) mais aussi dans le setup dans les boucles for et les autres digitalWrite. La condition est de faire suivre les différentes couleurs des feux.

Code : Tout sélectionner

/* Programme de feu tricolore
Cablage :
feu 1 : vert sur broche 2, orange sur broche 4 et rouge sur broche 6
feu 2 : vert sur broche 3, orange sur broche 5 et rouge sur broche 7
*/

const int feu_vert = 2;
const int feu_orange = 4;
const int feu_rouge = 6;
boolean feu = 0; //variable pour changer le feu de route

void setup()
{
  for(byte i=2; i<8; i++)
  {
    pinMode(i, OUTPUT);
  }
 
  for(byte i=2; i<6; i++)
  {
    digitalWrite(i, 0);
  }
  digitalWrite(6, 1);
  digitalWrite(7, 1);//seuls les feux rouges sont allumés
}

void loop ()
{
  digitalWrite(feu_rouge+feu, 0);
  digitalWrite(feu_vert+feu, 1);
  delay(5000);
  digitalWrite(feu_vert+feu, 0);
  digitalWrite(feu_orange+feu, 1);
  delay(1000);
  digitalWrite(feu_orange+feu, 0);
  digitalWrite(feu_rouge+feu, 1);
  delay(2000);
  feu = !feu;
}

Avatar du membre
Arduino
Prolixe
Messages : 1701
Enregistré le : mer. 25 sept. 2013, 17:14

Re: Article Arduino de LR 798 (janvier 2014)

Message par Arduino » jeu. 16 janv. 2014, 15:55

Merci Guillaume d'avoir bien voulu transférer dans ce forum, ce que tu avais déjà écrit dans le forum pour débutants.

La façon de programmer de Guillaume en utilisant une variable Booléenne, est bien plus élégante que la solution donnée dans LR 798 qui était faite pour démontrer qu'on peut programmer "comme on parle". Son programme occupe 1220 octets, le mien en faisait 1300. Bravo à lui ! :applause:

L'optimisation d'un programme n'est pas forcément une préoccupation de débutant (au début, on veut surtout que cela fonctionne), mais il faut s'habituer à écrire du code de la meilleure façon possible ... et cela vient avec la pratique.

Je vous invite donc tous à pratiquer ! :lol:

macsddau
Papotier
Messages : 114
Enregistré le : jeu. 17 oct. 2013, 22:46
Echelle pratiquée : N

Re: Article Arduino de LR 798 (janvier 2014)

Message par macsddau » jeu. 16 janv. 2014, 18:26

Le code que je prose est corrigé et testé.

Code : Tout sélectionner

// cablage de l'Arduino
#define VOIE_1_VERT    4
#define VOIE_1_ORANGE  5
#define VOIE_1_ROUGE   6
#define VOIE_2_VERT    7
#define VOIE_2_ORANGE  8
#define VOIE_2_ROUGE   9

// nombre de voies de circulation a controler
#define NOMBRE_DE_VOIES 2

// table des feux : correspondance voie / feu / cablage
const byte feux[NOMBRE_DE_VOIES][3] =
             {{VOIE_1_VERT, VOIE_1_ORANGE, VOIE_1_ROUGE},
              {VOIE_2_VERT, VOIE_2_ORANGE, VOIE_2_ROUGE}};

// table des temps d'activation des feux {VERT, ORANGE, ROUGE*}
//    * temps avant que la voie suivante passe au vert
const int temps[NOMBRE_DE_VOIES][3] = {{60000, 7000, 2000},
                                       {50000, 2500, 1000}};

// definition de l'extinction et de l'allumage
// sorties en pulldown : allumé lorsque la sortie est à 1
#define ALLUME(v, f)   digitalWrite(feux[v - 1][f], HIGH)
#define ETTEIND(v, f)  digitalWrite(feux[v - 1][f], LOW)

// ***** Les modifications sont à faire au dessus de cette ligne ******

// état des feux
enum {VERT, ORANGE, ROUGE};

// variables
byte voiePassante = NOMBRE_DE_VOIES;//voie actuelement controlée
byte feuActif = ROUGE;//feu actif sur la voie de circulation

void setup () {
  for (byte v = 1; v < NOMBRE_DE_VOIES + 1; v++) {
    for (byte f = VERT; f < ROUGE + 1; f++) {
      pinMode(feux[v - 1][f], OUTPUT);
      if (f == feuActif) {
        ALLUME(v, f);
      } else {
        ETTEIND(v, f);
      }
    }
  }
}

//Utilisé à la place de Delay(ms) car accepte les interruptions
//Ajuster le max de i :
//    utiliser un chronomètre avec duree = 10000 (10s) par exemple
//    ou plus pour une meilleure précision (65,535s max)
void attenteMs (unsigned int duree) {
  volatile unsigned int i; 
  unsigned int j;
  for (j=0; j<duree; j++) {
    for (i=0; i<200; i++) {//a ajuster
    }   
  }
}

void loop () {
  switch (feuActif) {
    case VERT :
      ETTEIND(voiePassante, VERT);
      ALLUME(voiePassante, ORANGE);
      feuActif = ORANGE;
      break;
      
    case ORANGE :
      ETTEIND(voiePassante, ORANGE);
      ALLUME(voiePassante, ROUGE);
      feuActif = ROUGE;
      break;
      
    case ROUGE :
      voiePassante --;//corrigé cette ligne et la suivante
      if (voiePassante == 0) {// passer à la voie suivante
        voiePassante = NOMBRE_DE_VOIES;//si == 0
      }
      ETTEIND(voiePassante, ROUGE);
      ALLUME(voiePassante, VERT);
      feuActif = VERT;
      break;
  }

  attenteMs(temps[voiePassante - 1][feuActif]); //remplace delay
}
Compilé 1306 octets. Peut-être plus gros que d'autres réalisations, mais le nombre de feux peut être étendu (jusqu'au nombre de pin du micro) sans retouche profonde du programme. De plus je peux gérer les tempo en fonction de la voie de circulation (les feux sur une route à 90km/h croisant une rue à 50km/h sont plus longs).
MS2 CC2 S-DEC-4-DC Rocrail

Avatar du membre
Arduino
Prolixe
Messages : 1701
Enregistré le : mer. 25 sept. 2013, 17:14

Re: Article Arduino de LR 798 (janvier 2014)

Message par Arduino » ven. 17 janv. 2014, 16:18

macsddau a écrit :Le code que je prose est corrigé et testé.
...
Compilé 1306 octets.
...
De plus je peux gérer les tempo en fonction de la voie de circulation (les feux sur une route à 90km/h croisant une rue à 50km/h sont plus longs).
Effectivement, ce nouveau programme de feux tricolores fonctionne parfaitement. Dans celui proposé dans Loco-Revue, il était aussi possible de régler différemment les longueurs de feux pour chacune des voies, puisqu'on traite les feux les uns après les autres (voir programme). Ceci avait d'ailleurs été indiqué dans l'encadré page 102. :wink:

De plus, pourquoi fabriquer une temporisation et ne pas utiliser delay ? :?: :?: Contrairement à ce que tu penses, la fonction delay ne fait que cela quand elle tourne, mais s'arrête en cas d'interruption. Voici ce qu'on peut lire sur le site Arduino, page Reference - delay :

Certain things do go on while the delay() function is controlling the Atmega chip however, because the delay function does not disable interrupts. Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, and interrupts will work as they should.

Bravo tout de même pour ta réalisation ! :applause:

Christian

Avatar du membre
Arduino
Prolixe
Messages : 1701
Enregistré le : mer. 25 sept. 2013, 17:14

Re: Article Arduino de LR 798 (janvier 2014)

Message par Arduino » sam. 08 févr. 2014, 15:52

Feux tricolores en mode clignotant

Dans l'article publié dans Loco-Revue de janvier 2014, je vous ai proposé d'améliorer le montage en prévoyant un mode secours (ou nocturne) où les feux sont tous oranges et clignotants. Quelques mails m'ont été envoyés pour demander la solution ; voici quelques éléments qui vous permettront de trouver la solution finale de vous-mêmes. :wink:

Monter un interrupteur sur l'entrée numérique 10, selon le schéma de la figure 4, en remplaçant le poussoir par l’interrupteur (celui-ci étant ouvert, c’est comme si on n’appuie pas sur le poussoir, celui-ci étant fermé, c’est comme si le poussoir était appuyé).

Vous avez 2 solutions : soit le 4a, lorsque l’interrupteur est fermé, l’entrée 10 voit un signal LOW (0 V), soit le 4b, interrupteur fermé, l’entrée 10 voit un signal HIGH (5 V).

Choisissez la solution que vous voulez, cela n’a aucune importance. :coeur1:

La broche 10 est une entrée (elle reçoit un signal, elle n’en émet aucun). Il faut la déclarer comme tel par pinMode (10, INPUT)
 
Il faut maintenant modifier votre programme pour surveiller votre interrupteur, ce que vous ferez au début de la boucle loop. La fonction du langage Arduino est digitalRead (10). Le résultat de cette fonction est soit LOW, soit HIGH, ce qui représente l’état de l’interrupteur (en fait LOW est égal à 0 et HIGH est égal à 1, mais c’est plus pratique de garder HIGH et LOW). On met ce résultat dans une variable (de type byte) qu’on appelle etat (attention, jamais d’accent avec le langage Arduino qui est de l’anglais).

Voici donc trois lignes de code à rajouter (aux bons endroits :ange: ) :
byte etat = 0 ;
pinMode (10, INPUT) ;
etat = digitalRead (10) ;
 
Supposons que vous ayez monté l’interrupteur selon le schéma 4b :
Votre programme connaît maintenant l’état de l’interrupteur. Si celui-ci est ouvert (etat = LOW), alors on fait réaliser la séquence de feux telle qu’elle est définie dans le programme de l’article, si l’interrupteur est fermé (etat = HIGH), on fait clignoter toutes les LED oranges (après avoir éteint les autres LED rouges et vertes).

Mais il reste à faire prendre une décision à votre programme (en fonction de etat). Pour cela, je préconise d’utiliser une fonction if ... else ... qui peut se traduire par si ... autrement ...
 
Juste après avoir testé l’interrupteur, c’est-à-dire après avoir attribué une valeur à etat, il faut faire le test :
if (etat == LOW)
{
mettre ici le programme de feu tricolore
}
else
{
mettre ici le programme de clignotement des feux oranges en s’inspirant du programme blink donné en exemple ou du premier programme publié dans le deuxième article (novembre)
}

Notez bien le double signe égal :diable: ! Ce qui est en italique est des portions de codes comme ceux publiés dans les articles Loco-Revue (clignotement (novembre 2013) ou bien feu tricolore (janvier 2014)).
 
Si vous avez choisi de monter votre interrupteur selon le schéma 4a, il suffit de faire le test par if (etat == HIGH), le reste est identique.
 
Attention : lorsque vous fermerez l'interrupteur, les feux continueront leur cycle (vert, orange, rouge) jusqu'au bout avant de clignoter orange, car l'état de l'interrupteur est testé en début de boucle loop.

Voilà. Avec ces quelques indications, vous devriez arriver à écrire votre programme. :wink:

Avatar du membre
Arduino
Prolixe
Messages : 1701
Enregistré le : mer. 25 sept. 2013, 17:14

Re: Article Arduino de LR 798 (janvier 2014)

Message par Arduino » dim. 09 févr. 2014, 19:40

Arduino a écrit : .......
Attention : lorsque vous fermerez l'interrupteur, les feux continueront leur cycle (vert, orange, rouge) jusqu'au bout avant de clignoter orange, car l'état de l'interrupteur est testé en début de boucle loop.
Ceux qui veulent que les feux clignotent oranges dès que l'interrupteur est fermé (donc sans attendre la fin du cycle) peuvent faire appel à une interruption externe. :wink:

Pour en savoir plus, consulter le forum Arduino et le traitement de l'information :roll: ; l'écriture d'un programme avec interruption est un très bon exercice qui vous servira à bien des choses.

Amusez-vous bien. :wink:

Répondre