Feu rouge avec automate à états

Bonjour à tous et toutes,

Je galère depuis plusieurs jour sur le codage d'un feu rouge avec automate d'état je pense pas être loin mais j'ai une erreur de fonctionnement.

Je suis preneur d'avis et de conseil, Merci par avance

// les pin utilisés pour les boutons
const byte APPUI_PIETON = 2;                      // notre bouton est sur la pin 2

// les pins utilisées pour les LEDs
const int FEU_VERT_PIETON = 8;                    // Broche n°8 led verte feu pièton
const int FEU_ROUGE_PIETON = 9;                    // Broche n°9 led rouge feu pièton
const int FEU_VERT_VOITURE = 10;                  // Broche n°10 led verte feu tricolore
const int FEU_ORANGE_VOITURE = 11;                  // Broche n°11 led verte feu tricolore
const int FEU_ROUGE_VOITURE = 12;                  // Broche n°12 led verte feu tricolore

// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {CYCLE_ROUGE, CYCLE_ORANGE, CYCLE_VERT, CYCLE_PIETON} etatCourant;

// Constantes définissant les temps de cycles en millisecondes
const uint32_t TEMPS_CYCLE_ROUGE = 3000;
const uint32_t TEMPS_CYCLE_ORANGE = 1000;
const uint32_t TEMPS_CYCLE_VERT = 3000;
const uint32_t TEMPS_CYCLE_PIETON = 5000;

// Variables régissant le fonctionnement de l'automate
bool demande_pieton;  // Enregistre l'appui du signal piéton pendant le cycle vert
uint8_t etat;     // Etat courant de l'automate
uint32_t tempsDebutCycle; // Horaire en millisecondes auquel a commencé le cycle courant de l'automate

// ------------------------------------------------------
// Cette fonction installe l'état initial
// ------------------------------------------------------
void demarrage()
{
  digitalWrite(FEU_VERT_PIETON, LOW);
  digitalWrite(FEU_ROUGE_PIETON, LOW);
  digitalWrite(FEU_VERT_VOITURE, LOW);
  digitalWrite(FEU_ORANGE_VOITURE, LOW);
  digitalWrite(FEU_ROUGE_VOITURE, LOW);
  etatCourant = CYCLE_ROUGE;
  demande_pieton = false;
  tempsDebutCycle = millis();
}

// ------------------------------------------------------
// On initialise notre système dans le setup
// ------------------------------------------------------
void setup() {
  pinMode (FEU_VERT_PIETON, OUTPUT);
  pinMode (FEU_ROUGE_PIETON, OUTPUT);
  pinMode (FEU_VERT_VOITURE, OUTPUT);
  pinMode (FEU_ORANGE_VOITURE, OUTPUT);
  pinMode (FEU_ROUGE_VOITURE, OUTPUT);
  pinMode (APPUI_PIETON, INPUT);

  //conditions Initiales
  demarrage();

}

