Menu HTML / Javascript : Aperçu

Blog du réseau du Mesnil-sur-Jorg

jeudi 18 avril 2024
      Membre de Train d'enfer 95

Le réseau : Reprise de la gestion des aiguillages


Je reprends mon travail sur la gestion des aiguillages par Arduino.

Après avoir testé plusieurs solutions plus ou moins sophistiquées sur des Arduino Nano ou Mini Pro, je pars sur un travail totalement basique avec un "gros" Mega 2560 pour 16 servos-moteurs.

Gestion


Le système comprend 4 éléments. 

Cimg9798.jpg

Comme d'habitude, j'ai dessiné les PCB et il ont été fabriqués par JLCPCB.

La carte principale dessinée sous forme d'un shield qui vient s'enfficher sur les plots de l'arduino Mega 2560. 

Cimg9792.jpg

Cimg9793.jpg

Cimg9796.jpg

 

Cimg9797.jpg

On trouve 2 régulateurs 5 volts. Le premier pour alimenter l'arduino seul, le second pour alimenter les 16 servos, les 32 leds de direction et l'écran LCD. A droite 16 sorties pour connecter les servomoteurs, en dessous une entrée DCC pour de futurs développements et en bas 4 74HC595 pour gérer les 32 leds bicolores du TCO. On voit également un connecteur (4 fils) pour l'écran, un connecteur (10 fils) d'entrée/sortie pour le clavier (modes de fonctionnement et réglages) et 2 connecteurs (9 et 10 fils)  d'entrée  toujours pour le clavier afin de recevoir les instructions des boutons poussoirs.

Cimg9836.jpg

Un clavier "numérique" (par opposition aux claviers analogiques branchés sur un seul pin analogique)  qui sera plutôt réservé aux tests et règlages. Il comprend 16 boutons poussoirs pour commander chacun des servmoteurs. Ces boutons poussoirs sont doublés de 16 pastilles de contact qui permettent de vérifier le bon fonctionnement du système de stylet qui sera employé sur le TCO. Le clavier numérique sera donc également connecté au PCB du TCO.

Cimg9794.jpg

Cimg9795.jpg

Un écran LCD pour lire les informations et directives.

Cimg9803.jpg

Cimg9799.jpg

 

Cimg9802.jpg

Et enfin la platine du TCO un grand PCB au format A3 qui reprendra le tracé de mon réseau et incorporera les leds de direction des aiguillages ainsi que des points de touches permettant de commander les aiguillages plus "visuellement" par un simple "touché" d'un stylet sur un plot conducteur.

CE PCB est en cours d'étude et de dessin mais en voici l'ébauche. Il sera relié aux connecteurs des 4 74HC595 pour les leds de direction et au clavier pour la sélection des aiguillages à manoeuvrer.

PCB-TCO.png
Il y aura donc deux exemplaires de ce système pour gérer l'ensemble du réseau.

voici la dernière mouture du programme



/* Gestion de 16 aiguillages sur une carte arduino Mega 2560
 *  
 * PCB Arduino Gestion 16 aiguillages par Mega 2560_b.dip
 *     Arduino Clavier digital.dip  
 * Ecran LCD par I2C 
 * 
 * 4 modules supplémentaires 74HC595
 * 
 * 1 entrée DCC pour de futurs développements
 * 
 *##### les interruptions Mega2560 ##### (corrigées)
 * Pin  #2 = interruption #4
 * Pin  #3 = interruption #5
 * Pin #18 = interruption #3
 * Pin #19 = interruption #2
 * Pin #20 = interruption #1
 * Pin #21 = interruption #0
 * Détection du clavier par interruption sur D18
 *        LOW to trigger the interrupt whenever the pin is low,
 *        CHANGE to trigger the interrupt whenever the pin changes value
 *        RISING to trigger when the pin goes from low to high, 
 *        FALLING for when the pin goes from high to low.
 *        HIGH to trigger the interrupt whenever the pin is high.
 *#############################       
 * Début  le 09/05/2022
 * MAJ    le 01/06/2022 =>  ajout du réglage de la valeur du ralenti                                          => OK
 *                      =>  ajout d'une led de visualisation de la valeur de valRalenti                       => OK
 *                      =>  ajout de bounce sur les BP de réglage de valRalenti et de mise au point milieu    => OK
 * MAJ    le 03/06/2022 =>  modification de l'enregistrement en eeprom de valRalenti.                         => OK
 * MAJ    le 04/06/2022 =>  mise en place de la procédure de point milieu
 * TESTS  le 05/06/2022                                                                                       => OK
 * MAJ    le 06/06/2022 =>  forcer la mise en place à la dernière position quand on revient en mode commande  => à faire
 * MAJ    le 14/06/2022 =>  séparation des boucles pour l'initialisation des Servos                           => tests à terminer.
 * MAJ    le 14/07/2022 =>  remplacemment des réglages par potentiomètre par un réglage avec 2 boutons        => OK
 * MAJ    le 17/07/2022 =>  ajout de la bibliothèque Bounce2
 * MAJ    le 17/07/2022 =>  affichage du sens en cours de déplacement                                         => OK
 * MAJ    le 18/07/2022 =>  ajout réglage ralenti en mode Réglage                                             => OK
 * MAJ    le 20/07/2022 =>  procédure de validation à continuer! Difficultés avec la gestion du poussoir par Bounce2
 * MAJ    le 23/07/2022 =>  abandon de l'utilisation de bounce2 dans la procédure "validationReglages         => OK
 *                      =>  revoir l'utilisation du reglage du ralenti (ne fonctionne pas en cours de reglage des butées) => OK
 *                      =>  voir la possibilité d'une procédure de PointMilieu général pour positionnement mécanique => fait => OK ..... utilisation seulement en position réglage ... doit désactiver tout le reste
 *        le 09/08/2022 =>  modification du timing des beep Commande / Arrêt                                  => OK
 *                      => modification séquence d'allumage de la led du ralenti pendant la procédure PM      => OK    
 *        le 11/08/2022 => affichage des valeurs de positions initiales des aiguillages                       => OK
 *        le 27/08/2022  => ajout d'une fonction de mise en veille
 */
