/****************************************************************************************************************************************
    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://youtu.be/8IkcWgwLTrs                                  *                                                                                                            *
     ou celui-ci pour accéder à toutes les leçons déjà publiées...
    https://www.youtube.com/playlist?list=PLoffRtP427acSg1FbpFuH_g5ptz-aovFN
*                                                                                                                                        *
 ****************************************************************************************************************************************/

/**** ENTÊTE DÉCLARATIVE ***/

#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;
int compteur_H = 1, compteur_V = 1; // variable compteur des boutons Horizontal et Vertical
const int buzzerPin = 13; // Buzzer relié à la broche 13.

// nouvelles variables
char msg1[20], msg2[20], msg3[20], msg4[20]; // réserve 20 espaces en mémoire tempon pour 4 variable msg de type char
char* note[] = {"Do", "Re", "Mi", "Fa", "Sol", "La", "Si", "Do", "Do", "Si", "La", "Sol", "Fa", "Mi", "Re", "Do"};
int melody[] = {262, 294, 330, 349, 392, 440, 494, 523, 523, 494, 440, 392, 349, 330, 294, 262};

// Tableaux de chaines de caractères.
char* Menu[] = {"                    ",  // Menu[index 0]
                "Menu Principal",        // Menu[index 1]
                "Menu Secondaire",       // Menu[index 2]
               };

// nom du tableau[index 0]  , [index 1],  [index 2] , [index 3] , [index 4] , [index 5] ,[index 6]  , [index 7] , [index 8] , [index 9] , [index 10];
char* Page[] = {"               ",
                "Menu 1 ",
                "Menu 2 ",
                "Menu 3 ",
                "Menu 4 ",
                "Menu 5 ",
                "Menu 6 ",
                "Menu 7 ",
                "Menu 8 ",
                "Menu 9 ",
                "Menu 10"
               };

char* Page2[7] = {"               ",
                  " Fonction Tone ",
                  "Jouer la Gamme",
                  "  Fonction 3   ",
                  "  Fonction 4   ",
                  "  Fonction 5   ",
                  "  Fonction 6   "
                 };

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(1000); // pause de 1000ms (1 seconde) avant de lancer le programme.
}

