/****************************************************************************************************************************************
    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=DOTPHtc6UtQ        *                                                                                                            *
     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>
// déclaration des variables LCD
LiquidCrystal_I2C lcd1(0x25, 20, 4), lcd2(0x26, 20, 4),  lcd3(0x27, 16, 2);

// déclaration des variables associées aux broches du contrôle joystick
const int btn_Select = 2, btn_Horz = A1, btn_Vert = A2 ;

/// déclaration des variables associées aux valeurs des positions du joystick
int select_Value, horz_Value, vert_Value;

// char msg1[20], msg2[20], msg3[20], msg4[20]; // réserve 20 espaces en mémoire tempon pour 4 variable msg de type char

int compteur_H = 0, compteur_V = 1; // variable compteur des boutons Horizontal et Vertical

// nouvelles variables
const int buzzerPin = 13; // Buzzer relié à la broche 13.
// Tableaux de chaines de caractères.
char* Menu[3] = {"Menu Principal", "Menu Secondaire", "                    "};
char* Page[11] = {"        ", " Menu 1 ", " Menu 2 ", " Menu 3 ", " Menu 4 ", " Menu 5 ", " Menu 6 ", " Menu 7 ", " Menu 8 ", " Menu 9 ", " Menu 10" };
char* P_Up[11] = {"        ", " MENU 1 ", " MENU 2 ", " MENU 3 ", " MENU 4 ", " MENU 5 ", " MENU 6 ", " MENU 7 ", " MENU 8 ", " MENU 9 ", " MENU 10 "};
char* Page2[7]  = {"        ", "Fonction 1", "Fonction 2", "Fonction 3", "Fonction 4", "Fonction 5", "Fonction 6"};
char* P_Up2[7]  = {"        ", " FONCTION 1", " FONCTION 2", " FONCTION 3", " FONCTION 4", " FONCTION 5", " FONCTION 6"};

// Tableaux de type byte pour générer des caractères spéciaux (revoir Cipad leçon 11)
byte up[8]    = { B00100, B01110, B11111, B00100, B00100, B00100, B00100, B00000}; // flèche pointe en haut. Représente le bouton vertical haut.
byte dn[8]    = { B00100, B00100, B00100, B00100, B11111, B01110, B00100, B00000}; // flèche pointe en bas. Représente le bouton vertical bas.
byte left[8]  = { B00000, B00100, B01100, B11111, B01100, B00100, B00000, B00000}; // flèche pointe à gauche. Représente le bouton horizontal gauche.
byte right[8] = { B00000, B00100, B00110, B11111, B00110, B00100, B00000, B00000}; // flèche pointe à droite. Représente le bouton horizontal droit.
byte dot[8]   = { B00000, B00100, B01110, B11111, B01110, B00100, B00000, B00000}; // point. Représente le bouton select.

// Variable Booléenne. Valeur binaire
bool Start; /* false|true, faux|vrai, lo|hi, bas|haut
                  0 | 1      0 | 1    0 | 1   0 | 1  */

