/****************************************************************************************************************************************
   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], MinuteurSET[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 heures_OFF = 0, heures_ON = 0;
long minutes_OFF = 0, minutes_ON = 0;
long secondes_OFF = 0, secondes_ON = 0;
long TempsEcoule;
long Milliseconde, Seconde, Minute, Heure;
unsigned long currentTime = 0, previousTime = 0;
unsigned long startMillis, currentMillis;
long period = 5000;
int Record, etatRecordON, etatRecordOFF, Start;
bool etatRecord = false;
bool TimeRecordON = false;
bool TimeRecordOFF = false;

unsigned long Pot_Set_Heure = A0;
unsigned long Pot_Set_Minute = A1;
unsigned long Pot_Set_Seconde = A2;
long Set_Heure_Value, Set_Minute_Value, Set_Seconde_Value;
long Heure_Value, Minute_Value, Seconde_Value;


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);
  pinMode(Pot_Set_Heure, INPUT);
  pinMode(Pot_Set_Minute, INPUT);
  pinMode(Pot_Set_Seconde, INPUT);


  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_RecordSet = digitalRead(btn_RecordSet);

  EtatBtn_Set_TimeON = digitalRead(btn_Set_TimeON);
  EtatBtn_Set_TimeOFF = digitalRead(btn_Set_TimeOFF);
  /*
    Set_Heure_Value = map( analogRead(Pot_Set_Heure),    -1, 1023, 0, 24);
    Set_Minute_Value = map(analogRead(Pot_Set_Minute),  -1, 1023, 0, 59);
    Set_Seconde_Value = map(analogRead(Pot_Set_Seconde), -1, 1023, 0, 59);
    ///Set_Minuteur();
    //Heure_Value = map(Set_Heure_Value, 0, 1023, 0, 24);
    /*
      lcd.setCursor(17, 0);  lcd.print(Set_Heure_Value);
      lcd.setCursor(17, 1);  lcd.print(Set_Minute_Value);
      lcd.setCursor(17, 2);  lcd.print(Set_Seconde_Value);
  */

  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 Set_Minuteur() {
  Set_Heure_Value = map( analogRead(Pot_Set_Heure),    -1, 1023, 0, 24);
  Set_Minute_Value = map(analogRead(Pot_Set_Minute),   -1, 1023, 0, 59);
  Set_Seconde_Value = map(analogRead(Pot_Set_Seconde), -1, 1023, 0, 59);
}

void fn_display() {
  sprintf(MinuteurON,  "ON :%02ld:%02ld:%02ld", Set_Heure_Value, Set_Minute_Value, Set_Seconde_Value); //Formate l'affichage.
  sprintf(MinuteurOFF, "OFF:%02ld:%02ld:%02ld", H_OFF, 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 ((!etatRecord) && (MyTimeON == 0)) {
      //lcd.setCursor(1,2);lcd.blink();
    }
  //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;
  }

}
$abcdeabcde151015202530354045505560fghijfghij