/****************************************************************************************************************************************
 * Projet Chronomètre et minuteur cyclique avec LCD 20X4 réalisé par:  Daniel Talbot Technicien                                         *
 * Pour Ez-Weekend-Project au Club Technique des Laurentides                                                                            *
 * Dans le cadre du programme C.I.P.A.D. (Cours d'initiation à la Programmation Arduino pour Débutant(e)s) gratuit et sans inscription. *
 * Copiez ce lien pour accéder à la vidéo concernant ce projet                                                                          *
 * https://www.youtube.com/watch?v=hNc6xO7kvRo                                                                                          *
 * ou celui-ci pour accéder à toutes les leçons déjà publiées...                                                                        *
 * https://www.youtube.com/playlist?list=PLoffRtP427acSg1FbpFuH_g5ptz-aovFN                                                             *
 *                                                                                                                                      *
 ****************************************************************************************************************************************/ 
 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // Renseigner l'adresse I2C du LCD à 0x27 sur 4 lignes et 20 chars

//Déclaration des variables globales disponibles n'importe où dans le programme
int ledBleu = 9;
int SSR_relais = 10;     bool etat_SSRrelais = LOW;
int btn_StartStop = 2;   bool EtatBtnStartStop;
int btn_Reset = 3;       bool EtatBtn_Reset;
int btn_RecordSet = 6;   bool EtatBtn_RecordSet;
int btn_Set_TimeON = 4;  bool EtatBtn_Set_TimeON;
int btn_Set_TimeOFF = 5; bool EtatBtn_Set_TimeOFF;
char tempsON[20], tempsOFF[20];
char Chrono[20], MinuteurON[20], MinuteurOFF[20];
bool  FlagON = false, etatBtnPresser, EtatChronoOnOFF;
long Min = 60000, Sec = 1000;
long onTime, offTime;
long MyTimeON, H_ON = 0, M_ON = 0, S_ON = 0, MS_ON = 0;
long MyTimeOFF, H_OFF = 0, M_OFF = 0, S_OFF = 0, MS_OFF = 0;
long minutes_OFF = 0, minutes_ON = 0;
long TempsEcoule;
long Milliseconde, Seconde, Minute, Heure;
unsigned long currentTime = 0, previousTime = 0;
unsigned long startMillis, currentMillis;
unsigned long period = 5000;
int Record, Start;
bool etatRecord = false;

void setup() {
  lcd.init(); lcd.backlight(); // initialise lcd I2C 2004 & active le rétro éclairage
  pinMode(btn_StartStop, INPUT_PULLUP);
  pinMode(btn_Reset, INPUT_PULLUP);
  pinMode(btn_RecordSet, INPUT);
  pinMode(btn_Set_TimeON, INPUT);
  pinMode(btn_Set_TimeOFF, INPUT);
  pinMode(ledBleu, OUTPUT);
  pinMode(SSR_relais, OUTPUT);
  etat_SSRrelais = LOW;
  digitalWrite(SSR_relais, LOW);
  //Affichage au démarrage
  lcd.setCursor(0, 0);  lcd.print("    Chronometre:     ");
  lcd.setCursor(0, 2);  lcd.print("                     ");
}

