/*******************************************************************************
* PN_TIB_4Feux_Barrieres_SortieSon_InitFerme.ino
* *****************************************************************************
* Programme developpe pour le projet de PN pour Train In Box.
* Il prend en compte l arrivee du train, le clignotement des feux en simulant
* une ampoule a filaments, un delai avant mouvement des barrieres,
* le mouvements des deux barrieres sur 90° d amplitude (depend de
* la transmission adoptee).
* Le programme s'initialise barrieres fermees, donc AVEC TRAIN EN GARE SUR TIB.
* La LED_SON est allumee tant que sonnerie doit jouer ; cette sortie commande
* le module sonore.
* *****************************************************************************
* Christian BEZANGER - 13 Novembre 2018 - 2 Juin 2019 - 29 mai 2020
******************************************************************************/
#include <LightDimmer.h> // Bibliotheque pour gerer les feux du PN
#include <Servo.h> // Bibliotheque pour gerer les barrieres du PN
const byte ILS=2; // entree des capteurs
const byte LED=6; // sortie PWM pour deux feux du PN
const byte LED2=5; // sortie PWM pour deux autres feux du PN
const byte LED_SON=7; // sortie pour indiquer sonnerie
const byte S1=4; // sortie pour le servomoteur 1
const byte S2=8; // sortie pour le servomoteur 2
unsigned int compteur = 1; // compteur d evenements (survol ILS)
// Variables utilisateur pour reglage du mouvement des barrieres
// -------------------------------------------------------------
unsigned long delaiFermeture = 4000; // Regle le delai entre clignotement LED
// et fermeture barrieres - entre 2000 et 8000 mais 0 sur TIB (pas de delai)
int speedServo = 30; // Regle la vitesse de mouvement des barrieres
// Variables non utilisateur
// -------------------------
volatile static boolean etatZonePN = true; // true si la zone du PN est occupee
volatile static boolean old_etatZonePN = false; // etat anterieur de la zone
volatile static unsigned long old_top_debutISR; // Date anterieure d appel ISR
unsigned long old_top = 0; // variable pour afficher donnees utiles
int posServo = 90; // position courante a initialiser imperativement FERMEE
int posOuvert = 0; // barriere a la verticale
int posFerme = 90; // barriere a l'horizontale (90° de la verticale)
unsigned long topAttente = 0; // top pris au début franchissement de la zone PN
boolean etatSon = false; // true si sonnerie doit retentir
// Instanciations
LightDimmer feuPN;
LightDimmer feu2PN;
Servo servo1;
Servo servo2;
void changeEtat() { // routine d'interruption (ISR)
unsigned long top_debutISR = millis(); // date appel ISR
if((top_debutISR - old_top_debutISR) > 2000) {
// 2 secondes au moins entre execution ISR
etatZonePN = !etatZonePN; // etat passe a etat oppose
old_top_debutISR = top_debutISR; // initialisation date anterieure d appel ISR
}
} // fin de ISR
void setup() {
// put your setup code here, to run once:
//Serial.begin(115200); // communication avec le moniteur si besoin
pinMode (ILS, INPUT_PULLUP); // entree capteur
pinMode (LED_BUILTIN, OUTPUT); // LED du module allumee si Zone PN occupee
pinMode (LED, OUTPUT); // sortie pour feux du PN
pinMode (LED2, OUTPUT); // sortie pour autres feux du PN
pinMode (LED_SON, OUTPUT);
attachInterrupt (digitalPinToInterrupt(ILS), changeEtat, FALLING);
digitalWrite (LED_BUILTIN, LOW);
feuPN.begin(LED, HIGH); // LED s'allume avec etat haut
feu2PN.begin(LED2, HIGH); // LED2 s'allume avec etat haut
servo1.attach(S1);
servo2.attach(S2);
// initialisation des barrieres en position fermee
servo1.write(posFerme); // barriere 1 FERMEE apres initialisation
servo2.write(posFerme); // barriere 2 FERMEE apres initialisation
delay(2000);
digitalWrite (LED_BUILTIN, HIGH); // Indique fin de setup
} // fin de setup
void loop() {
// put your main code here, to run repeatedly:
if(etatSon == false) {digitalWrite (LED_SON, LOW);}
if(etatSon == true) {digitalWrite (LED_SON, HIGH);}
if(etatZonePN == false) {
old_etatZonePN = etatZonePN;
digitalWrite (LED_BUILTIN, LOW); // eteint LED de controle de la zone PN
etatSon = false; // pas de sonnerie
feuPN.stopBlink(); // arrete le clignotement
feu2PN.stopBlink(); // arrete le clignotement
feuPN.off(); // eteint les feux
feu2PN.off(); // eteint les feux
// ouverture barriere
if(posServo > posOuvert) {
posServo = posServo - 1;
servo1.write(posServo);
servo2.write(posServo);
delay(speedServo);
} // fin du test sur position des servos
} // fin du test sur etat de la Zone du PN -> false
if(etatZonePN == true) {
if(etatZonePN != old_etatZonePN) {
topAttente = millis(); // prend un top d'entree dans zone PN
old_etatZonePN = etatZonePN;
etatSon = true; // sonnerie
} // fin du deuxieme if
digitalWrite (LED_BUILTIN, HIGH); // allume LED de controle de la zone PN
feuPN.startBlink(); // commence le clignotement
feu2PN.startBlink(); // commence le clignotement
// fermeture barriere après attente
if(millis() - topAttente > delaiFermeture) {
if(posServo <= posFerme) {
posServo = posServo + 1;
servo1.write(posServo);
servo2.write(posServo);
if(posServo >= 89) {etatSon = false;}
delay(speedServo);
} // fin du test sur position des servos
} // fin du test sur delai avant ouverture
} // fin du test sur etat de la Zone du PN -> true
LightDimmer::update();
/*
if(old_top_debutISR != old_top) { // Affichage pour chaque nouveau survol ILS
Serial.print(compteur);
Serial.print(" ");
Serial.print(old_top_debutISR);
Serial.print(" ");
Serial.println(old_top_debutISR - old_top);
old_top = old_top_debutISR;
compteur = compteur + 1;
}
*/
} // fin de loop