void setup() { // Initialisation.
  lcd1.init(); lcd2.init(); lcd3.init();  //Initialise les 3 afficheurs LCD I2C
  lcd1.backlight(); lcd2.backlight(); lcd3.backlight(); // Active le rétroéclairage des 3 afficheurs LCD I2C
  pinMode(btn_Select, INPUT_PULLUP); // Mode INPUT_PULLUP pour le bouton central "Select"

  pinMode(buzzerPin, OUTPUT);   // définition du mode SORTIE à la broche 13.

  // Affiche un titre pendant 3 secondes
  lcdPrintCenter("Gestionnaire", 1, 0);
  lcdPrintCenter("des", 1, 1);
  lcdPrintCenter("menus", 1, 2);

  delay(3000); // pause de 3000ms (3 secondes) avant de lancer le programme.
  // Créer 5 caractères spéciaux pour lcd2
  lcd2.createChar(1, up);    // Haut.
  lcd2.createChar(2, dn);    // Bas
  lcd2.createChar(3, left);  // Gauche.
  lcd2.createChar(4, right); // Droite
  lcd2.createChar(5, dot);   // Select
}
void display_Joystick() {  // Affiche une représentation graphique du joystick tant que le bouton Select n'a pas été pressé.
  lcdPrintCenter("Utilise le joystick", 2, 0);
  lcdPrintCenter(String((char)1), 2, 1);
  lcdPrintCenter(String((char)3) + " " + String((char)5) + " " + String((char)4), 2, 2);
  lcdPrintCenter(String((char)2), 2, 3);
}
void loop() {  //Exécution: du code principal à exécuter de manière répétitive | Balaie en boucle l'état des boutons du Joystick.
  select_Value = digitalRead(btn_Select);  // lit la valeur digitale du bouton select et la communique à la variable select_Value.
  horz_Value = analogRead(btn_Horz); // lit la valeur analogique du bouton horizontal et la communique à la variable horz_Value.
  vert_Value = analogRead(btn_Vert); // lit la valeur analogique du bouton vertical et la communique à la variable vert_Value.
  delay(500); // contrôle la vitesse d'exécution du programme.
  Fn_Joystick(); // Appel de la fonction perso "Fn_Joystick" dont le rôle est d'identifier les boutons pressés.

  //Par défaut la variable booléennea Start est fausse.
  if (!Start) { //Si la variable Start est fausse...
    lcd1.noBacklight(); // Désactive le rétroéclairage de lcd1
    display_Joystick(); //Appel de la fonction display_Joystick qui affiche une représentation graphique du joystick tant que le bouton Select n'a pas été pressé...
    // ... et affiche les instructions sur lcd3 pour lancer le programme.
    lcdPrintCenter("Presse Select", 3, 0); // en pressant sur select la variable Start passe à vrai
    lcdPrintCenter("pour commencer", 3, 1);
  }
  if (Start) {// Si la variable Start est vrai...
    lcd1.backlight(); // Réactive le rétroéclairage de lcd1
    
    Fn_Select_Menu(); // appel de la fonction Fn_Select_Menu.
  }
}
void Fn_Joystick() {// Fonction permettant d'assigner une valeur pour chaque bouton du joystick

  switch (select_Value) { // commute vers la case correspondant à la valeur du bouton Select.
    case 0:   // case 0 lorsque pressé.
      lcdPrintCenter(String((char)5), 2, 2); delay(300); // affiche pendant 300ms la représentation graphique du bouton select.
      lcd1.clear(); lcd2.clear();lcd3.clear(); // Vide lcd1, lcd2 et lcd3.
      Start = true;
      break; // Quitte la case 0.

    case 1: // case 1 par défaut.
      break; // Quitte la case 1.
  } // Quitte switch(select_Value)

  switch (vert_Value) { // commute vers la case correspondant à la valeur du bouton vertical.
    case 0: // Si bouton vertical "haut" est pressé
      compteur_V--; // décrément de 1 la variable compteur_V Si bouton vertical "haut" est pressé
      lcdPrintCenter(String((char)1), 2, 1); delay(300); // affiche pendant 300ms la flèche qui pointe en haut
      lcd2.clear(); // vide lcd2
      if (compteur_V <= 1) { // Si la condition est vrai... (vérifie si compteur_V est inférieur ou égale à 1)
        compteur_V = 1; //Limite la valeur minimale de compteur_V à 1.
      } // fin de la condition if()
      break; // Quitte la case 0

    case 512: // valeur par défaut, si aucun bouton vertical n'est pressé,
      // Présentement aucune action programmée.
      break; // Quitte la case 512

    case 1023: //Si bouton vertical "bas" est pressé
      compteur_V++; // incrémente la variable compteur_V de 1
      lcdPrintCenter(String((char)2), 2, 3); delay(300); // affiche pendant 300ms la flèche qui pointe en bas.
      lcd2.clear(); // vide lcd2
      if (compteur_V >= 10) { // Si la condition est vrai... (vérifie si compteur_V est supérieur ou égale à 10)
        compteur_V = 10; //Limite la valeur maximale de compteur_V à 10.
      } // fin de la condition if()
      break; // Quitte la case 1023
  } // Quitte switch (vert_Value)

  switch (horz_Value) { // commute vers la case correspondant à la valeur du bouton Horizontal.
    case 0:  // Si pressé Gauche affiche "Gauche" à gauche de la 3e ligne
      lcdPrintCenter(String((char)3) + "  ", 2, 2); delay(300); // affiche pendant 300ms la flèche qui pointe à gauche.
      compteur_H--; // décrémente de 1 la variable compteur_H si le bouton horizontal gauche est pressé.
      lcd1.clear(); lcd2.clear(); lcd3.clear(); // vide lcd1 lcd2 et lcd3
      compteur_V = 1; // Remet la valeur de la variable compteur_V à 1 à chaque changement du menu principal au menu secondaire et vice versa.
      if (compteur_H <= 0) { // Si la condition est vrai... (vérifie si compteur_H est inférieur ou égale à 0)
        compteur_H = 0; // Limite la valeur minimale de compteur_H à 0.
      }
      Fn_Select_Menu(); // Appele la fonction Fn_Select_Menu()
      break; // Quitte la case 0

    case 512: //delay(500);  // si aucun bouton pressé efface la 3e ligne
      // Présentement aucune action programmée.
      break; // Quitte la case 512

    case 1023: // Si pressé Droite affiche "Droite" à droite de la 3e ligne
      lcdPrintCenter(" " + String((char)4), 2, 2); delay(300);// affiche pendant 300ms la flèche qui pointe à droite
      compteur_H++; // Incrémente de 1 la variable compteur_H (si le bouton horizontal droite est pressé)
      lcd1.clear(); lcd2.clear(); lcd3.clear(); // vide lcd1 lcd2 et lcd3
      compteur_V = 1; // Remet la valeur de la variable compteur_V à 1 à chaque changement du menu principal au menu secondaire et vice versa.
      if (compteur_H >= 1) { // Si la condition est vrai... (vérifie si compteur_H est supérieur ou égale à 10)
        compteur_H = 1; //Limite la valeur maximale de compteur_H à 10.
      } // fin de la condition if()
      Fn_Select_Menu();// Appele la fonction Fn_Select_Menu()
      break; // Quitte la case 1023
  }  // quitte switch (horz_Value)
}
void Fn_Select_Menu() { // Permet de passer du menu principal au menu secondaire.
  switch (compteur_H) { // Commute du menu principal au menu secondaire et vice versa.
    case 0: Fn_MenuPrincipal(); break; // Appele la fonction Fn_MenuPrincipal()
    case 1: Fn_MenuSecondaire(); break;// Appele la fonction Fn_MenuSecondaire()
  }
}
void Fn_MenuPrincipal() { // Fonction d'affichage du choix des pages du menu principal. Permet de naviguer parmi les 10 pages de menus disponibles dans le menu principal.
  /* Commutateur de navigation entre les 10 pages de menu disponibles.
    La navigation de haut en bas se fait (pas à pas) en pressant sur le bouton "vertical bas" ou (consécutivement) en le maintenant pressé.
    Et de bas en haut (pas à pas) en pressant sur le bouton "vertical haut" ou (consécutivement) en le maintenant pressé.
  */
  lcdPrintCenter(Menu[0], 1, 0);
  switch (compteur_V) { // Commutateur de navigation entre les 10 pages de menus disponibles. Chaque case place en majuscules le titre du menu sélectionné.
    case 1: // affiche les 3 premiers titres du menu principal

      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up[1], 1, 1); lcdPrintRight("<-", 1, 1); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[2], 1, 2); lcdPrintRight("  ", 1, 2); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[3], 1, 3); lcdPrintRight("  ", 1, 3); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      break;

    case 2:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[1], 1, 1); lcdPrintRight("  ", 1, 1); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("->", 1, 2); lcdPrintCenter(P_Up[2], 1, 2); lcdPrintRight("<-", 1, 2); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[3], 1, 3); lcdPrintRight("  ", 1, 3); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      break;

    case 3:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[1], 1, 1); lcdPrintRight("  ", 1, 1); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[2], 1, 2); lcdPrintRight("  ", 1, 2); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("->", 1, 3); lcdPrintCenter(P_Up[3], 1, 3); lcdPrintRight("<-", 1, 3); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      break;

    case 4: // affiche les 3 titres suivant du menu principal.
      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up[4], 1, 1); lcdPrintRight("<-", 1, 1); // Ligne 1 sélectionnée
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[5], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[6], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 5:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[4], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("->", 1, 2); lcdPrintCenter(P_Up[5], 1, 2); lcdPrintRight("<-", 1, 2); // Ligne 2 sélectionnée
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[6], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 6:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[4], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[5], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("->", 1, 3); lcdPrintCenter(P_Up[6], 1, 3); lcdPrintRight("<-", 1, 3); // Ligne 3 sélectionnée
      break;

    case 7: // affiche les 3 titres suivant du menu principal.
      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up[7], 1, 1); lcdPrintRight("<-", 1, 1); // Ligne 1 sélectionnée
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[8], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[9], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 8:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[7], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("->", 1, 2); lcdPrintCenter(P_Up[8], 1, 2); lcdPrintRight("<-", 1, 2); // Ligne 2 sélectionnée
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page[9], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 9:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page[7], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page[8], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("->", 1, 3); lcdPrintCenter(P_Up[9], 1, 3); lcdPrintRight("<-", 1, 3); // Ligne 3 sélectionnée

      switch (select_Value) {
        case 1: // Affiche
          lcdPrintCenter("Alarm test", 2, 1);
          lcdPrintCenter("Press Select", 2, 3);
          break;
        case 0:
          Alarm();
          break;
      }
      break;

    case 10: // affiche le dernier titre du menu principal.

      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up[10], 1, 1); lcdPrintRight("<-", 1, 1); // Ligne 1 sélectionnée
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Menu[2], 1, 2); lcdPrintRight("  ", 1, 2);  // vide la ligne 2
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Menu[2], 1, 3); lcdPrintRight("  ", 1, 3);  // vide la ligne 3
      // Affiche des instructionspour revenir directement à la page 1 du menu principal.

      lcdPrintCenter("Fin du menu", 2, 1); // indique qu'on est à la dernière page
      lcdPrintCenter("For Menu #1", 2, 2); // instrcutions
      lcdPrintCenter("Press Select", 2, 3);// instrcutions
      beep();  // Émet une tonalité de 2,5kHz pendant 100 ms à répétition tant qu'on demeure sur cette page
      lcdPrintCenter("Press Select", 3, 0); // affiche les instructions...
      lcdPrintCenter("Return to Menu 1", 3, 1); //... pour revenir directement à la page 1 du menu principal.

      delay(250); lcd3.clear(); // Fait clignoter le texte de LCD3
      if (!select_Value) {
        lcd2.clear(); // vide lcd2
      }
      break;
  }
  lcdPrintCenter(String(Page[compteur_V]) + "de 10", 2, 0); // Affiche en entête de lcd2 le menu sélectionné.
}
void Fn_MenuSecondaire() {// Fonction d'affichage du choix des pages du menu Secondaire. Permet de naviguer parmi les 6 pages de fonctions disponibles dans le menu secondaire.

  lcdPrintCenter(Menu[1], 1, 0);

  if (compteur_V > 6) {
    compteur_V = 6; //Limite la valeur maximale de la variable compteur_V à 6
  }
  /* Commutateur de navigation entre les 6 pages de fonctions disponibles.
     La navigation de haut en bas se fait (pas à pas) en pressant sur le bouton "vertical bas" ou (consécutivement) en le maintenant pressé.
     Et de bas en haut (pas à pas) en pressant sur le bouton "vertical haut" ou (consécutivement) en le maintenant pressé.
  */
  switch (compteur_V) { // Commutateur de navigation entre les 6 pages de fonctions disponibles. Chaque case place en majuscules le titre de la fonction sélectionné.
    case 1: // affiche les 3 premiers titres du menu principal

      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up2[1], 1, 1); lcdPrintRight("<-", 1, 1); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page2[2], 1, 2); lcdPrintRight("  ", 1, 2); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page2[3], 1, 3); lcdPrintRight("  ", 1, 3); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      break;
    case 2:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page2[1], 1, 1); lcdPrintRight("  ", 1, 1); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("->", 1, 2); lcdPrintCenter(P_Up2[2], 1, 2); lcdPrintRight("<-", 1, 2); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page2[3], 1, 3); lcdPrintRight("  ", 1, 3); // efface le pointeur; Affiche le titre de la page suivante; efface le pointeur;
      break;

    case 3:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page2[1], 1, 1); lcdPrintRight("  ", 1, 1); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page2[2], 1, 2); lcdPrintRight("  ", 1, 2); // efface le pointeur; Affiche le titre de la page précédante; efface le pointeur;
      lcdPrintLeft("->", 1, 3); lcdPrintCenter(P_Up2[3], 1, 3); lcdPrintRight("<-", 1, 3); // pointe à droite; Place la page sélectionnée en majuscule; pointe vers la gauche.
      break;

    case 4: // affiche les 3 titres suivant du menu principal.
      lcdPrintLeft("->", 1, 1); lcdPrintCenter(P_Up2[4], 1, 1); lcdPrintRight("<-", 1, 1); // Ligne 1 sélectionnée
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page2[5], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page2[6], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 5:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page2[4], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("->", 1, 2); lcdPrintCenter(P_Up2[5], 1, 2); lcdPrintRight("<-", 1, 2); // Ligne 2 sélectionnée
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Page2[6], 1, 3); lcdPrintRight("  ", 1, 3);
      break;

    case 6:
      lcdPrintLeft("  ", 1, 1); lcdPrintCenter(Page2[4], 1, 1); lcdPrintRight("  ", 1, 1);
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Page2[5], 1, 2); lcdPrintRight("  ", 1, 2);
      lcdPrintLeft("->", 1, 3); lcdPrintCenter(P_Up2[6], 1, 3); lcdPrintRight("<-", 1, 3); // Ligne 3 sélectionnée
      break;
  }
  lcdPrintCenter(String(Page2[compteur_V]) + " de 6", 2, 0); // Affiche en entête de lcd2 la fonction sélectionné.
}
void beep() {   // Émet une tonalité de 2,5kHz pendant 100 ms
  if (select_Value == 0) { // Si le bouton Select est pressé
    compteur_V = 1;  //Réinitialise la variable compteur_V à 1
    Fn_Select_Menu(); // Rafraîchi lcd1.
  }
  tone(buzzerPin, 2500, 100);  //Émet un son à 2,5 kHz pendant 100 ms
}
void Alarm() {  // Fonction d'Alarme ou réveil matin
  lcd3.clear(); lcdPrintCenter("*** ALARM ***", 3, 0); // Affiche l'état de l'alarme
  lcdPrintCenter("*** ON TEST ***", 3, 1);
  for (int repeat = 0; repeat <= 10; ++repeat) { // répète les 2 tonalitéd 10 fois chaque avant de se taire
    tone(buzzerPin, 800, 300); delay(200);        // Émet une tonalité de 800Hz pendant 300 ms, suivi d'une interruption de 200ms
    tone(buzzerPin, 500, 300); delay(200);        // Émet une tonalité de 500Hz pendant 300 ms, suivi d'une interruption de 200ms
    for (int flash = 0; flash <= 10; ++flash) {   // Fait clignoter le rétroéclairage de l'afficheur lcd par interval de 100ms.
      lcd3.noBacklight();
    }
    delay(100);
    lcd3.backlight();                              // rétabli le rétroéclairage de l'afficheur lcd.
  }
  lcd3.clear();
  lcdPrintCenter("END OF TEST", 3, 0);
  lcdPrintCenter("Alarm OK!", 3, 1);
  delay(2000);
  lcd3.clear();
}
/***********************************************************************************
  Fonction lcdPrintCenter(1er paramètre, 2e paramètre, 3e paramètre).
  Fonction lcdPrintCenter(texte à afficher, choix de l'écran lcd, No de la ligne).
 **********************************************************************************/