void loop() {
  // Lit la broche d'entrée du btn_StartStop et stock ça valeur dans EtatBtnStartStop. Ect...
  EtatBtnStartStop = digitalRead(btn_StartStop);
  EtatBtn_Reset = digitalRead(btn_Reset);
  EtatBtn_RecordSet = digitalRead(btn_RecordSet);
  EtatBtn_Set_TimeON = digitalRead(btn_Set_TimeON);
  EtatBtn_Set_TimeOFF = digitalRead(btn_Set_TimeOFF);
 
  fn_boutons(); // Appel la fonctions boutons.

  //On stocke la valeur du timer interne du microcontrôleur récupéré grâce à millis() dans la variable currentTime
  currentTime = millis();
  //On calcule la valeur de TempsEcoule en effectuant une soustraction entre currentTime et previousTime.
  TempsEcoule = currentTime - previousTime;
  //On stocke la valeur du timer interne du microcontrôleur récupéré grace à millis() dans la variable previousTime
  previousTime = millis();

  if (EtatChronoOnOFF == 1) {
    Milliseconde = Milliseconde + TempsEcoule;
    if (Milliseconde > 999) {
      Milliseconde = Milliseconde - 1000;
      Seconde++;

      if (MyTimeON > 0) {
        FlagON = true;//*****************
        etat_SSRrelais = FlagON; // État du relais selon la valeur de FlagOn (On/OFF ou 1/0 ou true/false)
        digitalWrite(SSR_relais, FlagON);  // Mettre à jour le relais selon la valeur de FlagOn (On/OFF ou 1/0 ou true/false)
        lcd.setCursor(14, 3); lcd.print("  ON  ");
        MyTimeON--;
        S_ON = MyTimeON;
      }

      if ((MyTimeOFF > 0) && (MyTimeON == 0)) {
        FlagON = false ;//**********************
        lcd.setCursor(14, 3); lcd.print("  OFF ");
        etat_SSRrelais = FlagON; // État du relais selon la valeur de FlagOn (On/OFF ou 1/0 ou true/false)
        digitalWrite(SSR_relais, FlagON); // Mettre à jour le relais selon la valeur de FlagOn (On/OFF ou 1/0 ou true/false)
        MyTimeOFF--; S_OFF = MyTimeOFF;
        if ((MyTimeOFF == 0) && (MyTimeON == 0)) {
          MyTimeON = onTime;
          MyTimeOFF = offTime;
        }
      }
    }

    if (Seconde > 59) {
      Seconde = 0; Minute++;
    }

    if (Minute > 59) {
      Minute = 0; Heure++;
    }
  }
  fn_display();
}
//**************************************************************************
void fn_display() {
  sprintf(MinuteurON, "T-ON:  %02ld:%02ld", M_ON, S_ON); //Formate l'affichage.
  sprintf(MinuteurOFF, "T-OFF: %02ld:%02ld", M_OFF, S_OFF); //Formate l'affichage.
  sprintf(Chrono, "%02ld:%02ld:%02ld:%03ld", Heure, Minute, Seconde, Milliseconde);//Formate l'affichage.
  lcd.setCursor(4, 1); lcd.print(Chrono); //Affiche le chronomètre sur la 2e ligne du lcd.
  lcd.setCursor(0, 2); lcd.print(MinuteurON); // Afffiche le minuteur ON sur la 3e ligne du lcd.
  lcd.setCursor(0, 3); lcd.print(MinuteurOFF);// Afffiche le minuteur OFF sur la 4e ligne du lcd.
}
void fn_boutons() { // Regroupe les Fonctions de tous les boutons poussoirs.  
   digitalWrite(ledBleu, EtatChronoOnOFF);
  if (EtatBtn_Set_TimeON) {  // Réglage du temps ON
    minutes_ON = minutes_ON + 1; // Incrémente de 1 à chaque pression du bouton bleu.
    if (minutes_ON > 59) { // si dépassement de 59, remet à 0.
      minutes_ON = 0;
    }
    S_ON = minutes_ON; fn_display(); 
    delay(10); // Délais de 10 ms entre chaque pression du bouton
    // Empêche les rebonds des boutons poussoirs
    while (EtatBtn_Set_TimeON) EtatBtn_Set_TimeON = digitalRead(btn_Set_TimeON);
  }
  if (EtatBtn_Set_TimeOFF) { // Réglage du temps OFF
    minutes_OFF = minutes_OFF + 1; //Incrémente de 1 à chaque pression du bouton jaune.
    if (minutes_OFF > 59) { // si dépassement de 59, remet à 0.
      minutes_OFF = 0;
    }
    S_OFF = minutes_OFF; 
    fn_display(); // Rafraîchi l'affichage.
    delay(10); // Délais de 10 ms entre chaque pression du bouton
    // Empêche les rebonds des boutons poussoirs
    while (EtatBtn_Set_TimeOFF) EtatBtn_Set_TimeOFF = digitalRead(btn_Set_TimeOFF);
  }

  // Enregitrement des temps ON/OFF du minuteur
  if (EtatBtn_RecordSet) {
    Record = Record + 1; // Nombre de fois que le bouton gris est pressé.
    if (Record == 1) { // S'il est égale à 1, exécute les instructions entre ses accolades.
      lcd.setCursor(17, 2); lcd.print("SET");// Set indique que la valeur du temps ON est stocké.
      onTime = minutes_ON;  MyTimeON = onTime;  S_ON = MyTimeON; // Enregistre les variables.
      fn_display(); // Rafraîchi l'affichage.
    }
    if (Record == 2) {  // S'il est égale à 2, exécute les instructions entre ses accolades.
      lcd.setCursor(17, 3); lcd.print("SET"); // Set indique que la valeur du temps OFF est stocké.
      offTime = minutes_OFF; MyTimeOFF = offTime; S_OFF = MyTimeOFF;  // Enregistre les variables.
      fn_display(); // Rafraîchi l'affichage.
      etatRecord = true; // Confirme que les valeurs sélectionnées on été engeristrées.
      delay(1000); // Délais de 1 secondes avant d'afficher les messages qui suivent...
      lcd.setCursor(14, 2); lcd.print("Ready!"); // Ready! indique que le minuteur ON est programmé et prêt à être lancé.
      lcd.setCursor(14, 3); lcd.print("Ready!"); // Ready! indique que le minuteur OFF est programmé et prêt à être lancé.
      delay(1000);// Délais de 1 secondes avant d'afficher les messages qui suivent..
      lcd.setCursor(14, 2); lcd.print("Relais"); 
      lcd.setCursor(14, 3); lcd.print("  OFF "); // État actuel du relais. Prêt à être lancé avec le chronomètre (bouton rouge Start/Stop).   
    }
    delay(10); // Délais de 10 ms entre chaque pression du bouton
    // Empêche les rebonds des boutons poussoirs
    while (EtatBtn_RecordSet) EtatBtn_RecordSet = digitalRead(btn_RecordSet);
  }
  // Si EtatBtnStartStop == LOW et etatBtnPresser == 0 on exécute les actions entre {}
  if (EtatBtnStartStop == LOW && etatBtnPresser == 0) {
    etatBtnPresser = 1; // La variable etatBtnPresser prend la valeur de 1.
    EtatChronoOnOFF = !EtatChronoOnOFF; // Inverse l'EtatEtatChronoOnOFF ON ou OFF
    if((onTime >0)&& (offTime >0)){
    digitalWrite(SSR_relais, EtatChronoOnOFF);
    }
  }
  
  // Si EtatBtnStartStop == HIGH et EtatBtn_Reset == HIGH on exécute les actions entre {}
  if (EtatBtnStartStop == HIGH && EtatBtn_Reset == HIGH) {
    // La variable etatBtnPresser prend la valeur de 0.
    etatBtnPresser = 0;
  }
  
}
$abcdeabcde151015202530fghijfghij