#include "Wire.h"
#include "EEPROM.h"                                                                        // bibliothèque pour gérer la mise en mémoire
#include "Bounce2.h"

/* LES CONNECTEURS */
const int pinBPValidationReglage = 4;                                                     // BP de validation des réglages sur D4
const int pinSelecteurButee = 5;                                                          // switch de sélection de la butée (Direct/devie) en cours de réglage sur D5    
const int pinSelecteurChoixMode = 6;                                                      // switch de choix mode sur D6
const int pinLedvalRalenti = 7;                                                           // led témoin de la valeur du ralenti
const int pinBPvalRalenti = 8;                                                            // BP de réglage de la vitesse de déplacement des aiguillages
const int pinBPPointMilieu = 9;                                                           // positionne tous les aiguillages à leur point milieu.
// pins D10, D11, D12 réservés pour la gestion des 4 74HC595
const int pinLedTemoin = 13;                                                              // led de vérification du bon fonctionnement
const int pinBuzzer = 14;                                                                 // buzzer sur D14     
const int pinBPPlus = 15;
const int pinBPMoins = 16; 
const int pinInterruptionClavier = 18;                                                    // pour la détection des touches du clavier INT3
const int pinDCC1 = 19;                                                                   // pour les détections DCC / interruption INT2
//pin 20 et 21 réservés pour interruptions INT1 et INT0                                                                
//pins 22 à 37 réservés                                                                   // les servos sont connectés du pin 22 au pin 37 
//pins 38 à 53 réservés                                                                   // les BP sont connectés du pin 38 au pin 53  
/* =============== */

/* POUR LA MISE EN VEILLE */
// réveil par interruption sur D18
#include "LowPower.h"
uint32_t departExecution = 0ul;
uint32_t dureeInactivite = 60000ul;                                                       // mise en veille au bout de 60 secondes d'inctivité 
//* ===================== */

/* LES VARIABLES POUR LES SERVOS */
const int nbAiguillages = 16;
const int pinDepartServo = 22;
int ServoEnCours = 0;
const int angleMini = 1000; // 544 pris pour 600
const int angleMaxi = 2000; // 2400
const int angleMilieu = (angleMaxi + angleMini) / 2;
int sens[nbAiguillages];
int angleIntermediaire[nbAiguillages];
int angleDirect[nbAiguillages];
int angleDevie[nbAiguillages];
int DernierePosition[nbAiguillages];
bool selectionServo[nbAiguillages];
byte valRalenti = 1;                                                                       // peux prendre les valeurs de 1 à 5

/* pour gérer les servos */
#include "Servo.h"
Servo servoAiguillage[nbAiguillages];
/* ===================== */

/* pour gérer un écran LCD 2004 
* l'adresse de l'écran peut être déterminée à l'aide 
* du script "Scanner I2C"
*/
#include "LiquidCrystal_I2C.h"                                                             // bibliothèque pour gérer écran LCD 2004
LiquidCrystal_I2C lcd(0x27, 20, 4);
//LiquidCrystal_I2C lcd(0x3F, 20, 4);
/* ============================ */ 

/* POUR LE CLAVIER NUMERIQUE */
Bounce clavierBP[nbAiguillages] = Bounce();
volatile bool flagClavier = true;
const int pinDepartBP = 38;
int numBoutonPoussoir = 0;
int CompteurLoop = 0;  int I = 0;
const int dureeAntiRebond = 50;
bool etatLedRalenti = LOW;
unsigned long precedentMillis = 0;
/* ======================== */

/* LES VARIABLES POUR LES REGLAGES */
bool ButeeEnCours;
int pasReglage = 10;                                                                        // incrémentation des angles pour les réglages
bool flagPointMilieu = false;

Bounce BPvalRalenti = Bounce();
Bounce BP_Plus = Bounce();
Bounce BP_Moins = Bounce();
Bounce BPValidationReglage = Bounce();
Bounce BPPointMilieu = Bounce();
/* =============================== */

/* LES VARIABLES POUR LE BP DE VALIDATION */
unsigned long debutPressionBP = 0;
unsigned long finPressionBP = 0;
const int limitePressionCourteBP = 2000;                                                    // pression longue si + de 2 secondes
/* ================================== *

/* LES DRAPEAUX D'AFFICHAGE */
bool Z = 0; // flag affichage mode COMMANDE
bool Y = 0; // flag affichage mode REGLAGE
bool X = 0; // flag affichage butée droite (angle max)
bool W = 0; // flag affichage butée gauche (angle min))
bool V = 0; // flag desactivation interruptions D2 et D3 en mode REGLAGE
bool U = 0; // flag affichage suite mode REGLAGE
bool T = 0; // flag reglage valeur butées
bool R1; bool R2; // flag affichage direction en cours
/* ======================== */

/* =========== GESTION DES QUATRE 74HC595 EN SERIE ================ */
const int data_Pin = 10;                                                                    //pin 14 (DS)    du 74HC595 (Entrée)
const int verrou_Pin = 11;                                                                  //pin 12 (ST_CP) du 74HC595 (Horloge de registre de sortie)
const int horloge_Pin = 12;                                                                 //pin 11 (SH_CP) du 74HC595 (Horloge de registre de décalage)
const int pinDepartLed = 0;
#define Nombre_74hc595 4                                                                    // nombre de 74HC595 en série pour 16 leds bicolores                                          
#define numOfRegisterPins Nombre_74hc595 * 8
boolean Registres[numOfRegisterPins];
/* ================================================================= */

