Le réseau : Gestion de canton par Infra-Rouges et arduino

Voici le prototype d'une détection de présence sur un canton par infra-rouge et arduino. J'utiliserai peut-être ce module pour l'arrêt temporisé en gare. Il faut que je fasse un PCB pour tester la fiabilité en conditions réelles.

 


Le PCB est réalisé, comme d'habitude, par JLCPCB. Il y a sans aucun doute des améliorations à faire sur le code.

CIMG9675.JPG

Mise en mémoire de la dernière position en cas de coupure d'alimentation :

 

Essai de mise en place sous voie. Les réglages risquent d'être difficiles compte-tenu de la réactivité des détecteurs aux formes/volumes/couleurs des dessous de wagons/voitures.

 

Tests définitifs. Code revu et amélioré. Tout fonctionne à merveille.

 

Version définitive : Merci au site Locoduino pour la gestion des espaces entre les wagons/voitures => tout est OK

 

voici la dernière mouture du programme



#include 
#include 

/* Ecran OLED 128 X 64 en I2C */
#include 
#include 

Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire);
/* ========================== */

const byte pinDetecteurIR_A  = 2;                                                       // pin du detecteur IR A sur D2
const byte pinDetecteurIR_B  = 3;                                                        // pin du detecteur IR B sur D3
const byte pinLedRouge = 6;                                                             // pins des leds du signal
const byte pinLedJaune = 7;
const byte pinLedVerte = 8;
const byte pinRelaisOccupation = 12;                                                    // pin du transistor pour relais
const byte ledTemoin = 13;                                                              // témoin de lecture des détecteur = led interne

const byte pinReglageTempoLecture = A0;                                                 // potentiometre de réglage du temps de lecture
const byte pinReglageTempoLedJaune = A1;                                                // potentiometre de reglaage du temps d'affichage de la led de signal jaune
const byte pinDistance_A = A2;                                                          // sortie de IR A connecté à A2 lecture du réglage distance IR
const byte pinDistance_B = A3;                                                          // sortie de IR B connecté à A3 lecture du réglage distance IR
const byte pinSDA = A4;                                                                 // Réservé pour l'affichage si carte Uno
const byte pinSCL = A5;                                                                 // Réservé pour l'affichage si carte Uno

/*  pour un ATtiny 84
const byte pinDetecteurIR_A = PA5;                                                      // pin du detecteur IR A sur D2
const byte pinDetecteurIR_B = PA7;                                                      // pin du detecteur IR B sur D3
const byte pinRelaisOccupation = PB0;                                                    // pin du transistor pour relais
const byte pinLedJaune = PB1;                                                           // pins des leds du signal

const byte pinReglageTempoLecture = PA0;                                                // potentiometre de réglage du temps de lecture
const byte pinReglageTempoLedJaune = PA1;                                               // potentiometre de reglaage du teemps d'affichage de la led de signal jaune
const byte pinDistance_A = PA2;                                                         // sortie de IR A connecté à A2 lecture du réglage distance IR
const byte pinDistance_B = PA3;                                                         // sortie de IR B connecté à A3 lecture du réglage distance IR
const byte pinSDA = PA6;                                                                // Réservé pour l'affichage 
const byte pinSCL = PA4;                                                                // Réservé pour l'affichage
========================== */
 
bool etatRelaisOccupation = 0;                                                     // relais désactivé
bool etatDetecteurIR_A = 0;                                                        // etat courant du detecteur IR A
bool last_etatDetecteurIR_A = 0;
bool etatDetecteurIR_B = 0;                                                        // etat courant du detecteur IR B
bool last_etatDetecteurIR_B = 0;
int distance_A;                                                                   // enregistre la valeur de la sortie A0 de IR A
int distance_B;                                                                   // enregistre la valeur de la sortie A0 de IR B

long tempoLecture;                                                                // temps entre 2 lectures (en ms)
long last_potentiometre_tempoLecture;
long potentiometre_tempoLecture;

long last_tempoLectureA;
long last_tempoLectureB;
long last_debut_tempoLecture = 0;

