/*
************************************************
* Feux de passage à niveau français *
* version 20250529 multi carte *
*pour carte Nano, pro-mini ou ATtiny 88 MH&Live*
* *
* https://youtu.be/-hZ-K13oVk4 *
************************************************
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Ce code est distribué gratuitement sous licence !
! Creativ Commons CC-BY-NC-ND 3.0 !
! !
! Cette licence permet à d'autres utilisateurs d'utiliser ce code !
! à des fins non commerciales, dans la mesure où le nom de l'auteur est !
! mentionné. Toute modification du code devra être soumise à !
! l'autorisation expresse de l'auteur. !
! !
! auteur Philippe GUENET - [email protected] - https://wgnt-train.fr !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
/*
Déroulement :
Détection de présence ON => Feux rouges + sonnerie
8" après => fermeture barrière
barrières fermées => arrêt sonnerie
Détection de présence OFF => arrêt feux rouges + ouverture barrières
la luminosité peut se régler de 0 à 255 ... mais on pourra prendre des valeurs plus faibles pour plus de visibliyé
les paramètres dont les commentaires commencent par * peuvent être modifiés.
Pour la sonnerie, on utilise un enregistrement MP3 enregistré sur une carte DF Player interne ou externe.
*/
/* LES CONNECTEURS
pour Nano
D13 =| |= D12
+3.3V =| |= ~D11 /!\
AREF =| |= ~D10 /!\ La bibliothèque Servo désactive le PWM sur D10&D11
A0 =| |= ~D9
A1 =| |= D8
A2 =| |= D7
A3 =| |= ~D6
A4-SDA =| |= ~D5
A5-SCL =| |= D4
A6 =| |= ~D3 - INT1
A7 =| |= D2 - INT0
5V =| |= GND
RESET =| |= RESET
GND =| |= D0-RX
VIN =| |= D1-TX
/* =============== */
/* LES CONNECTEURS
pour mini pro
~D10 =| |= ~D9
~D11 =| |= D8 A6 A7
D12 =| |= D7
D13 =| |= ~D6
A0 =| |= ~D5
A1 =| |= D4 A4 = SDA
A2 =| |= ~D3 A5 = SCL
A3 =| |= D2
5V =| |= GND
RESET =| |= RESET
GND =| |= D0-RX
RAW =| |= D1-TX
/!\ La bibliothèque Servo désactive le PWM sur D10&D11
/* =============== */
/*
pour ATtiny88 MH&Live
VIN =| |= D2
GND =| |= D1
5V =| |= D0
D3 =| |= RESET
D4 =| |= D25
D5 =| |= D24-SCL-A5
D6 =| |= D23-SDA-A4
D7 =| |= D22-A3
D8 =| |= D21-A2
~D9 =| |= D20-A1
~D10 =| |= D19-A0
D11 =| |= D18-A7
D12 =| |= D17-A8
D13 =| |= D16
D14 =| |= D15
/!\ La bibliothèque Servo désactive le PWM sur D10 & D11
*/
/* Choix de la carte utilisée en décommentant la ligne concernée */
#define IsNano
//#define IsMiniPro
//#define IsTiny88
//#define IsDebug // Affiche des messages de débogages dans le Serial Monitor de l'IDE.
// n'est fonctionnel qu'avec la carte Nano
//#define IsRelaySon // On peut utilser soit un DF Player intégré soit un système externe.
// Dans ce cas, le son est exécuté juste en alimentant la carte externe au travers d'un relais.
// Vérification qu'une carte est activée et une seule
#if (defined(IsNano) + defined(IsMiniPro) + defined(IsTiny88)) > 1
#error "Plusieurs cartes activées ! Définissez une seule carte à la fois."
#elif (defined(IsNano) + defined(IsMiniPro) + defined(IsTiny88)) == 0
#error "Aucune carte activée ! Définissez une carte avant de compiler. Pensez à la définir également dans l'IDE."
#endif
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#include <EEPROM.h>
#define LED_BUILTIN 13
/* POUR LA DETECTION */
const int pinDetection = 2; // BP / Relais détection connectés à D2
#include <Bounce2.h>
Bounce BPDetection = Bounce();
Bounce BPMilieu = Bounce();
Bounce BPVolume = Bounce();
Bounce BPEqualizer = Bounce();
const int dureeAntiRebond = 10;
bool etatDetection = false;
uint32_t departChronoDetection = 0ul; // initialise la tempo de démarrage de détection // interval de temps pour le déclanchement de la sonnerie
bool blocageDetection = false;
bool etatPointMilieu;
/* ================= */
#if defined(IsNano)|| defined(IsMiniPro)
/* LES CONNECTEURS */
const int pinLedsRouge1 = 5;
const int pinLedsRouge2 = 6;
const byte pinBPMilieu = 7;
const byte pinServo1 = 8; // Les servos sont connectés sur D8 et D9
const byte pinServo2 = 9;
const int pinBPEqualizer = 10;
const int pinBPVolume = 11;
const int pinRelaisSon = 12; // Déclanche le relais qui va déclancher le lecteur MP3
/* ============== */
/* POUR LES SERVOMOTEURS */
#include <Servo.h>
Servo servoPassageNiveau1;
Servo servoPassageNiveau2;
const int angleFerme = 550; // * à déterminer. PaN fermé
const int angleOuvert = 1500; // * à déterminer. PaN ouvert
const int sensMouvement = (angleOuvert > angleFerme) ? 1 : -1;
const byte ralentissementServos = 3; // * Règle la vitesse de rotation du servo en introduisant une pause entre chaque rotation.
int angleIntermediaire; // valeur de l'angle intermédiaire pendant le mouvement
const int angleRebondsDown = 140; // * angles de dépacement maxi de rebonds. Doit être un multiple de 20
const int angleRebondsUp = 140;
const int pasRebonds = 10;
int amplitudeRebonds;
int angleRebonds;
uint32_t actuelTempsRebonds;
uint32_t precedentTempsRebonds;
const uint32_t delaisFermetureBarrieres = 3000ul; // * interval de temps pour la fermeture des barrière (14" / 2)
uint32_t precedentMillisBarrieres = 0ul;
uint32_t precedentMillisServos = 0ul;
/* ===================== */
#elif defined(IsTiny88)
#include <SoftwareServo.h>
SoftwareServo servoPassageNiveau1;
SoftwareServo servoPassageNiveau2;
/* LES CONNECTEURS */
const int pinDetection = 2; // BP - Relais détection connectés à D2
const int pinLedsRouge1 = 9;
const int pinLedsRouge2 = 10;
const int pinServo1 = 7; // Les servos sont connectés sur D8 et D9
const int pinServo2 = 8;
const int pinBPMilieu = 11;
const int pinRelaisSon = 12; // Déclanche le relais qui va déclancher le lecteur MP3
/* ============== */
/* POUR LES SERVOMOTEURS */
const int angleFerme = 75; // * à déterminer. PaN fermé
const int angleOuvert = 105; // * à déterminer. PaN ouvert
const byte ralentissementServos = 50; // * Règle la vitesse de rotation du servo en introduisant une pause entre chaque rotation.
int angleIntermediaire; // valeur de l'angle intermédiaire pendant le mouvement
const int angleRebondsDown = 8; //16; // * angles de dépacement maxi de rebonds. Doit être un multiple de 2
const int angleRebondsUp = 8; //16;
unsigned long actuelTempsRebonds;
unsigned long precedentTempsRebonds;
int amplitudeRebonds;
int angleRebonds;
int pasRebonds = 1; //2;
const unsigned long delaisFermetureBarrieres = 3000ul; // * interval de temps pour la fermeture des barrière (7" / 2)
unsigned long precedentMillisBarrieres = 0ul;
unsigned long precedentMillisServos = 0ul;
bool etatPinPM = false;
/* ===================== */
#else
#error "Erreur carte !!!!"
#endif
/* POUR LA SONNERIE */
#include <DFPlayerMini_Fast.h>
DFPlayerMini_Fast Sonnerie;
const uint32_t delaisRelaisSon = 0ul; // * interval de temps pour le déclanchement de la sonnerie
bool etatSonnerie = false;
int volumeSonnerie = 20; // de 0 à 30. BP de réglage au pas de 5
int equalizerSonnerie = 0; // de 0 à 5
/* =============== */
/* POUR LES LEDS ROUGES */
//const int incrementLuminositeRouges = 6; // * Pas d'incrémentation de la luminosité. Plus la valeur est grande, moins la variation de luminosité sera progressive
//const int intervalRouges = 15; // * Délai entre 2 incrémentations
const int incrementLuminositeRouges = 7; // * Pas d'incrémentation de la luminosité. Plus la valeur est grande, moins la variation de luminosité sera progressive
const int intervalRouges = 10; // * Délai entre 2 incrémentations
const int luminositeMiniRouges = 0; // *
const int luminositeMaxiRouges = 250; // *
int luminositeLedsRouges = luminositeMiniRouges;
unsigned long previousMillisRouges = 0ul; // Temps précédent état led rouge en millisecondes
enum etatRouges {
Rouges_INIT,
Rouges_UP,
Rouges_DOWN,
Rouges_OFF
};
etatRouges etatLedsRouges = Rouges_INIT;
/* ==================== */
enum barrieres {
INIT_FERMETURE,
FERMETURE,
FERME,
INIT_OUVERTURE,
OUVERTURE,
OUVERT
};
barrieres etatBarrieres;
enum rebonds {
UP,
DOWN
};
rebonds sensRebonds;
/* LES DRAPEAUX */
bool flagExtinctionRouges = false;
/* ============ */
void setup() {
#if defined(IsNano) && defined(IsDebug)
Serial.begin(9600);
Serial.println(F("PRET"));
#endif
pinMode(pinLedsRouge1, OUTPUT);
pinMode(pinLedsRouge2, OUTPUT);
pinMode(pinServo1, OUTPUT);
pinMode(pinServo2, OUTPUT);
pinMode(pinRelaisSon, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
#if defined(isTiny88) || defined(IsMiniPro)
// Sur les PCB pour Tiny88 la détection est cablée en PULLDOWN
BPDetection.attach(pinDetection, INPUT);
#else
// ici la détection est cablée en PULLUP
BPDetection.attach(pinDetection, INPUT_PULLUP);
#endif
BPDetection.interval(dureeAntiRebond);
BPMilieu.attach(pinBPMilieu, INPUT_PULLUP);
BPMilieu.interval(dureeAntiRebond);
BPVolume.attach(pinBPVolume, INPUT_PULLUP);
BPVolume.interval(dureeAntiRebond);
BPEqualizer.attach(pinBPEqualizer, INPUT_PULLUP);
BPEqualizer.interval(dureeAntiRebond);
// On lit l'état du pin de détection (D2). Comme on est en PullUp, on inverse la logique pour
// obtenir "Occupé" = true et "Libre" = false
#if defined(IsTiny88) || defined(IsMiniPro)
etatDetection = digitalRead(pinDetection);
#else
etatDetection = !digitalRead(pinDetection);
#endif
angleIntermediaire = etatDetection ? angleFerme : angleOuvert;
etatBarrieres = etatDetection ? FERME : OUVERT;
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.print(F("Etat initial : "));
Serial.println(etatDetection ? "Voie occupee : barrieres fermees!" : "Voie libre : barrieres ouvertes!");
#endif
// On attache les servos.
if (!servoPassageNiveau1.attached()) {servoPassageNiveau1.attach(pinServo1); }
if (!servoPassageNiveau2.attached()) {servoPassageNiveau2.attach(pinServo2); }
delay(100);
// On initialise les servos en fonction de l'état du pin de détection (D2).
#if defined(IsTiny88)
servoPassageNiveau1.write(angleIntermediaire);
servoPassageNiveau2.write(angleIntermediaire);
delay(400);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleIntermediaire);
servoPassageNiveau2.writeMicroseconds(angleIntermediaire);
delay(400);
#endif
// On détache les servos.if (servoPassageNiveau1.attached()) {servoPassageNiveau1.detach(); }
if (servoPassageNiveau2.attached()) {servoPassageNiveau2.detach(); }
delay(150);
// On lit la valeur du volume enregistrée en EEprom puis on initialise la carte DFPayer.
lectureEEprom(); initDFPlayer();
// On initialise l'état des PB annexes.
BPDetection.update();
BPMilieu.update();
BPVolume.update();
BPEqualizer.update();
} // Fin de setup
void loop() {
if (etatPointMilieu == false){
BPDetection.update();
if (BPDetection.changed() && blocageDetection == false){
litDetection();
} // Fin de if ((blocageDetection == false) && (BPDetection.changed()))
BPVolume.update();
if (BPVolume.changed()) {
reglageVolume();
} // Fin de if (BPVolume.changed())
BPEqualizer.update();
if (BPEqualizer.changed()) {
reglageEqualizer();
} // Fin de if (BPEqualizer.changed())
actionsBarrieres();
afficheLedsRouges();
} // Fin de if (etatPointMilieu == false)
BPMilieu.update();
if (BPMilieu.changed()&& BPMilieu.read() == LOW){
etatPointMilieu =! etatPointMilieu;
#if defined(IsNano) && defined(IsDebug)
Serial.println(F("Point Milieu!"));
#endif
pointMilieu();
} // Fin de if (BPMilieu.changed && BPMilieu.read == HIGH)
} // Fin de loop
void litDetection() {
/*L'état de D2 a été modifié. On relit etatDetection
Si le nouvel état est passé à "true" c'est qu'une présence est
détectée. On déclanche donc la fermeture des barrières.
Si au contraire le nouvel état passe à "false" c'est qu'il n'y a plus
d'occupation de voie et on déclanche l'ouverture des barrières.
Pendant ces deux actions, on empêche toute lecture de la détection.
Si le nouvel état de détection est égal à l'ancien, c'est que rien n'est changé. On maintient
l'état des barrières à OUVERT si la détection est à "false" ou à FERME si la détection est
à "true".
*/
#if defined(isTiny88) || defined(IsMiniPro)
etatDetection = digitalRead(pinDetection);
#else
etatDetection = !digitalRead(pinDetection);
#endif
if (etatDetection == true) {
etatBarrieres = INIT_FERMETURE;
} else {
etatBarrieres = INIT_OUVERTURE;
} // Fin de if (etatDetection == true)
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.print(F("Changement etat : "));
Serial.println(etatDetection ? "Voie occupee : Fermeture des barrieres!" : "Voie libre : Ouverture des barrieres!");
#endif
} // Fin de procédure litDetection()
void actionsBarrieres () {
switch (etatBarrieres) {
case INIT_FERMETURE :
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.println(F("Initialisation vers fermeture!"));
#endif
/* On bloque la lecture de la détection le temps du mouvement des servos. */
if (blocageDetection == false) {blocageDetection = true;}
/* On démarre le chrono pour déclancher la sonnerie et la fermeture des barrières. */
departChronoDetection = millis();
/* On met à jour l'état de l'action sur les barrières. */
etatBarrieres = FERMETURE;
break;
case FERMETURE :
/* On allume les leds rouges. */
if (etatLedsRouges == Rouges_INIT){
etatLedsRouges = Rouges_UP;
}
if ((millis() - departChronoDetection) >= delaisRelaisSon) {
/* On déclanche la sonnerie. */
if (etatSonnerie == false){
etatSonnerie = true;
#if defined(IsRelaySon)
digitalWrite(pinRelaisSon, HIGH);
#else
Sonnerie.loop(1);
#endif
} // Fin de if (etatSonnerie == false)
} // Fin de if ((millis() - departChronoDetection) >= delaisRelaisSon)
if ((millis() - departChronoDetection) >= delaisFermetureBarrieres) {
/* On abaisse les barrières. */
fermetureBarrieres();
} // Fin de if ((millis() - departChronoDetection) >= delaisFermetureBarrieres)
break;
case FERME :
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.println(F("Barrieres fermees!"));
#endif
/* On arrête la sonnerie. */
if (etatSonnerie == true){
etatSonnerie = false;
#if defined(IsRelaySon)
digitalWrite(pinRelaisSon, LOW);
#else
Sonnerie.pause();
#endif
} // Fin de if (etatSonnerie == true)
if (etatLedsRouges == Rouges_INIT){
etatLedsRouges = Rouges_UP;
}
/* On débloque la lecture de l'état de la détection. */
if (blocageDetection == true) {blocageDetection = false;}
break;
case INIT_OUVERTURE :
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.println(F("Initialisation vers ouverture!"));
#endif
/* On bloque la lecture de la détection le temps du mouvement des servos. */
if (blocageDetection == false) {blocageDetection = true;}
/* On éteint les leds rouges */
if (etatLedsRouges != Rouges_INIT){
etatLedsRouges = Rouges_OFF;
}
/* On met à jour l'état de l'action sur les barrières. */
etatBarrieres = OUVERTURE;
break;
case OUVERTURE :
/* On ouvre les barrières */
ouvertureBarrieres();
break;
case OUVERT :
#if defined(IsNano) && defined(IsDebug)
// Affichage de l'état sur le moniteur série
Serial.println(F("Barrieres ouvertes!"));
#endif
/* On débloque la lecture de l'état de la détection. */
if (blocageDetection == true) {blocageDetection = false;}
break;
} // Fin de switch (etatBarriere)
} // Fin de procédure actionsBarrieres()
void ouvertureBarrieres(){
if (!servoPassageNiveau1.attached()) {servoPassageNiveau1.attach(pinServo1); }
if (!servoPassageNiveau2.attached()) {servoPassageNiveau2.attach(pinServo2); }
//if (angleIntermediaire < angleOuvert) {
if ((angleIntermediaire - angleOuvert) * sensMouvement < 0) {
// Si l'angle intermédiaire n'est pas arrivé à la valeur angle ouvert, on continue
//en appiquant un ralentissement pour diminuer la vitesse d'ouverture
unsigned long actuelMillis = millis();
if (actuelMillis - precedentMillisBarrieres >= ralentissementServos) {
precedentMillisBarrieres = actuelMillis;
angleIntermediaire += sensMouvement;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleIntermediaire);
servoPassageNiveau2.write(angleIntermediaire);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleIntermediaire);
servoPassageNiveau2.writeMicroseconds(angleIntermediaire);
#endif
} // Fin de if (actuelMillis - previousMillis >= Ralentissement)
amplitudeRebonds = angleRebondsUp;
angleRebonds = 0;
sensRebonds = DOWN;
} else {
// Si l'angle intermédiaire est arrivé à la valeur angle ouvert,
/* Effet de rebonds à l'ouverture' */
if (amplitudeRebonds > 0){
rebondsUp();
} else {
// on débranche le servo, on met à jour etatBarriere
unsigned long actuelMillis = millis(); // Obtenir le temps actuel
if (actuelMillis - precedentMillisServos >= 150) {
if (servoPassageNiveau1.attached()) {servoPassageNiveau1.detach(); }
if (servoPassageNiveau2.attached()) {servoPassageNiveau2.detach(); }
} // Fin de if (actuelMillis - previousMillis >= 150)
angleIntermediaire = angleOuvert;
etatBarrieres = OUVERT;
} // Fin de if (amplitudeRebonds > 0)
} // Fin de if (angleIntermediaire < angleOuvert)
} // Fin de procédure ouvertureBarrieres()
void fermetureBarrieres(){
if (!servoPassageNiveau1.attached()) {servoPassageNiveau1.attach(pinServo1);}
if (!servoPassageNiveau2.attached()) {servoPassageNiveau2.attach(pinServo2);}
//if (angleIntermediaire > angleFerme) {
if ((angleIntermediaire - angleFerme) * sensMouvement > 0) {
// Si l'angle intermédiaire n'est pas arrivé à la valeur angle fermé, on continue
//en appiquant un ralentissement pour diminuer la vitesse de fermeture
unsigned long actuelMillis = millis();
if (actuelMillis - precedentMillisBarrieres >= ralentissementServos) {
precedentMillisBarrieres = actuelMillis;
angleIntermediaire -= sensMouvement;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleIntermediaire);
servoPassageNiveau2.write(angleIntermediaire);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleIntermediaire);
servoPassageNiveau2.writeMicroseconds(angleIntermediaire);
#endif
}
amplitudeRebonds = angleRebondsDown;
angleRebonds = 0;
sensRebonds = UP;
} else {
// Si l'angle intermédiaire est arrivé à la valeur angle fermé,
/* Effet de rebonds à la fermeture */
if (amplitudeRebonds > 0){
rebondsDown();
} else {
// on débranche le servo, on met à jour etatBarriere et on arrête le son
unsigned long actuelMillis = millis();
if (actuelMillis - precedentMillisServos >= 150) {
if (servoPassageNiveau1.attached()) {servoPassageNiveau1.detach();}
if (servoPassageNiveau2.attached()) {servoPassageNiveau2.detach();}
} // Fin de if (actuelMillis - previousMillisServos >= 150)
angleIntermediaire = angleFerme;
etatBarrieres = FERME;
} // Fin de if (amplitudeRebonds > 0)
} // Fin de if (angleIntermediaire > angleFerme)
} // Fin de procédure fermetureBarrieres()
void rebondsUp(){
switch (sensRebonds) {
case DOWN :
/* Le rebond redescend */
if (angleRebonds < amplitudeRebonds) {
actuelTempsRebonds = millis();
if (actuelTempsRebonds - precedentTempsRebonds >= 10) {
angleRebonds += pasRebonds;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleOuvert - angleRebonds);
servoPassageNiveau2.write(angleOuvert - angleRebonds);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleOuvert - angleRebonds);
servoPassageNiveau2.writeMicroseconds(angleOuvert - angleRebonds);
#endif
precedentTempsRebonds = actuelTempsRebonds;
} // Fin de if (actuelTempsRebonds - precedentTempsRebonds >= 10)
} else {
angleRebonds = amplitudeRebonds;
sensRebonds = UP;
} // Fin de if (angleRebonds < amplitudeRebonds)
break;
case UP :
/* Le rebond remonte */
if (angleRebonds > 0) {
actuelTempsRebonds = millis();
if (actuelTempsRebonds - precedentTempsRebonds >= 10) {
angleRebonds -= pasRebonds;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleOuvert - angleRebonds);
servoPassageNiveau2.write(angleOuvert - angleRebonds);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleOuvert - angleRebonds);
servoPassageNiveau2.writeMicroseconds(angleOuvert - angleRebonds);
#endif
precedentTempsRebonds = actuelTempsRebonds;
} // Fin de if (actuelTempsRebonds - precedentTempsRebonds >= 10)
} else {
amplitudeRebonds -= 20;
angleRebonds = 0;
sensRebonds = DOWN;
} // Fin de (angleRebonds > 0)
break;
} // Fin de switch (sensRebond)
} // Fin de procédure rebondsDown
void rebondsDown(){
/* angleRebonds s'incrémente de 0 à la valeur de amplitudeRebonds par pas de 10
quand la valeur angleRebondsDown est atteinte angleRebond se décrémente par pas de 10
jusque la valeur 0.
Quand ce cycle est termnié on recommence en décrémentant la valeur amplitude rebonds
de 20 et ainsi de suite jusqu'à ce que amplitudeRebonds soit égal à
*/
switch (sensRebonds) {
case UP:
/* Le rebond remonte */
if (angleRebonds < amplitudeRebonds) {
actuelTempsRebonds = millis();
if (actuelTempsRebonds - precedentTempsRebonds >= 10) {
angleRebonds += pasRebonds;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleOuvert + angleRebonds);
servoPassageNiveau2.write(angleOuvert + angleRebonds);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleFerme + angleRebonds);
servoPassageNiveau2.writeMicroseconds(angleFerme + angleRebonds);
#endif
precedentTempsRebonds = actuelTempsRebonds;
} // Fin de if (actuelTempsRebonds - precedentTempsRebonds >= 10)
} else {
angleRebonds = amplitudeRebonds;
sensRebonds = DOWN;
} // Fin de if (angleRebonds < amplitudeRebonds)
break;
case DOWN :
/* Le rebond redescend */
if (angleRebonds > 0) {
actuelTempsRebonds = millis();
if (actuelTempsRebonds - precedentTempsRebonds >= 10) {
angleRebonds -= pasRebonds;
#if defined(IsTiny88)
servoPassageNiveau1.write(angleOuvert + angleRebonds);
servoPassageNiveau2.write(angleOuvert + angleRebonds);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleFerme + angleRebonds);
servoPassageNiveau2.writeMicroseconds(angleFerme + angleRebonds);
#endif
precedentTempsRebonds = actuelTempsRebonds;
} // Fin de if (actuelTempsRebonds - precedentTempsRebonds >= 10)
} else {
amplitudeRebonds -= 20;
angleRebonds = 0;
sensRebonds = UP;
} // Fin de if (angleRebonds > 0)
} // Fin de switch (sensRebond)
} // Fin de procédure rebondsDown
void afficheLedsRouges(){
unsigned long actuelMillisRouges = millis();
if (actuelMillisRouges - previousMillisRouges >= intervalRouges) {
previousMillisRouges = actuelMillisRouges;
switch (etatLedsRouges) {
case Rouges_UP:
luminositeLedsRouges += incrementLuminositeRouges;
if (luminositeLedsRouges >= luminositeMaxiRouges) {
etatLedsRouges = Rouges_DOWN;
}
break;
case Rouges_DOWN:
luminositeLedsRouges -= incrementLuminositeRouges;
if (luminositeLedsRouges <= luminositeMiniRouges) {
etatLedsRouges = Rouges_UP;
}
break;
case Rouges_OFF :
int Rouges = luminositeMaxiRouges;
while (Rouges > luminositeMiniRouges){
Rouges -= 1;
delay(2);
analogWrite(pinLedsRouge1, Rouges);
analogWrite(pinLedsRouge2, Rouges);
} // Fin de while (Rouges > luminositeMiniRouges)
etatLedsRouges = Rouges_INIT;
luminositeLedsRouges = Rouges;
break;
break;
} // Fin de switch (etatLedsRouges)
analogWrite(pinLedsRouge1, luminositeLedsRouges);
analogWrite(pinLedsRouge2, luminositeLedsRouges);
} // Fin de if (actuelMillisRouges - previousMillisRouges >= tempoRouges)
} // Fin de procédure afficheLedRouge()
void lectureEEprom(){
volumeSonnerie = EEPROM.read(200);
if ((volumeSonnerie < 5) || (volumeSonnerie > 30)) {
volumeSonnerie = 20;
EEPROM.update(200, volumeSonnerie);
} else {
// On visualise la valeur du volume par le nombre d'allumage/extinction de la led intégrée
for (byte J = 0; J < (volumeSonnerie / 5); J += 1){
digitalWrite(LED_BUILTIN, HIGH);
delay(300);
digitalWrite(LED_BUILTIN, LOW);
delay(300);
} // Fin de for (byte J = 0; J < (volumeSonnerie / 5); J += 1)
} // Fin de if ((volumeSonnerie < 5) || (volumeSonnerie > 30))
equalizerSonnerie = EEPROM.read(220);
if ((equalizerSonnerie > 5) || (equalizerSonnerie < 0)) {
equalizerSonnerie = 0;
EEPROM.update(220, equalizerSonnerie);
} // Fin de if (equalierSonnerie > 5)
} // Fin de procédure lectureEEprom()
void initDFPlayer(){
// /!\ pour les cartes Uno et Nano, il conviendra d'utiliser d'autres sorties que DX0 et RX0 qui sont utilisées par le moniteur serial /!\
// /!\ ajouter dans ce cas #include <SoftwareSerial.h> /!\
// /!\ initialiser SoftwareSerial mySoftwareSerial(5, 6); // par exemple TX, RX /!\
Serial.begin(9600); // Lien avec le DFPlayer
Sonnerie.begin(Serial); // Initialisation DFPlayer
Sonnerie.volume(volumeSonnerie);
Sonnerie.EQSelect(equalizerSonnerie);
/*----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
myDFPlayer.EQ(DFPLAYER_EQ_POP);
myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
myDFPlayer.EQ(DFPLAYER_EQ_BASS);
*/
} // Fin de procédure initDFPlayer
void reglageVolume(){
if (BPVolume.read() == HIGH) {
volumeSonnerie += 5; if(volumeSonnerie > 30) volumeSonnerie = 5;
} else {
EEPROM.update(200, volumeSonnerie);
#if defined(IsNano) && defined(IsDebug)
// On affiche la valeur sur le moniteur série
Serial.print(F("Volume :")); Serial.println(volumeSonnerie);
#endif
// On visualise la valeur par le nombre d'allumage/extinction de la led intégrée
for (byte J = 0; J < (volumeSonnerie / 5); J += 1){
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
} // Fin de for (byte J = 0; J < (volumeSonnerie / 5); J += 1)
} // Fin de if (BPVolume.read() == HIGH)
} // Fin de procédure reglageVolume()
void reglageEqualizer(){
if (BPEqualizer.read() == HIGH) {
equalizerSonnerie += 1; if(equalizerSonnerie > 5) equalizerSonnerie = 0;
} else {
EEPROM.update(220, equalizerSonnerie);
// On affiche la valeur sur le moniteur série
#if defined(IsNano) && defined(IsDebug)
Serial.print(F("Eqalizer :")); Serial.println(equalizerSonnerie);
#endif
// On visualise la valeur par le nombre d'allumage/extinction de la led intégrée
for (byte J = 0; J < equalizerSonnerie; J += 1){
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
} // Fin de for (byte J = 0; J < equalizerSonnerie; J += 1)
} // Fin de if (BPEqualizer.read() == HIGH)
} // Fin de procédure reglageEqualizer()
void pointMilieu(){
if (etatPointMilieu == true){
// Si le drapeau etatMilieu est vrai on positionne à angle moyen.
// On allume la led intégrée
digitalWrite(LED_BUILTIN, HIGH);
// On attache les servos.
if (!servoPassageNiveau1.attached()) {servoPassageNiveau1.attach(pinServo1); }
if (!servoPassageNiveau2.attached()) {servoPassageNiveau2.attach(pinServo2); }
delay(150);
// On positionne les servos
#if defined(IsTiny88)
servoPassageNiveau1.write((angleFerme + angleOuvert) / 2);
servoPassageNiveau2.write((angleFerme + angleOuvert) / 2);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds((angleFerme + angleOuvert) / 2);
servoPassageNiveau2.writeMicroseconds((angleFerme + angleOuvert) / 2);
#endif
delay(150);
// On détache les servos.
if (servoPassageNiveau1.attached()) {servoPassageNiveau1.detach(); }
if (servoPassageNiveau2.attached()) {servoPassageNiveau2.detach(); }
delay(150);
} else {
// Si le drapeau etatMilieu est faux on repositionne à la position en cours.
#if defined(IsMiniPro)|| defined(isTiny88)
etatDetection = digitalRead(pinDetection);
#else
etatDetection = !digitalRead(pinDetection);
#endif
angleIntermediaire = etatDetection ? angleFerme : angleOuvert;
etatBarrieres = etatDetection ? FERME : OUVERT;
// On attache les servos.
if (!servoPassageNiveau1.attached()) {servoPassageNiveau1.attach(pinServo1); }
if (!servoPassageNiveau2.attached()) {servoPassageNiveau2.attach(pinServo2); }
delay(100);
// On positionne les servos en fonction de l'état du pin de détection (D2).
#if defined(IsTiny88)
servoPassageNiveau1.write(angleIntermediaire);
servoPassageNiveau2.write(angleIntermediaire);
delay(400);
SoftwareServo::refresh();
#else
servoPassageNiveau1.writeMicroseconds(angleIntermediaire);
servoPassageNiveau2.writeMicroseconds(angleIntermediaire);
delay(400);
#endif
// On détache les servos.
if (servoPassageNiveau1.attached()) {servoPassageNiveau1.detach(); }
if (servoPassageNiveau2.attached()) {servoPassageNiveau2.detach(); }
delay(150);
// On éteint la led intégrée
digitalWrite(LED_BUILTIN, LOW);
} // Fin de if (etatMilieu == true)
} // Fin de procédure pointMilieu()
Ouverture <=
Fermeture =>
Volume
Equal
P.M.
BP en PullUp