void clearRegisters(){  
  //Place tous les pins du 74HC595 à l'état "OFF"
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    Registres[i] = LOW;
  } // Fin de for
} // Fin de procédure clearRegisters()

void writeRegisters(){
  //Enregistrer et afficher les valeurs dans le registre
  //A n'executer que APRES que toutes les valeurs aient été programmées
  digitalWrite(verrou_Pin, LOW); 
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(horloge_Pin, LOW);
    int val = Registres[i];
    digitalWrite(data_Pin, val);
    digitalWrite(horloge_Pin, HIGH);
  } // Fin de for 
  digitalWrite(verrou_Pin, HIGH);
} // Fin de procédure writeRegisters()

void setRegisterPin(int index, int value){ 
  //Place un pin du 74HC595 à l'état HAUT ou BAS
  Registres[index] = value;
} // Fin de procédure setRegisterPin()
/* ========================================================================== */ 

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  
  /* Affichage message accueil pendant l'initialisation */
  lcd.clear(); 
  lcd.setCursor(0,0); lcd.print(" Bienvenue dans la ");
  lcd.setCursor(0,1); lcd.print("    gestion des    ");
  lcd.setCursor(0,2); lcd.print("aiguillages 1 a 16.");
  lcd.setCursor(0,3); lcd.print(" Initialisation ...");
    /* =================================================== */

  /* Initialisation des BP avec la bibliothèque Bounce2 */
  BPvalRalenti.attach(pinBPvalRalenti, INPUT);
  BPvalRalenti.interval(dureeAntiRebond);
  BP_Plus.attach(pinBPPlus, INPUT);
  BP_Plus.interval(dureeAntiRebond);
  BP_Moins.attach(pinBPMoins, INPUT);
  BP_Moins.interval(dureeAntiRebond);
  BPValidationReglage.attach(pinBPValidationReglage, INPUT);
  BPValidationReglage.interval(dureeAntiRebond);
  BPPointMilieu.attach(pinBPPointMilieu, INPUT);
  BPPointMilieu.interval(dureeAntiRebond);
  /* ================================================= */
      
  /* Initialisation des pins E/S */
  pinMode(pinSelecteurButee, INPUT);  
  pinMode(pinSelecteurChoixMode, INPUT);
  pinMode(pinLedvalRalenti, OUTPUT); digitalWrite(pinLedvalRalenti, LOW);
  pinMode(pinLedTemoin, OUTPUT); digitalWrite(pinLedTemoin, HIGH);
  pinMode(pinBuzzer, OUTPUT);
  pinMode(pinDCC1, INPUT);
  /* ========================== */
  
  /* Initialisation des quatre 74HC595 pour la gestion des leds du TCO */
  pinMode(data_Pin, OUTPUT);
  pinMode(verrou_Pin, OUTPUT);
  pinMode(horloge_Pin, OUTPUT);

  //Reset tous les pins du 74HC595
  clearRegisters();

  /* Initialisation des pins servo et clavier
  *  Initialisation des BP du clavier digital avec la bibliothèque Bounce2
  *  Lecture en EEprom des données de chaque servo 
  *  Positionnements des servos 
  *  Allumage des leds correspondantes
  */
  delay(2500);
  lcd.clear(); 
  for (int J = 0; J < nbAiguillages; J++){
    pinMode(pinDepartServo + J, OUTPUT);                                                                // pour les servos à partir de 22
    pinMode(pinDepartBP + J, INPUT);                                                                    // pour le clavier à partir de 38
    clavierBP[J].attach(pinDepartBP + J, INPUT);                                                        // pour Bounce2 du clavier
    clavierBP[J].interval(dureeAntiRebond);  
    lectureEEProm(J);   
    servoAiguillage[J].writeMicroseconds(DernierePosition[J]); 
    if (!servoAiguillage[J].attached()) servoAiguillage[J].attach(pinDepartServo + J);
    delay(50);
    servoAiguillage[J].writeMicroseconds(DernierePosition[J]);
    delay(400);
    selectionServo[J] = false;
    if (DernierePosition[J] == angleDirect[J]){
        setRegisterPin((J * 2), HIGH); 
        setRegisterPin((J * 2) + 1, LOW);
    } else {
        setRegisterPin((J * 2) + 1, HIGH); 
        setRegisterPin((J * 2), LOW);
    } // Fin de if (DernierePosition[J] == angleDirect[J])   
  } // Fin de for (int J = 0; J < nbAiguillages; J++)
  
  writeRegisters();    
      
  /* Message de fin d'initialisation */
  lcd.setCursor(0,0); lcd.print("   Gestion des      ");
  lcd.setCursor(0,1); lcd.print(" aiguillages 1 a 16.");
  lcd.setCursor(0,2); lcd.print(" Ralenti regle a "); lcd.print(valRalenti); lcd.print("   ");
  lcd.setCursor(0,3); lcd.print("     P R E T ! !    ");
  /* =============================== */

  /* visualisation de la valeur de valRalenti */ 
  for (byte J = 0; J < valRalenti; J += 1){
      digitalWrite(pinLedvalRalenti, HIGH);
      delay(200);
      digitalWrite(pinLedvalRalenti, LOW);
      delay(300);
  } // Fin de for (byte J = 0; J < valRalenti; J += 1)
   /* ======================================== */
   
  /* on détache les servos */
  for (int J = 0; J < nbAiguillages; J++){
       if (servoAiguillage[J].attached()) servoAiguillage[J].detach();         
  } 
  delay(2000);
  /* ===================== */

  /* on démarre la tempo de mise en veille */
  departExecution = millis();
  
 } // Fin de setup
 