long tempoLed = 3000;                                                             // temps affichage jaune clignotant (en ms)
long last_tempoLed;
int potentiometre_tempoLed;

bool etatCanton = 0;                                                                //  0 = pas de présence
bool dernierEtatCanton;
bool precedentEtatCanton = 0; 

/* les drapeaux d'affichage */
byte Z = 0;
byte Y = 0;

void setup() {

  Serial.begin(9600);
  Serial.println("Bienvenue dans la");
  Serial.println("gestion de canton");
  Serial.println("par Infra Rouge.");
  Serial.println("");
  
  pinMode(pinDetecteurIR_A, INPUT);
  pinMode(pinDetecteurIR_B, INPUT);
  pinMode(pinLedRouge,OUTPUT);
  pinMode(pinLedJaune,OUTPUT);
  pinMode(pinLedVerte,OUTPUT);
  pinMode(ledTemoin, OUTPUT);
  pinMode(pinReglageTempoLecture, INPUT);
  pinMode(pinReglageTempoLedJaune, INPUT);
  pinMode(pinRelaisOccupation, OUTPUT);

  /* initialisation de la led témoin de l'arduino*/
  digitalWrite(ledTemoin, LOW);
  /* =========================================== */
 
  /* initialisation du relais */
  // lecture de la dernière position dans l'eeprom
  dernierEtatCanton = EEPROM.read(1) | ((int)EEPROM.read(2)) << 8;
  if ((dernierEtatCanton <0)||(dernierEtatCanton >1)) dernierEtatCanton = 0;
  etatRelaisOccupation = dernierEtatCanton;
  digitalWrite(pinRelaisOccupation, etatRelaisOccupation);
  
  if (dernierEtatCanton == 0){
    etatCanton = 0;
    digitalWrite(pinLedRouge,LOW);
    digitalWrite(pinLedJaune,LOW);
    digitalWrite(pinLedVerte,HIGH);
  } else { 
    etatCanton = 1;
    digitalWrite(pinLedRouge,HIGH);
    digitalWrite(pinLedJaune,LOW);
    digitalWrite(pinLedVerte,LOW);
  }
  
  /* ======================== */

  tempoLecture = EEPROM.read(3) | ((int)EEPROM.read(4)) << 8;
  if (tempoLecture < 500) {
      tempoLecture = 500;
  } else if (tempoLecture > 3000){
      tempoLecture = 3000;
  } else {
      tempoLecture= 1500;   
  }

  /* Initialisation de l'écran OLED */
    display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32 
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.clearDisplay();
    display.setCursor(0,0);
    display.println("Bienvenue dans la");
    display.println("gestion de canton");
    display.println("par Infra Rouge.");
    display.display();
    delay(3000);
    display.clearDisplay();
    display.setCursor(0,0);
    display.print("Tempo lecture = ");
    display.println(tempoLecture);
    display.println(" ");
    display.print("PRET");
    display.display();
    delay(2000);
    display.clearDisplay();
    display.display();
  /* =================================================== */

  Serial.print("Tempo lecture = ");
  Serial.println(tempoLecture);
  Serial.println(" ");
  Serial.println("PRET");
   
} // Fin de setup

void reglagetempoLecture(void){
      potentiometre_tempoLecture = analogRead(pinReglageTempoLecture);
      tempoLecture = map(potentiometre_tempoLecture,0,1023,5,30); 
      tempoLecture = tempoLecture * 100;
      
      if ((potentiometre_tempoLecture < (last_potentiometre_tempoLecture - 50))||(potentiometre_tempoLecture > (last_potentiometre_tempoLecture + 50))){
            last_potentiometre_tempoLecture = potentiometre_tempoLecture;
            if (Z == 0){
                Z = 1;
                Y = 0;
                
                Serial.print("Nouvelle valeur de la tempo : "); Serial.println(tempoLecture);
                
                display.clearDisplay();
                display.setCursor(0,0);
                display.print("Tempo lecture = ");
                display.println(tempoLecture);
                display.display();
                delay(1000);
                display.clearDisplay();
                display.display();

                EEPROM.update(3, tempoLecture & 0xFF);                                       // écrit le premier byte de la valeur int
                EEPROM.update(4, tempoLecture >> 8);  
                
            }
      } else {
            if (Y == 0){
                Y = 1;
                Z = 0;
                //Serial.print("Tempo lecture regle a: ");Serial.println(tempoLecture);          
            }
      }

} // Fin de procédure