void loop() {  //Exécution: du code principal à exécuter de manière répétitive | Balaie en boucle l'état des boutons du Joystick.
  Fn_Joystick(); // Appel de la fonction perso "Fn_Joystick" dont le rôle est d'identifier les boutons pressés.
  // ---> 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
  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(250); // contrôle la vitesse d'exécution du programme.(temporisation)

  /*************** Action du bouton Select ***********************************************/
  if (select_Value == 0) {
    lcd123clear(); // Vide lcd1, lcd2 et lcd3.
  } // Quitte if(select_Value) .

  /*************** Action du bouton vertical *********************************************/
  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é
      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 1023: //Si bouton vertical "bas" est pressé
      compteur_V++; // incrémente la variable compteur_V de 1
      lcd2.clear(); // vide lcd2
      break; // Quitte la case 1023
  } // Quitte switch (vert_Value)

  /*************** Action du bouton Horizontal********************************************/
  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
      compteur_H--; // décrémente de 1 la variable compteur_H si le bouton horizontal gauche est pressé.
      lcd123clear(); // 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 inférieur ou égale à 0)
        compteur_H = 1; // Limite la valeur minimale de compteur_H à 0.
      }
      Fn_Select_Menu(); // Appele la fonction Fn_Select_Menu()
      break; // Quitte la case 0

    case 1023: // Si pressé Droite affiche "Droite" à droite de la 3e ligne
      compteur_H++; // Incrémente de 1 la variable compteur_H (si le bouton horizontal droite est pressé)
      lcd123clear(); // 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 >= 2) { // Si la condition est vrai... (vérifie si compteur_H est supérieur ou égale à 10)
        compteur_H = 2; //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 lcd123clear() { // vide lcd1 lcd2 et lcd3
  lcd1.clear(); lcd2.clear(); lcd3.clear();
}
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 1: Fn_MenuPrincipal(); break; // Appele la fonction Fn_MenuPrincipal()
    case 2: 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é.
  */
  // Limite la valeur de la variable compteur_V au nombre de pages contenues dans le menu principal.
  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()

  lcdPrintCenter(Menu[1], 1, 0); // Affiche le titre du menu en cours en entête de lcd1.

  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(Page[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(Page[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(Page[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(Page[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(Page[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(Page[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(Page[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(Page[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(Page[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(Page[10], 1, 1); lcdPrintRight("<-", 1, 1); // Ligne 1 sélectionnée
      lcdPrintLeft("  ", 1, 2); lcdPrintCenter(Menu[0], 1, 2); lcdPrintRight("  ", 1, 2);  // vide la ligne 2
      lcdPrintLeft("  ", 1, 3); lcdPrintCenter(Menu[0], 1, 3); lcdPrintRight("  ", 1, 3);  // vide la ligne 3

      // Affiche des instructions pour 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); // instructions
      lcdPrintCenter("Press Select", 2, 3);// instructions
      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) { // si
        lcd2.clear(); // vide lcd2
        lcd1.clear();
      }
      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[2], 1, 0); // Affiche le titre du menu en cours en entête de lcd1.
  if (compteur_V >= 6) {// Limite la valeur de la variable compteur_V au nombre de pages contenues dans le menu Secondaire.
    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(Page2[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;
      switch (select_Value) {
        case 1: // Affiche
          lcdPrintCenter("Tone test", 2, 2);
          lcdPrintCenter("Press Select", 2, 3);
          break;
        case 0:
          PlayTone();
          break;
      }
      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(Page2[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;
      switch (select_Value) {
        case 1: // Affiche
          lcdPrintCenter("Jouer la gamme", 2, 2);
          lcdPrintCenter("Press Select", 2, 3);
          break;
        case 0:
          PlayGamme();
          break;
      }
      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(Page2[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(Page2[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(Page2[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(Page2[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();                         // désactive le rétroéclairage de lcd3
    }
    delay(100);                                   // Vitesse du clignotement
    lcd3.backlight();                             // rétabli le rétroéclairage de l'afficheur lcd3.
  }
  lcd3.clear();                                   // vide momentamnément lcd3
  lcdPrintCenter("END OF TEST", 3, 0);            // rétabli ce message sur la ligne 0 de lcd3
  lcdPrintCenter("Alarm OK!", 3, 1); delay(2000); // rétabli ce message sur la ligne 1 de lcd3 pendant 2 secondes.
  lcd3.clear();                                   // Vide lcd3.
}


void PlayTone() {
  lcd3.clear(); lcdPrintCenter("*** Tone ***", 3, 0); // Affiche l'état de l'alarme
  lcdPrintCenter("*** ON TEST ***", 3, 1);

  unsigned long duree = 500;

  for (unsigned long freq = 31; freq <= 2011; freq = freq + 10) {
    select_Value = digitalRead(btn_Select); lcdPrintRight(String(select_Value), 1, 0);     
//  tone(pin,frequency,duration) Syntaxe
    tone(buzzerPin, freq, duree); delay(50);    
    lcdPrintCenter("Frequence", 2, 0);
    lcdPrintCenter(String(freq) + "Khz", 2, 1);
    lcdPrintCenter("Fonction tone()", 2, 2);
    lcdPrintCenter("tone(pin," + String(freq) + "," + String(duree) + ")", 2, 3);
  }
  delay(500);
  lcd2.clear();lcd3.clear();
}
void PlayGamme() {
  int speed =500;
  int duree =500;
  for (int i = 0; i < 16; i++) {
    sprintf(msg1, "Note:%3s", note[i]);
    sprintf(msg2, "Frequency: %3dHz", melody[i]);
    lcdPrintCenter(msg1, 2, 0);
    lcdPrintLeft(msg2, 2, 1);
    tone(buzzerPin, melody[i], duree);
    delay(speed);
    noTone(buzzerPin);
    delay(speed);
  }
}

/***********************************************************************************
  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