void loop() {
if ((millis() - departExecution) >= dureeInactivite){
    digitalWrite(pinLedTemoin, LOW);
    lcd.setBacklight(LOW); //lcd.noDisplay(); 
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    lcd.setBacklight(HIGH); //lcd.display();
    digitalWrite(pinLedTemoin, HIGH);
   }
  
  BPvalRalenti.update();
  clavierBP[CompteurLoop].update();    
  CompteurLoop++; if (CompteurLoop == nbAiguillages) CompteurLoop = 0;  
  if (flagClavier) Clavier();                                                                           // détection par interruption sur D2
  
  if (digitalRead(pinSelecteurChoixMode)== LOW) {                                               
       //**********************************************
       // Sélecteur choix MODE à gauche => mode REGLAGE
       //**********************************************   
       BPPointMilieu.update();
       PointMilieu();
       if (Y == 0){
          Y = 1;
          departExecution = millis();
          dureeInactivite = 3600000ul;
          initMessagesModeReglage();
       } // fin de if (Y == 0)     
       // si un bouton poussoir valide a été appuyé          
       if ((numBoutonPoussoir > 0) && (numBoutonPoussoir < nbAiguillages + 1)){
          //Serial.print(BP_Plus.read());Serial.print(F(" - "));Serial.println(BP_Moins.read());
            if (V == 0) {
                // on exécute ceci une seule fois
                V = 1;
                // on désactive le clavier...la réactivation se fera par la validation du réglage
                detachInterrupt(digitalPinToInterrupt(2));   
                // on positionne le servo en cours à son point milieu pour un éventuel réglage mécanique
                angleIntermediaire[ServoEnCours] = (angleMaxi + angleMini) / 2;
                servoAiguillage[ServoEnCours].writeMicroseconds(angleIntermediaire[ServoEnCours]);  
                //Serial.print(F("Servo : "));Serial.print(ServoEnCours);Serial.print(F(" => "));Serial.println(angleIntermediaire[ServoEnCours]);                              
            } // Fin de if (V == 0)
            do {
                choixButee(); 
                BP_Plus.update();
                BP_Moins.update(); 
                BPValidationReglage.update(); 
                if (BP_Plus.changed()){ 
                    if (BP_Plus.read() == HIGH){
                        angleIntermediaire[ServoEnCours] += pasReglage;                       
                        servoAiguillage[ServoEnCours].writeMicroseconds(angleIntermediaire[ServoEnCours]);
                        //Serial.println(angleIntermediaire[ServoEnCours]);
                        lcd.setCursor(4,3); lcd.print("Valeur : ");
                        lcd.setCursor(12,3);lcd.print(angleIntermediaire[ServoEnCours]);
                    }
                }
                if (BP_Moins.changed()){ 
                    if (BP_Moins.read() == HIGH){
                        angleIntermediaire[ServoEnCours] -= pasReglage;                       
                        servoAiguillage[ServoEnCours].writeMicroseconds(angleIntermediaire[ServoEnCours]);
                        //Serial.println(angleIntermediaire[ServoEnCours]);
                        lcd.setCursor(4,3); lcd.print("Valeur : ");
                        lcd.setCursor(12,3);lcd.print(angleIntermediaire[ServoEnCours]);
                    }
                }            
            } while(BPValidationReglage.read() == 1); // Fin de while
            validationReglage(ServoEnCours, ButeeEnCours, angleIntermediaire[ServoEnCours]);
       } // Fin de if ((numPoussoir > 0) && (numPoussoir < nbAiguillages + 1))
              
  } else { // else de if (digitalRead(pinSelecteurChoixMode) == LOW)
       //***********************************************
       // Sélecteur choix MODE à droite => mode COMMANDE
       //*********************************************** 
       // on active le réglage du ralentissement de déplacement des aiguillages
       reglageRalenti();
       if (Z == 0){ 
          Z = 1;
          departExecution = millis();
          dureeInactivite = 600000ul;
          initMessagesModeCommande();
       } // fin de if (Z == 0)   
       if (selectionServo[CompteurLoop] == true) {
          //Serial.print(F("Aiguillage : ")); Serial.print(CompteurLoop + 1); Serial.println(F(" actif "));
          if (DernierePosition[CompteurLoop] == angleDirect[CompteurLoop]){ 
            if(R1 == 0){
              R1 = 1;
              lcd.clear();          
              lcd.setCursor(0,0);lcd.print("Aiguillage ");
              lcd.setCursor(13,0);lcd.print(CompteurLoop + 1); 
              lcd.setCursor(0,1);lcd.print("   vers devie ...   "); 
            }                  
            DirectToDevie(CompteurLoop);
          } else {
            if(R2 == 0){
              R2 = 1;            
              lcd.clear();
              lcd.setCursor(0,0);lcd.print("Aiguillage ");
              lcd.setCursor(13,0);lcd.print(CompteurLoop + 1); 
              lcd.setCursor(0,1);lcd.print("   vers direct ...  ");  
            }
            DevieToDirect(CompteurLoop);
          } // Fin de if (DernierePosition[CompteurLoop] == angleDirect[CompteurLoop])
       } // Fin de if (selection[CompteurLoop] == true)
  } // fin de if (digitalRead(pinBPMode) == LOW)
} // Fin de loop

void detectInterruptClavier(){
// ISR appelé par interruption sur D18 
  departExecution = millis();                                               
  flagClavier = true;                                                        
} // Fin de procédure detectInterruptClavier()