void loop() {
 switch(etat)
  {
    case CYCLE_ROUGE:
    // Si temps de cycle écoulé, on passe au feu vert
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ROUGE)
    {
      etat = CYCLE_VERT;
      digitalWrite(FEU_ROUGE_VOITURE, LOW);
      digitalWrite(FEU_VERT_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_VERT:
    // Enregistrer l'appui piéton
    if (digitalRead(APPUI_PIETON) == HIGH)
    {
      demande_pieton = true;
    }
    // Si temps de cycle écoulé ou demande piéton, on passe à l'orange
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_VERT || demande_pieton)
    {
      etat = CYCLE_ORANGE;
      digitalWrite(FEU_VERT_VOITURE, LOW);
      digitalWrite(FEU_ORANGE_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    
    case CYCLE_ORANGE:
    // Si le temps de cycle est écoulé, on passe le feu au rouge
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ORANGE)
    {
      digitalWrite(FEU_ORANGE_VOITURE, LOW);
      digitalWrite(FEU_ROUGE_VOITURE, HIGH);
      // En cas d'appui piéton lors du cycle vert, on va au cycle piéton
      if (demande_pieton)
      {
        etat = CYCLE_PIETON;
        digitalWrite(FEU_VERT_PIETON, HIGH);
        demande_pieton = false;
      }
      // Sinon au feu rouge voiture
      else
        etat = CYCLE_ROUGE;
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_PIETON:
    // Si le temps de cycle est écoulé, on fait un cycle feu rouge voiture
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_PIETON)
    {
      etat = CYCLE_ROUGE;
      digitalWrite(FEU_ROUGE_PIETON, HIGH);
      digitalWrite(FEU_VERT_PIETON, LOW);
      tempsDebutCycle = millis();
    }
    break;
  }
}

Manque un break au cycle vert
Vérifiez le commentaire et ce que vous faites pour le bouton piéton en cycle orange

Pas sûr de bien comprendre le cycle rouge versus cycle piéton - vous pouvez poster le dessin des états?

Bonsoir J-M-L,

Merci déjà pour le break malgré multiple relecture je ne l'avais point vu.

Je vous joins en jpeg le dessin d'état

Le fonctionnement que je recherche est que l'on puisse détecter le premier appui sur le bouton appel piéton lors du cycle vert et dans ce cas lancer le cycle piéton après le cycle orange au lieu du cycle rouge

lien tinkercad : Login | Tinkercad

Code modifier:

// les pin utilisés pour les boutons
const byte APPUI_PIETON = 2;                      // notre bouton est sur la pin 2

// les pins utilisées pour les LEDs
const int FEU_VERT_PIETON = 8;                    // Broche n°8 led verte feu pièton
const int FEU_ROUGE_PIETON = 9;                    // Broche n°9 led rouge feu pièton
const int FEU_VERT_VOITURE = 10;                  // Broche n°10 led verte feu tricolore
const int FEU_ORANGE_VOITURE = 11;                  // Broche n°11 led verte feu tricolore
const int FEU_ROUGE_VOITURE = 12;                  // Broche n°12 led verte feu tricolore

// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {CYCLE_ROUGE, CYCLE_ORANGE, CYCLE_VERT, CYCLE_PIETON} etatCourant;

// Constantes définissant les temps de cycles en millisecondes
const uint32_t TEMPS_CYCLE_ROUGE = 3000;
const uint32_t TEMPS_CYCLE_ORANGE = 1000;
const uint32_t TEMPS_CYCLE_VERT = 3000;
const uint32_t TEMPS_CYCLE_PIETON = 5000;

// Variables régissant le fonctionnement de l'automate
bool demande_pieton;  // Enregistre l'appui du signal piéton pendant le cycle vert
uint8_t etat;     // Etat courant de l'automate
uint32_t tempsDebutCycle; // Horaire en millisecondes auquel a commencé le cycle courant de l'automate

// ------------------------------------------------------
// Cette fonction installe l'état initial
// ------------------------------------------------------
void demarrage()
{
  digitalWrite(FEU_VERT_PIETON, LOW);
  digitalWrite(FEU_ROUGE_PIETON, HIGH);
  digitalWrite(FEU_VERT_VOITURE, LOW);
  digitalWrite(FEU_ORANGE_VOITURE, LOW);
  digitalWrite(FEU_ROUGE_VOITURE, HIGH);
  etatCourant = CYCLE_ROUGE;
  demande_pieton = false;
  tempsDebutCycle = millis();
}

// ------------------------------------------------------
// On initialise notre système dans le setup
// ------------------------------------------------------
void setup() {
  pinMode (FEU_VERT_PIETON, OUTPUT);
  pinMode (FEU_ROUGE_PIETON, OUTPUT);
  pinMode (FEU_VERT_VOITURE, OUTPUT);
  pinMode (FEU_ORANGE_VOITURE, OUTPUT);
  pinMode (FEU_ROUGE_VOITURE, OUTPUT);
  pinMode (APPUI_PIETON, INPUT);

  //conditions Initiales
  demarrage();

}

void loop() {
 switch(etat)
  {
    case CYCLE_ROUGE:
    // Si temps de cycle écoulé, on passe au feu vert
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ROUGE)
    {
      etat = CYCLE_VERT;
      digitalWrite(FEU_ROUGE_VOITURE, LOW);
      digitalWrite(FEU_VERT_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_VERT:
    // Enregistrer l'appui piéton
    if (digitalRead(APPUI_PIETON) == HIGH)
    {
      demande_pieton = true;
    }
    // Si temps de cycle écoulé ou demande piéton, on passe à l'orange
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_VERT || demande_pieton)
    {
      etat = CYCLE_ORANGE;
      digitalWrite(FEU_VERT_VOITURE, LOW);
      digitalWrite(FEU_ORANGE_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
   
    case CYCLE_ORANGE:
    // Si le temps de cycle est écoulé, on passe le feu au rouge
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ORANGE)
    {
      digitalWrite(FEU_ORANGE_VOITURE, LOW);
      digitalWrite(FEU_ROUGE_VOITURE, HIGH);
      // En cas d'appui piéton lors du cycle vert, on va au cycle piéton
      if (demande_pieton)
      {
        etat = CYCLE_PIETON;
        digitalWrite(FEU_ROUGE_PIETON, LOW);
        digitalWrite(FEU_VERT_PIETON, HIGH);
        demande_pieton = false;
      }
      // Sinon au feu rouge voiture
      else
        etat = CYCLE_ROUGE;
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_PIETON:
    // Si le temps de cycle est écoulé, on fait un cycle feu rouge voiture
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_PIETON)
    {
      etat = CYCLE_ROUGE;
      digitalWrite(FEU_ROUGE_PIETON, HIGH);
      digitalWrite(FEU_VERT_PIETON, LOW);
      tempsDebutCycle = millis();
    }
    break;
  }
}

Et quelle est l’erreur de fonctionnement maintenant ?
Votre diagramme ne montre pas bien les transitions, par exemple comment lire qu’après un cycle piéton on reste pour un cycle rouge ?

Comment est câblé votre bouton ?

C'est drôle les posts que l'on voit apparaître en même temps que les Tp d'un Mooc consacré à l'apprentissage de l'Arduino actuellement diffusé.
Ça doit être ça la définition de la coïncidence..

Bonsoir,

Pour répondre à Elafye
Je ne pense pas au coïncidence cela fait 10 jours que je me suis mis à Arduino juste un peu avant l'ouverture du mooc. Pour ton information les consigne du TP sont proche mais pas identique je trouvais seulement complètement chiant de devoir maintenir appuyer 3 seconde sur le bouton donc j'ai lu tous se que je trouver sur les interruption de programme mais le résultat ne me convenais pas plus donc j'ai fini mes recherches sur la machine à états et cela ne fait pas parti du TP. En 10 jours je doit avouer que je suis pas mécontent du résultat. Après si cela te pose un problème qu'on pose des questions sur le forum pour chercher d'autre solution pour améliorer l'idée de base du tp je pense que le mieux c'est que tu passe ton chemin.

Consignes du TP

Fonctionnement normal :

  • Feu tricolore : même consigne que la semaine dernière
  • Une LED verte (branchée sur la broche 10) allumée pendant 3 secondes (c'est la première LED à s'allumer)
  • Puis une LED orange (branchée sur la broche 11) allumée pendant 1 seconde
  • Enfin, une LED rouge (branchée sur la broche 12) allumée pendant 3 secondes
  • Feu bicolore (piéton)
  • Le feu piéton est constamment rouge (rouge→broche 9 et vert→ broche 8) tant que le bouton (broche 2) n'est pas appuyé
    Si le bouton est maintenu appuyé pendant que le feu voiture est au vert, alors le feu tricolore passe au orange allumé pendant 1 seconde puis rouge pendant 5 secondes durant lesquelles le feu vert piéton passe au vert.
    Attention, laissez bien votre doigt appuyé suffisamment longtemps sur le bouton pour que le feu piéton passe au vert
  • Après ces 5 secondes, le feu piéton repasse au rouge et le fonctionnement normal reprend (à partir du vert pour le feu tricolore)

Code que j'ai réaliser pour le TP

/*

// Initialisation des constantes :
const int buttonPin2 = 2;                 // Broche n°2 bouton poussoir pièton
const int ledPin8 = 8;                    // Broche n°8 led verte feu pièton
const int ledPin9 = 9;                    // Broche n°9 led rouge feu pièton
const int ledPin10 = 10;                  // Broche n°10 led verte feu tricolore
const int ledPin11 = 11;                  // Broche n°11 led verte feu tricolore
const int ledPin12 = 12;                  // Broche n°12 led verte feu tricolore

// Déclaration des variables :
int buttonState = 0;                      // variable qui sera utilisée pour stocker l'état du bouton

// le code dans cette fonction est exécuté une fois au début
void setup() {
  pinMode(ledPin8, OUTPUT);               // indique que la broche ledPin8 est une sortie
  pinMode(ledPin9, OUTPUT);               // indique que la broche ledPin9 est une sortie
  pinMode(ledPin10, OUTPUT);              // indique que la broche ledPin10 est une sortie
  pinMode(ledPin11, OUTPUT);              // indique que la broche ledPin11 est une sortie
  pinMode(ledPin12, OUTPUT);              // indique que la broche ledPin12 est une sortie   
  pinMode(buttonPin2, INPUT);             // indique que la broche buttonPin est une entrée  
}


// le code dans cette fonction est exécuté en boucle
void loop(){
  digitalWrite(ledPin9, HIGH);            // allumer la LED rouge feu piéton (tension 5V sur la broche)
  digitalWrite(ledPin10, HIGH);           // allumer la LED verte feu tricolore (tension 5V sur la broche)
  delay(3000);                            // attendre 3000ms = 3s  
  buttonState = digitalRead(buttonPin2);  // lit l'état du bouton et stocke le résultat dans buttonState 
  digitalWrite(ledPin10, LOW);            // éteindre la LED verte feu tricolore (tension 0V sur la broche)
  if (buttonState == HIGH) {              // Si buttonState est à 5V (HIGH→bouton appuyé)
    digitalWrite(ledPin11, HIGH);         // allumer la LED orange feu tricolore (tension 5V sur la broche)
    delay(1000);                          // attendre 1000ms = 1s
    digitalWrite(ledPin11, LOW);          // éteindre la LED orange feu tricolore (tension 0V sur la broche)
    digitalWrite(ledPin12, HIGH);         // allumer la LED rouge feu tricolore (tension 5V sur la broche)
    digitalWrite(ledPin9, LOW);           // éteindre la LED rouge feu piéton (tension 0V sur la broche)
    digitalWrite(ledPin8, HIGH);          // allumer la LED verte feu piéton (tension 5V sur la broche)
    delay(5000);                          // attendre 5000ms = 5s
    digitalWrite(ledPin8, LOW);           // éteindre la LED verte feu piéton (tension 0V sur la broche)
    digitalWrite(ledPin9, HIGH);          // allumer la LED rouge feu piéton (tension 5V sur la broche)      
    digitalWrite(ledPin12, LOW);          // éteindre la LED rouge feu tricolore (tension 5V sur la broche)  
  } 
  else {                                  // sinon buttonState est à 0V (Low→bouton non appuyé)
    digitalWrite(ledPin11, HIGH);         // allumer la LED orange feu tricolore (tension 5V sur la broche)
    delay(1000);                          // attendre 1000ms = 1s
    digitalWrite(ledPin11, LOW);          // éteindre la LED orange feu tricolore (tension 0V sur la broche)
    digitalWrite(ledPin12, HIGH);         // allumer la LED rouge feu tricolore (tension 5V sur la broche)
    delay(3000);                          // attendre 3000ms = 3s
    digitalWrite(ledPin12, LOW);          // éteindre la LED rouge feu tricolore (tension 0V sur la broche)
  }
}

Pour répondre à J_M_L

le problème que j'avais était le doublement du feu rouge à la fin d'opération mais en relisant j'ai trouver mon erreur. Partie cycle piéton modifier Code fonctionnel comme je le souhaiter sans devoir maintenir le bouton piéton. merci pour le tutoriel sur les machines à états sur le forum ca m'a aidé

// les pin utilisés pour les boutons
const byte APPUI_PIETON = 2;                      // notre bouton est sur la pin 2

// les pins utilisées pour les LEDs
const int FEU_VERT_PIETON = 8;                    // Broche n°8 led verte feu pièton
const int FEU_ROUGE_PIETON = 9;                    // Broche n°9 led rouge feu pièton
const int FEU_VERT_VOITURE = 10;                  // Broche n°10 led verte feu tricolore
const int FEU_ORANGE_VOITURE = 11;                  // Broche n°11 led verte feu tricolore
const int FEU_ROUGE_VOITURE = 12;                  // Broche n°12 led verte feu tricolore

// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {CYCLE_ROUGE, CYCLE_ORANGE, CYCLE_VERT, CYCLE_PIETON} etatCourant;

// Constantes définissant les temps de cycles en millisecondes
const uint32_t TEMPS_CYCLE_ROUGE = 3000;
const uint32_t TEMPS_CYCLE_ORANGE = 1000;
const uint32_t TEMPS_CYCLE_VERT = 3000;
const uint32_t TEMPS_CYCLE_PIETON = 5000;

// Variables régissant le fonctionnement de l'automate
bool demande_pieton;  // Enregistre l'appui du signal piéton pendant le cycle vert
uint8_t etat;     // Etat courant de l'automate
uint32_t tempsDebutCycle; // Horaire en millisecondes auquel a commencé le cycle courant de l'automate

// ------------------------------------------------------
// Cette fonction installe l'état initial
// ------------------------------------------------------
void demarrage()
{
  digitalWrite(FEU_VERT_PIETON, LOW);
  digitalWrite(FEU_ROUGE_PIETON, HIGH);
  digitalWrite(FEU_VERT_VOITURE, LOW);
  digitalWrite(FEU_ORANGE_VOITURE, LOW);
  digitalWrite(FEU_ROUGE_VOITURE, HIGH);
  etatCourant = CYCLE_ROUGE;
  demande_pieton = false;
  tempsDebutCycle = millis();
}

// ------------------------------------------------------
// On initialise notre système dans le setup
// ------------------------------------------------------
void setup() {
  pinMode (FEU_VERT_PIETON, OUTPUT);
  pinMode (FEU_ROUGE_PIETON, OUTPUT);
  pinMode (FEU_VERT_VOITURE, OUTPUT);
  pinMode (FEU_ORANGE_VOITURE, OUTPUT);
  pinMode (FEU_ROUGE_VOITURE, OUTPUT);
  pinMode (APPUI_PIETON, INPUT);

  //conditions Initiales
  demarrage();

}

void loop() {
 switch(etat)
  {
    case CYCLE_ROUGE:
    // Si temps de cycle écoulé, on passe au feu vert
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ROUGE)
    {
      etat = CYCLE_VERT;
      digitalWrite(FEU_ROUGE_VOITURE, LOW);
      digitalWrite(FEU_VERT_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_VERT:
    // Enregistrer l'appui piéton
    if (digitalRead(APPUI_PIETON) == HIGH)
    {
      demande_pieton = true;
    }
    // Si temps de cycle écoulé ou demande piéton, on passe à l'orange
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_VERT)
    {
      etat = CYCLE_ORANGE;
      digitalWrite(FEU_VERT_VOITURE, LOW);
      digitalWrite(FEU_ORANGE_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
   
    case CYCLE_ORANGE:
    // Si le temps de cycle est écoulé, on passe le feu au rouge
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_ORANGE)
    {
      digitalWrite(FEU_ORANGE_VOITURE, LOW);
      digitalWrite(FEU_ROUGE_VOITURE, HIGH);
      // En cas d'appui piéton lors du cycle vert, on va au cycle piéton
      if (demande_pieton)
      {
        etat = CYCLE_PIETON;
        digitalWrite(FEU_ROUGE_PIETON, LOW);
        digitalWrite(FEU_VERT_PIETON, HIGH);
        demande_pieton = false;
      }
      // Sinon au feu rouge voiture
      else
        etat = CYCLE_ROUGE;
      tempsDebutCycle = millis();
    }
    break;
    
    case CYCLE_PIETON:
    // Si le temps de cycle est écoulé, on fait un cycle feu rouge voiture
    if (millis() - tempsDebutCycle > TEMPS_CYCLE_PIETON)
    {
      etat = CYCLE_VERT;
      digitalWrite(FEU_ROUGE_PIETON, HIGH);
      digitalWrite(FEU_VERT_PIETON, LOW);
      digitalWrite(FEU_ROUGE_VOITURE, LOW);
      digitalWrite(FEU_VERT_VOITURE, HIGH);
      tempsDebutCycle = millis();
    }
    break;
  }
}

Bravo et bonnes recherches perso! +1 karma pour cela