void Detect_IR_A()  {

   int etatA =! digitalRead(pinDetecteurIR_A);                                       // lecture du detecteur IR dans une variable locale
   if (etatA == LOW && etatA != last_etatDetecteurIR_A) {
       last_tempoLectureA = millis();
   } // Fin de if (etatA == LOW && etatA != last_etatDetecteurIR_A)
 
   if ((millis() - last_tempoLectureA) > tempoLecture) {                             // si le delai est atteint, le changement est valide                                                                                   // sinon le changement est ignore (parasite ou inter-wago

      if (etatA != etatDetecteurIR_A) {
        
          etatDetecteurIR_A = etatA;      
          digitalWrite(ledTemoin, etatDetecteurIR_A);
          Serial.println(etatDetecteurIR_A);
          if (etatCanton == 0){
              if (etatDetecteurIR_A == HIGH){             
                 digitalWrite(pinLedRouge,LOW);
                 /* sert a allumer la led jaune pendant l'entrée d'un train
                  *digitalWrite(pinLedJaune,HIGH);
                  *delay(tempoLed);  
                  */
                 digitalWrite(pinLedVerte,LOW);
                 
                 etatRelaisOccupation = 1;
                 
                 Serial.println("Entree du convoi par A en cours!");
                 
                 display.clearDisplay();
                 display.setCursor(0,0);
                 display.println("Entree du convoi");
                 display.println("par A en cours!");
                 display.display();
              } else {
                  etatCanton = 1;
                  
                  digitalWrite(pinLedRouge,HIGH);
                  digitalWrite(pinLedJaune,LOW);
                  digitalWrite(pinLedVerte,LOW);

                  Serial.println("Canton occupe!");
                  Serial.println("Entree par A!");
                 
                  display.clearDisplay();
                  display.setCursor(0,0);
                  display.println("Canton occupe!");
                  display.println("Entree par A!");
                  display.display();

                  /* Memorisation en EEprom */
                  dernierEtatCanton = 1;
                  EEPROM.update(1, dernierEtatCanton & 0xFF);                                       // écrit le premier byte de la valeur int
                  EEPROM.update(2, dernierEtatCanton >> 8);  
          
              } // Fin de if (etatDetecteurIR_A == HIGH)
          } else {
              if (etatDetecteurIR_A == HIGH){                
                 digitalWrite(pinLedRouge,LOW);
                 digitalWrite(pinLedJaune,HIGH);
                 delay(tempoLed);
                 digitalWrite(pinLedVerte,LOW);
                 
                 Serial.println("Sortie du convoi par A en cours");
                 
                 display.clearDisplay();
                 display.setCursor(0,0);
                 display.println("Sortie du convoi");
                 display.println("par A en cours!");
                 display.display();
              } else {
                  etatCanton = 0;
                  etatRelaisOccupation = 0;
                  digitalWrite(pinLedRouge,LOW);
                  digitalWrite(pinLedJaune,LOW);
                  digitalWrite(pinLedVerte,HIGH);

                  Serial.println("Canton Libre!");
                  Serial.println("Sortie par A!");
                  
                  display.clearDisplay();
                  display.setCursor(0,0);
                  display.println("Canton Libre!");
                  display.println("Sortie par A!");
                  display.display();

                  /* Memorisation en EEprom */
                  dernierEtatCanton = 0;
                  EEPROM.update(1, dernierEtatCanton & 0xFF);                                       // écrit le premier byte de la valeur int
                  EEPROM.update(2, dernierEtatCanton >> 8);  
          
              } // Fin de if (etatDetecteurIR_A == HIGH)  
          } // Fin de if (etatCanton == 0)
  
      } // Fin de if (etatA != etatDetecteurIR_A)
      
   } // Fin de if ((millis() - last_tempoLecture) > tempoLecture)
   last_etatDetecteurIR_A = etatA;

} // Fin de fonction