void Clavier(){
  // Déclanchement par interruption sur D18
  //Serial.println(F("Clavier OK"));
  // on boucle sur les BP pour lire leur état
  for (int J = 0; J < nbAiguillages; J++){
    if (clavierBP[J].changed()) {
        if (clavierBP[J].read() == HIGH) {
            numBoutonPoussoir = J + 1;
            ServoEnCours = J;
            selectionServo[J] = true;
            // On attache le servomoteur correspondant s'il n'est pas déjà attaché
            if (!servoAiguillage[J].attached()) servoAiguillage[J].attach(pinDepartServo + J);
                    //Serial.print(F("Aiguillage "));Serial.print(ServoEnCours + 1); Serial.println(F(" attache!")); 
            // On sort de la boucle au premier BP sélectionné
            flagClavier = false;
            break;       
        } // Fin de if (clavierPB[J].read() == HIGH)
    } // Fin de if (clavierPB[J].changed())
  } // For for (int J = 0; J < nbAiguillages; J++)
} // Fin de procédure Clavier()

int lectureEEProm(int I){
    /*
     * byte 200     => valRalenti
     * byte 10-11 => angleDirect 
     * byte 12-13 => angleDevie
     * byte 14-15 => DernierPosition
     */
    if (I == 0) {
        valRalenti = EEPROM.read(200);                            
        if ((valRalenti < 1) || (valRalenti > 5)) {
            valRalenti = 1;
            EEPROM.update(200, valRalenti);
        } // Fin de if ((valRalenti < 1) || (valRalenti > 5))
     } // Fin de if (I == 0)
     
    angleDirect[I] = EEPROM.read(I * 10) | ((int)EEPROM.read((I * 10) + 1)) << 8;                       // lecture des 2 ints pour int angleDirect[]
    if (angleDirect[I] > angleMaxi || angleDirect[I] < angleMini){                                      // si incohérence de valeur ou initialisation (=255) 
        angleDirect[I] = angleMini;                                                                     // on enregistre la limite pour angleMin 
        EEPROM.update((I * 10), angleDirect[I] & 0xFF);                                                 // écrit le premier int de la valeur int
        EEPROM.update((I * 10) + 1, angleDirect[I] >> 8);                                               // écrit le second int de la valeur int
    } // fin de if (angleDirect[I] > angleMaxi || angleDirect[I] < angleMini)
          
    angleDevie[I] = EEPROM.read((I * 10) + 2) | ((int)EEPROM.read((I * 10) + 3)) << 8;                  // lecture des 2 ints pour int angleMax[]
    if (angleDevie[I] > angleMaxi || angleDevie[I] < angleMini){                                        // si incohérence de valeur ou initialisation (=255)
        angleDevie[I] = angleMaxi;                                                                      // on enregistre la limite pour angleMax
        EEPROM.update((I * 10) + 2, angleDevie[I] & 0xFF);                                              // écrit le premier int de la valeur int
        EEPROM.update((I * 10) + 3, angleDevie[I] >> 8);                                                // écrit le second int de la valeur int
    } // Fin de if (angleDevie[I] > angleMaxi || angleDevie[I] < angleMini)
          
    DernierePosition[I] = EEPROM.read((I * 10) + 4) | ((int)EEPROM.read((I * 10) + 5)) << 8; 
    if (DernierePosition[I] != angleDevie[I] && DernierePosition[I] != angleDirect[I]){
        DernierePosition[I] = (angleDirect[I] + angleDevie[I]) / 2;                                     // si incohérence de valeur on se met au point milieu
        EEPROM.update((I * 10) + 4, DernierePosition[I] & 0xFF);                                        // écrit le premier int de la valeur int
        EEPROM.update((I * 10) + 5, DernierePosition[I] >> 8);                                          // écrit le second int de la valeur int
    } // Fin de if (DernierePosition[I] < limitAngleMin || servoAiguillage[I].DernierePositionServo > limitAngleMax)  
      
    //Serial.print(F("Aiguillage "));Serial.print(I+1); 
    //Serial.print(F(" : "));Serial.print(angleDirect[I]);
    //Serial.print(F(" - "));Serial.print(angleDevie[I]);
    //Serial.print(F(" position ")); Serial.println(DernierePosition[I]);     
        
    lcd.setCursor(2,0); lcd.print("Aiguillage : ");lcd.setCursor(16,0); lcd.print(I + 1);
    lcd.setCursor(0,1); lcd.print("Angle direct : ");lcd.setCursor(16,1);lcd.print(angleDirect[I]);
    lcd.setCursor(0,2); lcd.print("Angle devie  : ");lcd.setCursor(16,2);lcd.print(angleDevie[I]);
    
    angleIntermediaire[I] = DernierePosition[I];
    sens[I] = 1;    
} // Fin de procédure lectureEEProm()

void initMessagesModeReglage(){              
        digitalWrite(pinLedvalRalenti, LOW);
        tone(pinBuzzer,2000,300);                           
        // activation du clavier => detection interruptions D2
        attachInterrupt(digitalPinToInterrupt(pinInterruptionClavier), detectInterruptClavier, RISING);
                  
        //Serial.println(F("MODE REGLAGE : Pret!"));
        //Serial.println(F("Selectionnez l'aiguillage a regler"));
        //Serial.println(F("en appuyant sur le poussoir correspondant."));
            
        lcd.clear(); lcd.setCursor(0,0);
        lcd.print("MODE REGLAGE:Pret!");
        lcd.setCursor(0,1);
        lcd.print("Selection aiguillage");
        lcd.setCursor(0,2);
        lcd.print("en appuyant le pous-");
        lcd.setCursor(0,3);
        lcd.print("-soir correspondant.");

        /* visualisation de la valeur de valRalenti */ 
        for (byte J = 0; J < valRalenti; J += 1){
            digitalWrite(pinLedvalRalenti, HIGH);
            delay(200);
            digitalWrite(pinLedvalRalenti, LOW);
            delay(300);
        } // Fin de for (byte J = 0; J < valRalenti; J += 1)
                    
        Z = 0; // RAZ flag affichage choix COMMANDE
        numBoutonPoussoir = 0; ServoEnCours = 0;  
} // Fin de procedure initReglage()

