Creation d'un menu avec LCD et boutons

Bonjour,
Je suis tout nouveau sur votre forum, j'ai les connaissances de base dans le langage Arduino et j'essaie de faire un menu avec un LCD 4*20 et quelques boutons mais j'ai bien des soucis : Ce que je pensai simple au départ s'averre plus compliqué.
Je voudrai faire un menu avec 7 entrées, qui, quand on sélectionne l'une d'elle, on arrive sur un choix de sous-menu(en option), puis en validant l'un d'entre eux , on active un programme( j'ai écris les différents programmes qui animent le décor d'une maquette de train et, eux, fonctionnent bien).
J'ai fait un switch d'une variable(pointeurMenu)incrémentée par deux boutons et dans chaque case, j'indique au LCD son affichage.
Pour chacune des pages, des flèches indiquent les directions à prendre: ^:haut, v:bas, >:droite,<:gauche .
Mais l'affichage est déplorable, ça clignote très vite et toute la page ne s'affiche pas.
Par contre, si je mets une valeur dans pointeurMenu qui ne correspond pas à une case, là, l'afficheur devient stable et affiche correctement la page.
Je joints mon code, si quelqu'un a une idée, elle serait le bien venue...

#include <LiquidCrystal.h>                  //Bibliothèque pour gérer le LCD
#include <RBD_Timer.h>                      // Bibliothèque pour gérer les boutons
#include <RBD_Button.h>

RBD::Button boutonHaut(A5, true);          //Déclaration des boutons
RBD::Button boutonBas(A4, true);
RBD::Button boutonDroit(A2, true);
RBD::Button boutonGauche(A1, true);
RBD::Button boutonValidation(A3, true);
bool OK = boutonValidation.onPressed();    // Bouléen pour valider les programmes
#define   CONTRAST_PIN   9
#define   BACKLIGHT_PIN  7
#define   CONTRAST       110

LiquidCrystal lcd(12,11,5,4,3,2,BACKLIGHT_PIN, POSITIVE);


byte pointeurMenu = 0;                         //Variable indiquant les pages du menu
const byte valeurMin=0;                       // Valeur minimum du pointeurMenu
const byte valeurMax=70;                       // Valeur maximum du pointeurMenu
byte programme;
byte PWMleds = 125;
byte PWMhalogene = 125;
byte PWMleds1 = 250;
byte PWMhalogene1 = 250;

unsigned long dernierClic = 0;
/************************************LIRE LES BOUTONS*********************************************/
void lireBouton() {

  if (millis()-dernierClic>=200) {
    if(boutonBas.onPressed()) {
      if(pointeurMenu<valeurMax){pointeurMenu = pointeurMenu+10;}
      dernierClic = millis();
    }
    else if(boutonHaut.onPressed()) {
      if(pointeurMenu>valeurMin){pointeurMenu = pointeurMenu-10;}
      dernierClic = millis();   
    }
    else if(boutonDroit.onPressed()) {
      pointeurMenu = pointeurMenu+1;
      dernierClic = millis();
    }
    else if(boutonGauche.onPressed()) {
      pointeurMenu = pointeurMenu-1;
      dernierClic = millis();
    }
    
  }
}
/***************************************PANNEAU D'ACCEUIL***************************************/
void acceuil() {

  lcd.clear();
  lcd.print("GARE DE CHATEAUVIEUX");
  lcd.setCursor(0,2);
  lcd.print("    ANNEES 60...    ");
  lcd.setCursor(0,3);
  lcd.print("V                  V");

}
/*****************************************MISE EN ROUTE*****************************************/
void miseEnRoute() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,1);
  lcd.print("                   >");
  lcd.setCursor(0,2);
  lcd.print("   MISE EN ROUTE    ");
  lcd.setCursor(0,3);
  lcd.print("v                  v");
  }