void Detect_IR_B()  {

   int etatB =! digitalRead(pinDetecteurIR_B);                                    // lecture du detecteur IR dans une variable locale
   if (etatB == LOW && etatB != last_etatDetecteurIR_B) {
       last_tempoLectureB = millis();
   } // Fin de if (etatB == LOW && etatB != last_etatDetecteurIR_B)
 
   if ((millis() - last_tempoLectureB) > tempoLecture) {                             // si le delai est atteint, le changement est valide                                                                                   // sinon le changement est ignore (parasite ou inter-wago

      if (etatB != etatDetecteurIR_B) {
        
          etatDetecteurIR_B = etatB;      
          digitalWrite(ledTemoin, etatDetecteurIR_B);
          Serial.println(etatDetecteurIR_B);
          if (etatCanton == 0){
              if (etatDetecteurIR_B == HIGH){
                 digitalWrite(pinLedRouge,LOW);
                 /* sert a allumer laa led jaune pendant l'entrée d'un train
                  *digitalWrite(pinLedJaune,HIGH);
                  *delay(tempoLed);  
                  */
                 digitalWrite(pinLedVerte,LOW);
                 
                 etatRelaisOccupation = 1;
                 
                 Serial.println("Entree du convoi par B en cours!");
                 
                 display.clearDisplay();
                 display.setCursor(0,0);
                 display.println("Entree du convoi");
                 display.println("par B en cours!");
                 display.display();
              } else {
                  etatCanton = 1;
                  
                  digitalWrite(pinLedRouge,HIGH);
                  digitalWrite(pinLedJaune,LOW);
                  digitalWrite(pinLedVerte,LOW);

                  Serial.println("Canton occupe!");
                  Serial.println("Entree par B!");
                 
                  display.clearDisplay();
                  display.setCursor(0,0);
                  display.println("Canton occupe!");
                  display.println("Entree par B!");
                  display.display();

                  /* Memorisation en EEprom */
                  dernierEtatCanton = 1;
                  EEPROM.update(1, dernierEtatCanton & 0xFF);                                       // écrit le premier byte de la valeur int
                  EEPROM.update(2, dernierEtatCanton >> 8);  
          
              } // Fin de if (etatDetecteurIR_B == HIGH)
          } else {
              if (etatDetecteurIR_B == HIGH){             
                 digitalWrite(pinLedRouge,LOW);
                 digitalWrite(pinLedJaune,HIGH);
                 delay(tempoLed);
                 digitalWrite(pinLedVerte,LOW);
                 
                 Serial.println("Sortie du convoi par B en cours!");
                 
                 display.clearDisplay();
                 display.setCursor(0,0);
                 display.println("Sortie du convoi");
                 display.println("par B en cours!");
                 display.display();
              } else {
                  etatCanton = 0;
                  etatRelaisOccupation = 0;
                  digitalWrite(pinLedRouge,LOW);
                  digitalWrite(pinLedJaune,LOW);
                  digitalWrite(pinLedVerte,HIGH);

                  Serial.println("Canton Libre!");
                  Serial.println("Sortie par B!");
                  
                  display.clearDisplay();
                  display.setCursor(0,0);
                  display.println("Canton Libre!");
                  display.println("Sortie par B!");
                  display.display();

                  /* Memorisation en EEprom */
                  dernierEtatCanton = 0;
                  EEPROM.update(1, dernierEtatCanton & 0xFF);                                       // écrit le premier byte de la valeur int
                  EEPROM.update(2, dernierEtatCanton >> 8);  
          
              } // Fin de if (etatDetecteurIR_B == HIGH)  
          } // Fin de if (etatCanton == 0)
  
      } // Fin de if (etatB != etatDetecteurIR_B)
      
   } // Fin de if ((millis() - last_tempoLecture) > tempoLecture)
   last_etatDetecteurIR_B = etatB;

} // Fin de procédure
 
void loop() {
    reglagetempoLecture();
    Detect_IR_A();
    Detect_IR_B();
    digitalWrite(pinRelaisOccupation, etatRelaisOccupation);
} // Fin de loop