void lcdPrintCenter(String texte, int lcd, int ligne) {
  // texte.length(); // Défini la longeur de la variable "texte"
  switch (lcd) { // Commute vers l'afficheur correspondant à la variable "lcd"
    case 1: // Sélectionne lcd1.
      lcd1.setCursor((20 - texte.length()) / 2, ligne);  // positionne le curseur au centre de la ligne choisie et soustrait la longeur du text à afficher
      lcd1.print(texte);  // Affiche le texte demandé sur lcd1.
      break; // Quitte la case 1
    case 2:  // Sélectionne lcd2.
      lcd2.setCursor((20 - texte.length()) / 2, ligne);  // positionne le curseur au centre de la ligne choisie et soustrait la longeur du text à afficher
      lcd2.print(texte); // Affiche le texte demandé sur lcd2.
      break; // Quitte la case 2
    case 3: // Sélectionne lcd3.
      lcd3.setCursor((16 - texte.length()) / 2, ligne);  // positionne le curseur au centre de la ligne choisie et soustrait la longeur du text à afficher
      lcd3.print(texte); // Affiche le texte demandé sur lcd3.
      break; // Quitte la case 3
  }  // Quitte la fonction switch.
}  // Quitte la fonction lcdPrintCenter(texte à afficher, choix de l'écran lcd, No de la ligne).
/***********************************************************************************
  Fonction lcdPrintLeft(1er paramètre, 2e paramètre, 3e paramètre).
  Fonction lcdPrintLeft(texte à afficher, choix de l'écran lcd, No de la ligne).
 **********************************************************************************/