/*********************************MISE EN ROUTE Sous-Menu UN************************************/
void miseEnRouteUn() {
  lcd.clear();
  lcd.print("    CHATEAUVIEUX    ");
  lcd.setCursor(0,1);
  lcd.print("<                  >");
  lcd.setCursor(0,2);
  lcd.print("   SOU-MENU:   ");
  lcd.setCursor(0,3);
  lcd.print("  HALOGENE:");
  lcd.setCursor(13,3);
  lcd.print(PWMhalogene);
}
/********************************MISE EN ROUTE Sous-Menu DEUX************************************/
void miseEnRouteDeux() {
  lcd.clear();
  lcd.print("    CHATEAUVIEUX    ");
  lcd.setCursor(0,1);
  lcd.print("<                  >");
  lcd.setCursor(0,2);
  lcd.print("REGLAGE LEDS:");
  lcd.setCursor(13,2);
  lcd.print(PWMleds);
}
/******************************************MAINTENANCE******************************************/
void maintenance() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,1);
  lcd.print("                   >");
  lcd.setCursor(0,2);
  lcd.print("     MAINTENANCE    ");
  lcd.setCursor(0,3);
  lcd.print("v                  v");
}
/******************************************MAINTENANCE SouMenu UN******************************************/
void maintenanceUn() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,1);
  lcd.print("<                  >");
  lcd.setCursor(0,2);
  lcd.print("Halogènes:");
  lcd.setCursor(13,2);
  lcd.print(PWMhalogene1);
}
/*************************************MAINTENANCE SouMenu Deux************************************/
void maintenanceDeux() {
  lcd.clear();
  lcd.print("    CHATEAUVIEUX    ");
  lcd.setCursor(0,1);
  lcd.print("<                  >");
  lcd.setCursor(0,2);
  lcd.print("REGLAGE LEDS:");
  lcd.setCursor(13,2);
  lcd.print(PWMleds1);
}

/**************************************ESSAI DES ECLAIRAGES*************************************/
void essaiEclairage() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,2);
  lcd.print("  ESSAI ECLAIRAGE   ");
  lcd.setCursor(0,3);
  lcd.print("v                  v");
}

/*****************************************JOURNEE D'ETE*****************************************/
void jourEte() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,2);
  lcd.print("   JOURNEE D'ETE    ");
  lcd.setCursor(0,3);
  lcd.print("v                  v");
}

/********************************************HIVER**********************************************/
void hiver() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,2);
  lcd.print("    DANS LE FROID   ");
  lcd.setCursor(0,3);
  lcd.print("v    DE L'HIVER    v");
}

/*****************************************JOUR ET NUIT******************************************/
void jourNuit() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,2);
  lcd.print("    JOUR ET NUIT    ");
  lcd.setCursor(0,3);
  lcd.print("v                  v");
}

/*****************************************NUIT FESTIVE******************************************/
void nuitFestive() {
  lcd.clear();
  lcd.print("^   CHATEAUVIEUX   ^");
  lcd.setCursor(0,2);
  lcd.print("    NUIT FESTIVE    ");
}


/****************************************INITIALISATION*****************************************/
void setup() {
  pinMode(CONTRAST_PIN, OUTPUT);
  analogWrite ( CONTRAST_PIN, CONTRAST );
  lcd.begin(20,4);
  lcd.backlight();
  Serial.begin(9600);
}
/****************************************BOUCLE*************************************************/
void loop() {
  Serial.println(pointeurMenu);
  lireBouton();
  switch (pointeurMenu) {
    case 0 : acceuil();
    break;
    case 10 : miseEnRoute();if(OK){programme =1;}
    break;
    case 11 : miseEnRouteUn();                      // Sous-Menu1 du programme 1
    break;
    case 12 : miseEnRouteDeux();                    // Sous-Menu2 du programme 1
    break;
    case 20 : maintenance();if(OK){programme =2;}
    break;
    case 21 : maintenanceUn();
    break;
    case 22 : maintenanceDeux();
    break;
    case 30 : essaiEclairage();if(OK){programme =3;}
    break;
    case 40 : jourEte();if(OK){programme =4;}
    break;
    case 50 : hiver();if(OK){programme =5;}
    break;
    case 60 : jourNuit();if(OK){programme =6;}
    break;
    case 70 : nuitFestive();if(OK){programme =7;}
    break;
    default : pointeurMenu = 0; 
  }
}