void choixButee(){
  // ButeeEnCours = LOW => bouton à gauche => butée angleDirect
  // ButeeEnCours = HIGH => bouton à droite => butée angleDevie         
          
  ButeeEnCours = digitalRead(pinSelecteurButee);
  if (ButeeEnCours == HIGH){
      if (W == 0){
          W = 1;
          U = 0;
          //Serial.print(F("Angle direct aiguillage ")); Serial.print(numBoutonPoussoir);Serial.println(F(" en cours de reglage!"));
                
          lcd.clear();
          lcd.setCursor(4,0); lcd.print("Angle direct");
          lcd.setCursor(4,1); lcd.print("aiguillage "); lcd.print(numBoutonPoussoir); 
          lcd.setCursor(0,2); lcd.print("en cours de reglage!");
      } // Fin de if (W == 0)
  } else {
      if (U == 0){
          U = 1;
          W = 0;
          //Serial.print(F("Angle devie aiguillage ")); Serial.print(numBoutonPoussoir);Serial.println(F(" en cours de reglage!"));
                
          lcd.clear();
          lcd.setCursor(4,0); lcd.print("Angle devie"); 
          lcd.setCursor(4,1); lcd.print("aiguillage "); lcd.print(numBoutonPoussoir); 
          lcd.setCursor(0,2); lcd.print("en cours de reglage!");
      } // Fin de if (U == 0)
  } // Fin de if (ButeeEnCours == LOW)
}// Fin de procédure choixButee()

void validationReglage(int numServo, bool valButee, int valReglage) {
  if (digitalRead(pinBPValidationReglage) == 1 && debutPressionBP == 0) {
    debutPressionBP = millis();  
  }

  if (digitalRead(pinBPValidationReglage) == 0 && debutPressionBP != 0) {
    finPressionBP = millis();  
    if((finPressionBP - debutPressionBP) > 0) {
      if((finPressionBP - debutPressionBP) < limitePressionCourteBP) {
          //pression courte => validation 
          if (servoAiguillage[ServoEnCours].attached()) servoAiguillage[ServoEnCours].detach();
          if (valButee == HIGH) {
              //Serial.print(F(" Angle direct pour aguillage "));
              //Serial.println(numServo + 1);
              //Serial.print(F(" enregistre a  "));
              //Serial.println(valReglage);
           
              lcd.clear();
              lcd.setCursor(0,0); lcd.print("  Angle direct pour ");
              lcd.setCursor(0,1); lcd.print("    aiguillage ");lcd.print(numServo + 1);
              lcd.setCursor(0,2); lcd.print("  enregistre a ");lcd.print(valReglage); 
              
              angleDirect[numServo] = valReglage;
              EEPROM.update((numServo * 10), angleDirect[numServo] & 0xFF); 
              EEPROM.update((numServo * 10) + 1, angleDirect[numServo] >> 8);                       
          } else {
              //Serial.print(F(" Angle devie pour aguillage "));
              //Serial.println(numServo + 1);
              //Serial.print(F(" enregistre a  "));
              //Serial.println(valReglage);
          
              lcd.clear();
              lcd.setCursor(0,0);lcd.print("  Angle devie pour");
              lcd.setCursor(0,1);lcd.print("    aiguillage ");lcd.print(numServo + 1);
              lcd.setCursor(0,2);lcd.print("  enregistre a ");lcd.print(valReglage);
       
              angleDevie[numServo] = valReglage;
              EEPROM.update((numServo * 10) + 2, angleDevie[numServo] & 0xFF);   
              EEPROM.update((numServo * 10) + 3, angleDevie[numServo] >> 8);       
          } // Fin de if (valButee == 0)
          
          angleIntermediaire[numServo] = valReglage;
          DernierePosition[numServo] = valReglage;
          EEPROM.update((numServo * 10) + 4, DernierePosition[numServo] & 0xFF);   
          EEPROM.update((numServo * 10) + 5, DernierePosition[numServo] >> 8); 
          delay(400);      
          tone(pinBuzzer,2500,100); delay(100);tone(pinBuzzer,2000,1000); 
          // nouveau reglage
          lcd.setCursor(0,3);lcd.print("  Nouveau reglage  ");
          attachInterrupt(digitalPinToInterrupt(pinInterruptionClavier), detectInterruptClavier, RISING);
          selectionServo[numServo] = false; numBoutonPoussoir = 0; ServoEnCours = 0; debutPressionBP = 0; finPressionBP = 0;
          Z = 0; Y = 0; X = 0; W = 0; V = 0; U = 0; T = 0;
      } else {
          //pression longue => annulation et on recommence
          tone(pinBuzzer,2000,1000); delay(100);tone(pinBuzzer,3500,50); tone(pinBuzzer,3500,50);
          //Serial.println(F("Operation annulee"));            
          lcd.clear();
          lcd.setCursor(0,1);lcd.print(" O P E R A T I O N ");
          lcd.setCursor(0,2);lcd.print(" A N N U L E E ! ! ");
            
          for (int buz = 0; buz < 4; buz++){
              tone(pinBuzzer,3000,50); delay(50);
          } // Fin de for
          servoAiguillage[numServo].writeMicroseconds(DernierePosition[numServo]);
          delay(2500);   
          if (servoAiguillage[numServo].attached()) servoAiguillage[numServo].detach();    // on "débranche" le servo  
          delay(50);       
          attachInterrupt(digitalPinToInterrupt(pinInterruptionClavier), detectInterruptClavier, RISING);            
          selectionServo[numServo] = false; numBoutonPoussoir = 0; ServoEnCours = 0; debutPressionBP = 0; finPressionBP = 0;
          Z = 0; Y = 0; X = 0; W = 0; V = 0; U = 0; T = 0;
      } // Fin de if((finPressionBP - debutPressionBP) < limitePressionBP      
    } // Fin de if((finPressionBP - debutPressionBP) > 0)    
  } // Fin de if (digitalRead(pinBPValidationReglage) == 1 && debutPressionBP != 0)
            
} // Fin de procédure validationReglage(int numServo, bool valButee, int valReglage)
  