void lcdPrintLeft(String texte, int lcd, int ligne) {
  switch (lcd) { // Commute vers l'afficheur correspondant à la variable "lcd"
    case 1: // Sélectionne lcd1.
      lcd1.setCursor(0, ligne);  // positionne le curseur à gauche de la ligne choisie
      lcd1.print(texte);  // Affiche le texte demandé sur lcd1.
      break; // Quitte la case 1
    case 2:  // Sélectionne lcd2.
      lcd2.setCursor(0, ligne);  // positionne le curseur à gauche de la ligne choisie
      lcd2.print(texte); // Affiche le texte demandé sur lcd2.
      break; // Quitte la case 2
    case 3: // Sélectionne lcd3.
      lcd3.setCursor(0, ligne);  // positionne le curseur à gauche de la ligne choisie
      lcd3.print(texte); // Affiche le texte demandé sur lcd3.
      break; // Quitte la case 3
  }  // Quitte la fonction switch.
} // Quitte la fonction lcdPrintLeft(texte à afficher, choix de l'écran lcd, No de la ligne).
/***********************************************************************************
  Fonction lcdPrintRight(1er paramètre, 2e paramètre, 3e paramètre).
  Fonction lcdPrintRight(texte à afficher, choix de l'écran lcd, No de la ligne).
 **********************************************************************************/