bonjour,
un peu normal, dans chaque void tu mets un lcd.clear
donc ca tourne en boucle avec un clear et tu n'as pas le temps de tout voir.
vire les lcd.clear() dans chaque void du menu et mets le dans ton case

 case 0 : 
lcd.clear();
acceuil();
    break;

Merci pour cette réponse facile, j'essaie dés que possible...
Cà parait si simple, et dire que j'ai cherché longtemps...

Hello,

A mon sens, cela ne changera rien...
Faire le lcd.clear() avant l'appel à Accueil() ou pendant ne change rien. Cela clignotera tout autant.

Le problème est que le code boucle et met à jour l'affichage même si l'utilisateur ne s'est pas déplacé...

Une solution serait de garder la valeur précédente de PointeurMenu. (AncienPointeurMenu par exemple)
Si PointeurMenu est différent de AncienPointeurMenu alors

  • On copie PointeurMenu dans AncienPointeurMenu. (Il deveint la nouvelle référence)
  • On passe dans le switch() pour mettre le menu à jour puisque qu'il y a eu un changement...
void loop() {
  Serial.println(pointeurMenu);
  lireBouton();
  if( pointeurMenu != ancienPointeurMenu ) {
    ancienPointeurMenu = pointeurMenu;
    switch (pointeurMenu) {
      case 0 : acceuil();
      break;
      case 10 : miseEnRoute();if(OK){programme =1;}
      break;
      case 11 : miseEnRouteUn();                      // Sous-Menu1 du programme 1
      break;
   ....
    }
  }
}

Voilà... C'est une piste, il y en a d'autres...

Coyotte

effectivement, ça ne marche pas mieux avec lcd.clear() dans case. Mais, du coup, j'ai pu voir que le problème venait de cette fonction. J'ai réécrits mon code en la supprimant : Assez facile en écrivant des
" " sur les mots qui doivent disparaitre. Côté affichage, maintenant, ça va. J'ai aussi modifier le switch(pointeurMenu):
j'ai créé une deuxième variable(pointeurSousMenu) qui gère l'affichage des sous-menus.

void loop() {
//  Serial.println(pointeurMenu);
//  Serial.println(pointeurSousMenu);
  lireBouton();

  if((pointeurMenu==0)&&(pointeurSousMenu==0)){acceuil();}
  else if((pointeurMenu==1)&&(pointeurSousMenu==0)){miseEnRoute();}
  else if((pointeurMenu==1)&&(pointeurSousMenu==1)){sousMenu1();}
  else if((pointeurMenu==1)&&(pointeurSousMenu==2)){sousMenu2();}
  else if((pointeurMenu==2)&&(pointeurSousMenu==0)){maintenance();}
  else if((pointeurMenu==2)&&(pointeurSousMenu==1)){sousMenu3();}
  else if((pointeurMenu==2)&&(pointeurSousMenu==2)){sousMenu4();}
  else if((pointeurMenu==3)&&(pointeurSousMenu==0)){essaiEclairage();}
  else if(pointeurMenu==4){jourEte();}
  else if(pointeurMenu==5){hiver();}
  else if(pointeurMenu==6){jourNuit();}
  else if(pointeurMenu==7){nuitFestive();}
}

Maintenant je cherche comment incrémenter les variables dans mes sous-menus à l'aide des boutons existants.
Par exemple : dans sous menu 1 comment incrémenter ma variable PWMhalogene à l'aide de boutonDroit et boutonGauche puis OK.

/*********************************MISE EN ROUTE Sous-Menu UN************************************/
void sousMenu1() {
  lcd.setCursor(18,0);
  lcd.print(" ");
  lcd.setCursor(19,1);
  lcd.print(">");
  lcd.setCursor(17,1);
  lcd.print("<");
  lcd.setCursor(18,2);
  lcd.print(" ");
  lcd.setCursor(18,1);
  lcd.print(pointeurMenu);
  lcd.setCursor(0,2);
  lcd.print("   SOUS-MENU 1: ");
  lcd.setCursor(0,3);
  lcd.print("REGLAGE HALOGENE:");
  lcd.setCursor(17,3);
  lcd.print(PWMhalogene);
}

Merci pour votre aide, on se sent moins seul devant une machine qui n'en fait qu'a sa tête.