/* Claude EMERY - 07/08/2026 - Versiuon 02
Code Arduino avec 2 relais, qui ajoute 1 dans une variable toutes les heures de 09h00 à 14h00
pour commuter le relais 1 pendant 2 minutes avec relais 2 à off.
Puis de 14h00 à 20h00 commute le relais 2 pendant 2 minutes, et relais 1 à off.
Ajouter un module RTC pour la gestion de heure en cas de coupure électrique et la fonction millis().
Prévoir à 23h00 de commuter le relais 1 durant 15 minutes.
Prévoir un arrêt d'urgence en cas de problème.
************************************
09h00 → 14h00 : toutes les heures, incrémenter une variable et activer Relais 1 pendant 2 min, Relais 2 OFF.
14h00 → 20h00 : toutes les heures, incrémenter une variable et activer Relais 2 pendant 2 min, Relais 1 OFF.
23h00 : activer Relais 1 pendant 15 min.
RTC DS3231 : l'heure est conservée pendant une coupure grâce à sa pile.
millis() : aucune temporisation bloquante.
Arrêt d'urgence : désactivation immédiate des deux relais et blocage du fonctionnement jusqu'au réarmement.
Les changements de période provoquent également l'arrêt du relais opposé
*/
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
const byte ARRET_URGENCE = 2; // Pin Arret Urgence
const int Rouge = 6; // Pin Led Rouge
const int Verte = 7; // Pin Led Verte
const byte RELAIS_1 = 8; // Pin Relais 1
const byte RELAIS_2 = 9; // Pin Relais 2
const bool RELAIS_ACTIF_LOW = true; // Mettre false si votre relais est actif à HIGH
const bool URGENCE_ACTIVE_LOW = true; // Arrêt d'urgence actif à LOW avec INPUT_PULLUP
unsigned long compteur = 0; // Compteur demandé
unsigned long debutRelais = 0; // Gestion des temporisations avec millis()
unsigned long dureeRelais = 0; // Durée actuelle de fonctionnement du relais
byte relaisActif = 0; // Relais actuellement en fonctionnement
int derniereHeure = -1; // Mémorisation de l'heure déjà traitée
int dernierJour = -1; // Mémorisation du jour
bool cycle23hEffectue = false; // Pour l'événement de 23h00
void relaisOFF(byte relais){ // Fonction Relais OFF => LOW
if (RELAIS_ACTIF_LOW)
digitalWrite(relais, LOW);
else
digitalWrite(relais, HIGH);
}
void relaisON(byte relais){ // Fonction Relais ON => HIGH
if (RELAIS_ACTIF_LOW)
digitalWrite(relais, HIGH);
else
digitalWrite(relais, LOW);
}
void tousRelaisOFF(){ // Fonction Tous les Relais OFF
relaisOFF(RELAIS_1);
relaisOFF(RELAIS_2);
relaisActif = 0;
}
bool arretUrgence() {
if (URGENCE_ACTIVE_LOW)
return digitalRead(ARRET_URGENCE) == LOW;
else
return digitalRead(ARRET_URGENCE) == HIGH;
}
void demarrerRelais(byte relais, unsigned long duree){ // DEMARRAGE D'UN RELAIS
tousRelaisOFF(); // Toujours couper les deux avant de démarrer
if (arretUrgence()) // Sécurité : on ne démarre rien si arrêt d'urgence
return;
relaisON(relais);
relaisActif = relais;
debutRelais = millis();
dureeRelais = duree;
}
void gererRelais(){ // GESTION DES TEMPORISATIONS
if (relaisActif == 0)
return;
if (millis() - debutRelais >= dureeRelais){ // millis() fonctionne correctement même en cas de débordement
tousRelaisOFF();
Serial.println("Fin de temporisation relais.");
}
}
void verifierNouveauJour(const DateTime &now){ // RESET JOURNALIER
if (dernierJour != now.day()){
dernierJour = now.day();
derniereHeure = -1;
cycle23hEffectue = false;
Serial.println("Nouveau jour.");
}
}
void gererProgrammeHoraire(const DateTime &now){ // PROGRAMME 09h00 -> 20h00
int heure = now.hour();
int minute = now.minute();
// On ne déclenche qu'une fois au début de chaque heure.
// Exemple : 09:00, 10:00, 11:00...
if (minute != 0)
return;
if (heure == derniereHeure)
return;
if (heure >= 9 && heure < 14){ // 09h00 -> 14h00
compteur++;
Serial.print("Compteur = ");
Serial.println(compteur);
Serial.println("Activation RELAIS 1 pendant 2 minutes.");
demarrerRelais(RELAIS_1, 2UL * 60UL * 1000UL);
derniereHeure = heure;
}
else if (heure >= 14 && heure < 20){ // 14h00 -> 20h00
compteur++;
Serial.print("Compteur = ");
Serial.println(compteur);
Serial.println("Activation RELAIS 2 pendant 2 minutes.");
demarrerRelais(RELAIS_2, 2UL * 60UL * 1000UL);
derniereHeure = heure;
}
}
void gererProgramme23h(const DateTime &now){ // PROGRAMME DE 23h00
int heure = now.hour();
int minute = now.minute();
if (heure == 23 && minute == 0 && !cycle23hEffectue){ // Déclenchement à 23:00
Serial.println("23h00 : activation RELAIS 1 pendant 15 minutes.");
demarrerRelais(RELAIS_1, 15UL * 60UL * 1000UL);
cycle23hEffectue = true;
}
}
void setup(){ // Fonction SETUP
Serial.begin(9600); // Initialisation moniteur série
Wire.begin(); // Initialisation I2C
pinMode(RELAIS_1, OUTPUT); // Relais 1
pinMode(RELAIS_2, OUTPUT); // Relais 2
pinMode(Rouge, OUTPUT); // Déclaration en sortie de la pin led Rouge
pinMode(Verte, OUTPUT); // Déclaration en sortie de la pin led Verte
tousRelaisOFF(); // Arrêt immédiat des relais au démarrage
pinMode(ARRET_URGENCE, INPUT_PULLUP); // Bouton / contact arrêt d'urgence
if (!rtc.begin()){ // Initialisation RTC
Serial.println("ERREUR : RTC DS3231 non detectee !");
tousRelaisOFF(); // Sécurité : relais OFF
while (1)
{
// Blocage en cas d'absence du RTC
}
}
if (rtc.lostPower()){ // Si le RTC a perdu son alimentation
Serial.println("ATTENTION : RTC a perdu son alimentation.");
// -------------------------------------------------
// IMPORTANT :
// Ne pas remettre automatiquement l'heure ici
// sur une installation réelle.
//
// Pour régler l'heure une seule fois :
//
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
//
// Puis commenter cette ligne après programmation.
// -------------------------------------------------
Serial.println("Regler l'heure du RTC avant utilisation.");
}
DateTime now = rtc.now();
dernierJour = now.day();
Serial.println("Systeme demarre..."); // Affichage "Systeme demarre..."
Serial.print("Heure RTC : "); // Affichage "Heure RTC : "
Serial.print(now.hour()); // Affichage de l'heure
Serial.print(":"); // Affichage des :
Serial.println(now.minute()); // Affichage des minutes
}
void loop(){ // Fonction LOOP
if (arretUrgence()){ // PRIORITE ABSOLUE : ARRET D'URGENCE
tousRelaisOFF();
// Tant que l'urgence est active, aucune commande de relais n'est autorisee.
delay(10);
return;
}
DateTime now = rtc.now(); // Lecture du RTC
verifierNouveauJour(now); // Vérification changement de jour
gererRelais(); // Gestion des relais avec millis()
gererProgrammeHoraire(now); // Programme 09h00 -> 20h00
gererProgramme23h(now); // Programme de 23h00
delay(100); // Petite pause pour éviter de surcharger la boucle
}
Relais 1
Relais 2
Leds Jaune = Simulation moteur
Module RTC
09h00 => 14h00
14h00 => 20h00
Arret Urgence