void lcdPrintRight(String texte, int lcd, int ligne) {
  // texte.length() Défini la longeur de la variable "texte"
  switch (lcd) { // Commute vers l'afficheur correspondant à la variable "lcd"
    case 1: // Sélectionne lcd1.
      lcd1.setCursor(20 - texte.length(), ligne); // positionne le curseur à 20 de la ligne choisie et soustrait la longeur du text à afficher
      lcd1.print(texte);  // Affiche le texte demandé sur lcd1.
      break; // Quitte la case 1
    case 2:  // Sélectionne lcd2.
      lcd2.setCursor(20 - texte.length(), ligne);  // positionne le curseur à 20 de la ligne choisie et soustrait la longeur du text à afficher
      lcd2.print(texte); // Affiche le texte demandé sur lcd2.
      break; // Quitte la case 2
    case 3: // Sélectionne lcd3.
      //int displayCharLength = 16;
      // int offset = (displayCharLength - texte.length());
      lcd3.setCursor(16 - texte.length(), ligne);  // positionne le curseur à 16 de la ligne choisie et soustrait la longeur du text à afficher
      lcd3.print(texte); // Affiche le texte demandé sur lcd3.
      break; // Quitte la case 3
  }  // Quitte la fonction switch.
} // Quitte la fonction lcdPrintRight(texte à afficher, choix de l'écran lcd, No de la ligne).























$abcdeabcde151015202530354045505560fghijfghij