Table des matières

, , ,

Arduino: Passage à niveau

Schéma du montage

Sketch

Ci-dessous le programme complet.

/*
  Fun MOOC, Programmer un objet avec Arduino
  TP 04: Le passage à niveau
 
  Le fonctionnement normal est un feu allumé au rouge (le feu vert est éteint) et une barrière fermée (0°).
  Le fonctionnement normal est interrompu par l'appui sur un bouton poussoir.
  Si l'appui du bouton est détecté, alors la barrière (actionnée par le servomoteur) se relève doucement.
  Lorsque la barrière est à la verticale (90°), le feu vert s'allume pendant 5 secondes pendant lesquelles la barrière reste ouverte (90°) et le feu rouge s'éteint.
  Après les 5 secondes, le feu repasse au rouge, la barrière redescend doucement et le fonctionnement normal reprend.
  Nous souhaitons recevoir le message "Bouton appuye" dans le moniteur série lorsque l'appui a été détecté.
 
  A propos du montage:
  - Un servomoteur branché sur les broches 9, +5V et GND)
  - Un bouton pour demander l'ouverture de la barrière branché sur la broche 2 avec resistance de pull down de 1KΩ
  - Un feu bicolore qui passera au vert lorsque la barrière sera complètement ouverte
  - Avec une LED rouge sur la broche 3 en serie avec une resistance de 220Ω
  - Avec une LED verte sur la broche 4 en serie avec une resistance de 220Ω
*/
 
// On inclus la bibliothèque Servo afin de bénéficier des fonctions de pilotage des servomoteurs
#include <Servo.h>
 
const int GREEN_LED = 4;
const int RED_LED = 3;
 
 
const int PIN_SERVO = 9;
const int GATE_MOTOR_STEP=1; //Permet de regler la vitesse d'ouverture/fermeture de la barriere, pas de 1° par défaut.
                              //Valeurs conseillées de 1 à 10.
 
//servo moteur de la barriere
Servo gate_motor;
 
// Broche reliée au bouton de demande de levée de barrière (montage PULL DOWN identique au TP 02)
const int BUTTON_PIN = 2;
 
//variable d'enregistrement d'une demande de levée de barriere.
bool cross_request = false;
 
 
//NB: C'est le dernier TP, aucune information n'a été donnée au sujet de la déclaration/définition de types et de fonctions.
// J'ai fait le choix les utiliser pour augmenter la lisibilité dans la boucle principale et la maintenance du code.
 
// Définition du type enuméré traffic_light pouvant prendre 2 valeurs RED ou GREEN
enum traffic_light {RED, GREEN};
 
/**
 * Fonction: trafficLightTo()
 * Role: Controle le feu de signalisation
 * Parametres:
 *   const traffic_light l: Ne peut prendre que deux valeurs: soit RED, soit GREEN selon le feu à allumer.
 * Retour: Néant
 */
void trafficLightTo(const traffic_light l);
 
// Définition d'un type enuméré gate_position pouvant prendre 2 valeurs OPEN ou CLOSE
enum gate_position {OPEN, CLOSE};
 
/**
 * Fonction: setGate()
 * Role: Controle l'ouverture et la fermeture le la barrière.
 * Parametres:
 *   const gate_position p: Ne peut prendre que deux valeurs: soit OPEN, soit CLOSE pour ouvrir ou fermer la barriere.
 * Retour: Néant
 */
void setGate(const gate_position p);
 
 
void setup() {
  //Initialisation de la connexion série à 9600 bauds
  Serial.begin(9600);
 
  //Les broches reliées aux DELs sont configurées en sorties
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
 
  gate_motor.attach(PIN_SERVO);
 
  // L'etat du boutton est lu, configuration en entrée
  pinMode(BUTTON_PIN, INPUT);
 
  //Etat initial: on passe le feu au rouge, la barriere doit être baissée
  trafficLightTo(RED);
  gate_motor.write(0);
}
 
void loop() {
 
   if(digitalRead(BUTTON_PIN) == HIGH)
  {
    // Le bouton est enfoncé, on enregistre la demande de traversée.
    cross_request = true;
 
    //envoi du message sur port serie
    Serial.println("Bouton appuye");
  }
 
  if(cross_request == true)
  {
    // Une demande de traversée a été enregistrée.
    // Ouvrir la barriere et passer le feu au vert
    setGate(OPEN);
    trafficLightTo(GREEN);
    // 5 secondes pour passer
    delay(5000);
 
    //Délai écoulé on condamne le passage.
    //Passer le feu au rouge et refermer la barriere
    trafficLightTo(RED);
    setGate(CLOSE);
 
    // La demande de traversée a été prise en compte, on réinitialise la valeur
    cross_request = false;
  }
 
 
}
 
void trafficLightTo(const traffic_light l)
{
   switch (l) {
        case RED:
            //eteint le vert
            digitalWrite(GREEN_LED, LOW);
            //allume le rouge
            digitalWrite(RED_LED, HIGH);
            break;
 
        case GREEN:
            //eteint le rouge
            digitalWrite(RED_LED, LOW);
            //allume le vert
            digitalWrite(GREEN_LED, HIGH);
            break;
    }
}
 
void setGate(const gate_position p)
{
  volatile int pos; //declarer cette variable volatile permet conserver sa valeur entre les appels de la fonction.
 
  switch (p) {
     case OPEN:
         //Boucle d'ouverture progressive de 0 à 90°
         for (pos = 0; pos <= 90; pos += GATE_MOTOR_STEP)
         {
           gate_motor.write(pos);   // Demande au servo de prendre la position de consigne dans la variable pos
           delay(15);               // Attendre quelques millisecondes pour laisser le servo atteindre la position de consigne pos
         }
         break;
 
     case CLOSE:
         //Boucle de fermeture progressive
         for (pos = 90; pos >= 0; pos -= GATE_MOTOR_STEP)
         {
           gate_motor.write(pos);   // Demande au servo de prendre la position de consigne dans la variable pos
           delay(15);               // Attendre quelques millisecondes pour laisser le servo atteindre la position de consigne pos
         }
         break;
    }
 
}