void initMessagesModeCommande(){                                          
        // activation du clavier => detection interruptions D2
        attachInterrupt(digitalPinToInterrupt(pinInterruptionClavier), detectInterruptClavier, RISING);
        tone(pinBuzzer,2500,100);  
        
        //Serial.println(F("MODE COMMANDE : Pret!"));
        //Serial.println(F("Selectionnez l'aiguillage a commander"));
        //Serial.println(F("en appuyant sur le poussoir correspondant."));
         
        lcd.clear(); lcd.setCursor(0,0);
        lcd.print("MODE COMMANDE:Pret!");
        lcd.setCursor(0,1);
        lcd.print("Selection aiguillage");
        lcd.setCursor(0,2);
        lcd.print("en appuyant le pous-");
        lcd.setCursor(0,3);
        lcd.print("-soir correspondant.");
                
        Y = 0; // RAZ flag affichage choix REGLAGE          
        W = 0;
        U = 0;
        T = 0;
        CompteurLoop = 0;
        numBoutonPoussoir = 0; 
        ServoEnCours = 0;  
} // Fin de procédure initCommande()

void DirectToDevie(int numServoEnCours) 
{     
  if (angleDirect[numServoEnCours] > angleDevie[numServoEnCours])
  {
      sens[numServoEnCours] = -1;     
  } else {
      sens[numServoEnCours] = 1;
  } 
  angleIntermediaire[numServoEnCours] += sens[numServoEnCours];
  servoAiguillage[numServoEnCours].writeMicroseconds(angleIntermediaire[numServoEnCours]);
  delay(valRalenti * 2); 
  //Serial.println(servoAiguillage[numServoEnCours].read()); 
  
  //if(abs(angleDevie[numServoEnCours] - angleIntermediaire[numServoEnCours]) < 0){
    if (angleIntermediaire[numServoEnCours] == angleDevie[numServoEnCours]){  
    selectionServo[numServoEnCours] = false;                                                       // on annule la sélection du servo
    if (servoAiguillage[numServoEnCours].attached()) servoAiguillage[numServoEnCours].detach();    // on "débranche" le servo
    DernierePosition[numServoEnCours] = angleDevie[numServoEnCours];
    
    /* allumage des leds correspondantes */
    setRegisterPin((numServoEnCours * 2), LOW); 
    setRegisterPin((numServoEnCours * 2) + 1, HIGH);
    writeRegisters();
    /* ==================================*/    
    
    /* messages */
    //Serial.print(F("Aiguillage "));Serial.print(numServoEnCours + 1);Serial.println(F(" devie. Detache! "));
   
    //lcd.clear();
    //lcd.setCursor(0,0);lcd.print("Aiguillage ");
    //lcd.setCursor(13,0);lcd.print(numServoEnCours + 1);
    R1 = 0;
    lcd.setCursor(0,1);lcd.print(" D E V I E ! ! ");
    lcd.setCursor(0,2);lcd.print("Autre choix avec le");
    lcd.setCursor(1,3);lcd.print("BP correspondant.");
    /* ======== */

    /* mise em mémoire de la dernière position */
    EEPROM.update((numServoEnCours * 10) + 4, DernierePosition[numServoEnCours] & 0xFF);  
    EEPROM.update((numServoEnCours * 10) + 5, DernierePosition[numServoEnCours] >> 8);  
    /* ======================================= */
  } // Fin de if (angleIntermediaire[numServoEnCours] == angleDevie[numServoEnCours])
} // Fin de procédure DirectToDevie

void DevieToDirect(int numServoEnCours) {
  if (angleDevie[numServoEnCours] > angleDirect[numServoEnCours])
  {
      sens[numServoEnCours] = -1;     
  } else {
      sens[numServoEnCours] = 1;
  }
  
  angleIntermediaire[numServoEnCours] += sens[numServoEnCours];
  servoAiguillage[numServoEnCours].writeMicroseconds(angleIntermediaire[numServoEnCours]);
  delay(valRalenti * 2); 
  //Serial.println(servoAiguillage[numServoEnCours].read());
  
  if (angleIntermediaire[numServoEnCours] == angleDirect[numServoEnCours]){
    selectionServo[numServoEnCours] = false;                                                       // on annule la sélection du servo
    if (servoAiguillage[numServoEnCours].attached()) servoAiguillage[numServoEnCours].detach();    // on "débranche" le servo
    DernierePosition[numServoEnCours] = angleDirect[numServoEnCours];
   
    /* allumage des leds correspondantes */
    setRegisterPin((numServoEnCours * 2), HIGH); 
    setRegisterPin((numServoEnCours * 2) + 1, LOW);
    writeRegisters();
    /* ================================= */
    
    /* messages */
    //Serial.print(F("Aiguillage "));Serial.print(numServoEnCours + 1);Serial.println(F(" direct. Detache! "));
   
    //lcd.clear();
    //lcd.setCursor(0,0);lcd.print("Aiguillage ");
    //lcd.setCursor(13,0);lcd.print(numServoEnCours + 1);
    R2 = 0;
    lcd.setCursor(0,1);lcd.print(" D I R E C T ! ! ");
    lcd.setCursor(0,2);lcd.print("Autre choix avec le");
    lcd.setCursor(1,3);lcd.print("BP correspondant.");
    /* ======== */
         
    /* mise em mémoire de la dernière position */
    EEPROM.update((numServoEnCours * 10) + 4, DernierePosition[numServoEnCours] & 0xFF);  
    EEPROM.update((numServoEnCours * 10) + 5, DernierePosition[numServoEnCours] >> 8);  
    /* ======================================= */
 
  } // Fin de if (angleIntermediaire[numServoEnCours] == angleDirect[numServoEnCours])
} // Fin de procédure DevieToDirect

void reglageRalenti(){
     if (BPvalRalenti.changed()) {
        //if ((BPvalRalenti.read() == HIGH) && (BPPointMilieu.read() == LOW)) {
        if (BPvalRalenti.read() == HIGH) {
              valRalenti += 1; if(valRalenti > 5) valRalenti = 1;
              //Serial.print("RALENTI ");
              //Serial.print("regle a :  ");
              //Serial.println(valRalenti);                                                                            
          } else {
              EEPROM.update(200, valRalenti); 
              valRalenti = EEPROM.read(200);
              //Serial.print("RALENTI ");
              //Serial.print("enregistre a :  "); 
              //Serial.println(valRalenti);
              /* visualisation de la valeur de valRalenti */ 
              for (byte J = 0; J < valRalenti; J += 1){
                digitalWrite(pinLedvalRalenti, HIGH);
                delay(200);
                digitalWrite(pinLedvalRalenti, LOW);
                delay(300);
              } // Fin de for (byte J = 0; J < valRalenti; J += 1)
          } // Fin de if (BP_ralenti.read() == HIGH)
     } // Fin de if (BP_ralenti.changed())
 } // Fin de procédure reglageRalenti

void PointMilieu(){
     if (BPPointMilieu.changed() && BPPointMilieu.read() == HIGH) {   
        if (flagPointMilieu == false){
            flagPointMilieu = true;
            digitalWrite(pinLedvalRalenti, HIGH);
            detachInterrupt(digitalPinToInterrupt(2)); 
            for (int J = 0; J < nbAiguillages; J++){
                servoAiguillage[J].writeMicroseconds((angleMaxi + angleMini) / 2); 
                if (!servoAiguillage[J].attached()) servoAiguillage[J].attach(pinDepartServo + J);
                delay(50);
                servoAiguillage[J].writeMicroseconds((angleMaxi + angleMini) / 2);
                delay(500);
            } // Fin de for (int J = 0; J < nbAiguillages; J++)
            
             for (int J = 0; J < nbAiguillages; J++){
                if (servoAiguillage[J].attached()) servoAiguillage[J].detach();
                delay(50);
            } // Fin de for (int J = 0; J < nbAiguillages; J++)
            tone(pinBuzzer,5000,500);
            //Serial.println(F("MODE POINT MILIEU ACTIF"));
            //Serial.println(F("pour un centrage mecanique des aiguillages."));
            //Serial.println(F("Desactivation de toutes les commandes!"));

            lcd.clear();
            lcd.setCursor(2,0); lcd.print("Mode Point Milieu");
            lcd.setCursor(5,1); lcd.print("A C T I F !");
            lcd.setCursor(0,2); lcd.print("pour un centrage des");
            lcd.setCursor(5,3); lcd.print("aiguillages");
            do{
                BPPointMilieu.update();
                unsigned long actuelMillis = millis();
                if (actuelMillis - precedentMillis >= 250) {
                  precedentMillis = actuelMillis;
                  etatLedRalenti =! etatLedRalenti;
                  digitalWrite(pinLedvalRalenti, etatLedRalenti);
                }
                if(BPPointMilieu.changed() && BPPointMilieu.read() == HIGH && flagPointMilieu == true){
                  flagPointMilieu = false;
                  digitalWrite(pinLedvalRalenti, HIGH);
                  for (int J = 0; J < nbAiguillages; J++){
                      servoAiguillage[J].writeMicroseconds(DernierePosition[J]); 
                      if (!servoAiguillage[J].attached()) servoAiguillage[J].attach(pinDepartServo + J);
                      delay(50);
                      servoAiguillage[J].writeMicroseconds(DernierePosition[J]);
                      delay(400);
                  } // Fin de for (int J = 0; J < nbAiguillages; J++)
                  for (int J = 0; J < nbAiguillages; J++){
                      if (servoAiguillage[J].attached()) servoAiguillage[J].detach();
                      delay(50);
                  } // Fin de for (int J = 0; J < nbAiguillages; J++)
                  tone(pinBuzzer,5000,500);
                  //Serial.println(F("MODE POINT MILIEU INACTIF"));
                  digitalWrite(pinLedvalRalenti, LOW);
                  Y = 0; Z = 0;
                  break;
                }
            }
            while(1);
        } //Fin de if (flagPointMilieu == true)
     } // Fin de if (BPPointMilieu.changed() && BPPointMilieu.read() == HIGH)
 } // Fin procédure PointMilieu()

 


Publié le : Lundi 05 septembre 2022 @ 07:01:02
Envoyer cet article à un ami      Page spéciale pour impression
Article du Jour
Il n'y a pas encore d'article du jour.
Lettre d'information

Recevez par mail les nouveautés du site.

Chat Box
Activité du Site

Pages vues depuis 15/01/2020 : 456 580

  • Nb. de membres 7
  • Nb. d'articles 119
  • Nb. de forums 0
  • Nb. de sujets 45
  • Nb. de critiques 0

Top 5  Statistiques


Plus de contenu