Pages: [1]   Go Down
Author Topic: Menu lcd 16x2  (Read 1773 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

J'essaie de faire un menu avec mon lcd 16x2 et un arduino uno.
L'idée: Je voudrais qu'un des boutons me fasse naviguer dans un menu et que le deuxième me lance le code correspondant.

Mon code:
Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int buttonPin = 10;     
const int buttonPin2 = 6;     
  int buttonState = 0;         
int buttonState2 = 0;
   void setup() {
     lcd.begin(16, 2);
     lcd.print("TEST");   
   }
  void loop() {   
buttonState = digitalRead(buttonPin);
buttonState2 = digitalRead(buttonPin2);
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
if (buttonState == HIGH) {
  delay(500); //on évite de sauter les menus d'un coup
   lcd.clear();
  lcd.print("menu #1");/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    if (buttonState2 == HIGH){
      delay(300);
      lcd.clear();
      lcd.print("SOUS menu 1");   
buttonState = digitalRead(buttonPin);
buttonState2 = digitalRead(buttonPin2);
if (buttonState == HIGH) {
  delay(500); //on évite de sauter les menus d'un coup
   lcd.clear();
   lcd.print("menu #2");
  if (buttonState2 == HIGH){
      delay(500);
      lcd.clear();
      lcd.print("SOUS menu 2");   
  }
  }
  }
  }
  }

Mon lcd reste bloquer avec le texte "menu 1" je n'ai plus de reactions au boutons...
Merci de votre aide les copains. smiley-red
Logged

Sud-Ouest
Offline Offline
Full Member
***
Karma: 0
Posts: 117
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour, il y a quelque temps je me suis fais une "Base" de menu, pour un projet a qui comporte un afficheur 16x2 I2C.
3 menus et dans chaqu' un 3 sous menus
Je partage  smiley-wink =
(Dans le post suivant car trop de char...)
Logged

Sud-Ouest
Offline Offline
Full Member
***
Karma: 0
Posts: 117
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x20,16,2);

//variable menu

byte bp_haut = 9;
byte bp_bas = 10;
byte bp_gauche = 11;
byte bp_droite = 12;
byte bp_ok = 13;
int time_anti_rebond = 250;

boolean dans_menu_1 = false;
boolean dans_menu_2 = false;
boolean dans_menu_3 = false;

boolean dans_option_1_menu_1 = false;
boolean dans_option_2_menu_1 = false;
boolean dans_option_3_menu_1 = false;

boolean dans_option_1_menu_2 = false;
boolean dans_option_2_menu_2 = false;
boolean dans_option_3_menu_2 = false;

boolean dans_option_1_menu_3 = false;
boolean dans_option_2_menu_3 = false;
boolean dans_option_3_menu_3 = false;

byte num_menu = 1;
byte num_option = 1;

byte nb_max_menu = 3;
byte nb_max_option_menu_1 = 3;
byte nb_max_option_menu_2 = 3;
byte nb_max_option_menu_3 = 3;

void setup()
{   
 
  lcd.init();                     
  lcd.backlight();
  Serial.begin(9600);
 
  pinMode(bp_haut, INPUT_PULLUP);
  pinMode(bp_bas, INPUT_PULLUP);
  pinMode(bp_gauche, INPUT_PULLUP);
  pinMode(bp_droite, INPUT_PULLUP);
  pinMode(bp_ok, INPUT_PULLUP);
 
  Serial.println("Go menu prog");
  affiche_menu();//affiche le premier menu
 
}//fin setup

void loop()
{
 li_bp();//lecture des inputs des boutons poussoir
}

void appui_bp_ok()
{
 
  if (num_menu == 1)//entre dans le menu =>
    {
      dans_menu_1 = true;
      dans_menu_2 = false;
      dans_menu_3 = false;
     
      if (dans_option_1_menu_1 == true)//si appui sur "ok" quand l'option 1 est afficher
        {
          Serial.println("action option 1 menu 1");//execute l'action de l"option 1 du menu 1
        }
      if (dans_option_2_menu_1 == true)
        {
          Serial.println("action option 2 menu 1");
        }
      if (dans_option_3_menu_1 == true)
        {
          Serial.println("action option 3 menu 1");
        }
                 
      affiche_option_menu(1);// => et affiche l'option 1
     
    }
       
  if (num_menu == 2)
    {
      dans_menu_1 = false;
      dans_menu_2 = true;
      dans_menu_3 = false;
     
      if (dans_option_1_menu_2 == true)
        {
          Serial.println("action option 1 menu 2");
        }
      if (dans_option_2_menu_2 == true)
        {
          Serial.println("action option 2 menu 2");
        }
      if (dans_option_3_menu_2 == true)
        {
          Serial.println("action option 3 menu 2");
        }
                 
      affiche_option_menu(2);
    }

  if (num_menu == 3)
    {
      dans_menu_1 = false;
      dans_menu_2 = false;
      dans_menu_3 = true;
     
      if (dans_option_1_menu_3 == true)
        {
          Serial.println("action option 1 menu 3");
        }
      if (dans_option_2_menu_3 == true)
        {
          Serial.println("action option 2 menu 3");
        }
      if (dans_option_3_menu_3 == true)
        {
          Serial.println("action option 3 menu 3");
        }
                 
      affiche_option_menu(3);
    }

}//fin appui_bp_ok

void affiche_menu()
{
   
  if (num_menu > nb_max_menu)
    {
      num_menu = 1;
    }
  if (num_menu < 1)
    {
      num_menu = nb_max_menu;
    }
   
  Serial.print("menu : ");
  Serial.println(num_menu);
   
}//fin menu

void affiche_option_menu(byte dans_menu)
{
 
  if (dans_menu == 1)//affiche les options du menu 1
    {
      if (num_option > nb_max_option_menu_1)
        {
          num_option = 1;
        }
      if (num_option < 1)
        {
          num_option = nb_max_option_menu_1;
        }
       
      if (num_option == 1)
        {
          Serial.println("option 1 menu 1"); //affiche le nom de l'option
         
          dans_option_1_menu_1 = true;//passe la variable de l'option a true pour action si appui sur "ok"
          dans_option_2_menu_1 = false;
          dans_option_3_menu_1 = false;
         
         }
         
       if (num_option == 2)
        {
          Serial.println("option 2 menu 1");
         
          dans_option_1_menu_1 = false;
          dans_option_2_menu_1 = true;
          dans_option_3_menu_1 = false;
         
        }
       
       if (num_option == 3)
        {
          Serial.println("option 3 menu 1");
         
          dans_option_1_menu_1 = false;
          dans_option_2_menu_1 = false;
          dans_option_3_menu_1 = true;
         
        }
    }//fin si dans menu 1
   
  if (dans_menu == 2)
    {
      if (num_option > nb_max_option_menu_2)
        {
          num_option = 1;
        }
      if (num_option < 1)
        {
          num_option = nb_max_option_menu_2;
        }
       
      if (num_option == 1)
        {
          Serial.println("option 1 menu 2");
         
          dans_option_1_menu_2 = true;
          dans_option_2_menu_2 = false;
          dans_option_3_menu_2 = false;
         
        }
       
       if (num_option == 2)
        {
          Serial.println("option 2 menu 2");
         
          dans_option_1_menu_2 = false;
          dans_option_2_menu_2 = true;
          dans_option_3_menu_2 = false;
                   
        }
       
       if (num_option == 3)
        {
          Serial.println("option 3 menu 2");
         
          dans_option_1_menu_2 = false;
          dans_option_2_menu_2 = false;
          dans_option_3_menu_2 = true;
         
        }
       
    }//fin si dans menu 2
   
  if (dans_menu == 3)
    {
      if (num_option > nb_max_option_menu_3)
        {
          num_option = 1;
        }
      if (num_option < 1)
        {
          num_option = nb_max_option_menu_3;
        }
       
      if (num_option == 1)
        {
          Serial.println("option 1 menu 3");
         
          dans_option_1_menu_3 = true;
          dans_option_2_menu_3 = false;
          dans_option_3_menu_3 = false;
         
        }
       
       if (num_option == 2)
        {
          Serial.println("option 2 menu 3");
         
          dans_option_1_menu_3 = false;
          dans_option_2_menu_3 = true;
          dans_option_3_menu_3 = false;
                   
        }
       
       if (num_option == 3)
        {
          Serial.println("option 3 menu 3");
         
          dans_option_1_menu_3 = false;
          dans_option_2_menu_3 = false;
          dans_option_3_menu_3 = true;
         
        }
       
    }//fin si dans menu 3

 
}//fin affiche option menu

void exit_option_menu()
{
  dans_option_1_menu_1 = false;
  dans_option_2_menu_1 = false;
  dans_option_3_menu_1 = false;
 
  dans_option_1_menu_2 = false;
  dans_option_2_menu_2 = false;
  dans_option_3_menu_2 = false;
 
  dans_option_1_menu_3 = false;
  dans_option_2_menu_3 = false;
  dans_option_3_menu_3 = false;
 
  }

void exit_menu()
{
  dans_menu_1 = false;
  dans_menu_2 = false;
  dans_menu_3 = false;
 
  num_option = 1;//raz des num option
}

void li_bp()//lecture des entrees digital des bp
{
 
  if (digitalRead(bp_haut) == LOW)
    {
      //Serial.println("bp_haut");
     
      exit_menu();//raz des variable "dans_menu"
      exit_option_menu();//raz des variables "dans_option_menu"
      num_menu = num_menu - 1;//incremente les menus
      affiche_menu();//affiche le nom des menus
     
      delay(time_anti_rebond);
     
    }

  if (digitalRead(bp_bas) == LOW)
    {
      //Serial.println("bp_bas");
     
      exit_menu();
      exit_option_menu();
      num_menu = num_menu + 1;
      affiche_menu();
     
      delay(time_anti_rebond);
    } 

  if (digitalRead(bp_ok) == LOW)
    {
      //Serial.println("bp_ok");
      appui_bp_ok();
      delay(time_anti_rebond);
    }
 
  if (digitalRead(bp_droite) == LOW)
    {
      //Serial.println("bp_droite");
     
      exit_option_menu();//raz des variables "dans_option_menu"
     
      if (dans_menu_1 == true || dans_menu_2 == true || dans_menu_3 == true)
        {
          num_option = num_option + 1;//incrementes les options que si on est dans un des menu
        }
     
      if(dans_menu_1 == true)
        {
          affiche_option_menu(1);//une fois incrementer on affiche le nom de cette option
        }
       
      if(dans_menu_2 == true)
        {
          affiche_option_menu(2);
        }

      if(dans_menu_3 == true)
        {
          affiche_option_menu(3);
        }
       
      delay(time_anti_rebond);
     
    }//fin bp droite

  if (digitalRead(bp_gauche) == LOW)
    {
      //Serial.println("bp_gauche");
     
      exit_option_menu();
     
      if (dans_menu_1 == true || dans_menu_2 == true || dans_menu_3 == true)
        {
          num_option = num_option - 1;//decrementes les options que si on est dans un des menu
        }
     
      if(dans_menu_1 == true)
        {
          affiche_option_menu(1);
        }
       
      if(dans_menu_2 == true)
        {
          affiche_option_menu(2);
        }
     
      if(dans_menu_3 == true)
        {
          affiche_option_menu(3);
        }
       
      delay(time_anti_rebond);
     
    }//fin bp gauche
   
}//fin appui_bp

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut,

merci beaucoup à toi, je vais tester ca.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 63
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut, moi je te conseil d'utilisé la librairie MenuBackend (http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip)
(https://github.com/WiringProject/Wiring/tree/master/framework/libraries/MenuBackend),(Le deuxième lien est une version apparament plus récente mais pas encore testé par mes soins) moi je l'utilise et elle marche très bien.

Elle permet de crée un menu basic avec l'arduino, puis en fessant appel à une fonction lors du changement de menu géré l'affichage avec un afficheur lcd 16x2 par exemple.

je la trouve très pratique, elle ce décompose en plusieurs points :
  • Crée les objets de menu
  • définir les relation entre les menus
  • Gérer l'affichage du menu, l'or d'un changement
  • Gérer l’événement d'une activation
  • Définir les "touches" / actions pour déplacer le curseur de menu

Si tu a besoin d'aide pour cette librairie, je connais bien et je serais content de t'aider.

Timiti29

PS : cutprod -> Je trouve ton code un peut "lourd", comparer à la librairie MenuBackend
« Last Edit: June 13, 2013, 10:46:24 am by timiti29 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut,
Désolé du retard de ma réponse...
Je te remercie pour ton conseil, entre temps j'ai réussi à coder mon menu ( je mettrais le code si quelqu'un si intéresse.)
Je souhaite faire évoluer mes boutons en clavier 4x4 et je doit dire que pour l'instant les résultats ne sont pas encore au rendez-vous.
La librairie que tu me conseil peut elle m'aider dans mon cas ?
Encore merci
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 63
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, tu a la librairie  http://playground.arduino.cc/code/Keypad pour gérer les claviers matriciel.
tu a juste à brancher le clavier directement sur l'arduino sans autres composants.

J'ai fait un code d'exemple d'utilisation d'un menu avec un clavier 16 touches et un afficheur LCD :
Code:
#include <Keypad.h>
#include <MenuBackend.h>
#include <LiquidCrystal.h>

/*
La structure du menu

Settings
Pin  / a droite de settings
Debug / en dessous de Pin
Options
Delay (D) / a droite de Options
100 ms / a droite de Delay
200 ms / en desous de 100ms
300 ms / ...
400 ms / ...
*/
///////////////////////////////
#define ROWS 4
#define COLS 4

char keys[ROWS][COLS] = {
  {'1', '2', '3', 'F'},
  {'4', '5', '6', 'E'},
  {'7', '8', '9', 'D'},
  {'A', '0', 'B', 'C'}
};

byte rowPins[ROWS] = {14, 15, 16, 17}; //les pin's des ligne, L1 L2 L3 L4
byte colPins[COLS] = {18, 19, 20, 21}; //les pin's des colonne, C1 C2 C3 C4

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

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

//On crée l'objet du menu principal
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
//On crée les objets de chaques éléments du menu
MenuItem settings = MenuItem("Settings");
MenuItem pin = MenuItem("Pin");
MenuItem debug = MenuItem("Debug");

MenuItem options = MenuItem("Options");
MenuItem setDelay = MenuItem("Delay");
MenuItem d100 = MenuItem("100 ms");
MenuItem d200 = MenuItem("200 ms");
MenuItem d300 = MenuItem("300 ms");
MenuItem d400 = MenuItem("400 ms");

//On crée / initialise les éléments au menu et les relations (gauche, droite, haut, bas)
void menuSetup()
{
Serial.println("Setting up menu...");
//add the file menu to the menu root
menu.getRoot().add(settings); // Il faut ajouter cette fonction dans le fichier :
//MenuBackend.h MenuItem &getRoot() {return root;} dans la classe MenuBackend dans les fonctions publique l66 par exemple
                settings.addBefore(settings);
//setup the settings menu item
settings.addRight(pin);
//we want looping both up and down
//pin.addBefore(debug);
pin.add(debug);
//we want a left movement to pint to settings from anywhere
debug.addLeft(settings);
pin.addLeft(settings);
//settings.addBefore(options);
settings.add(options);
options.addRight(setDelay);
                  options.setShortkey('T');
//setDelay.addLeft(options);
setDelay.addRight(d100);
d100.add(d200);
d200.add(d300);
d300.add(d400);
//we want left to always be bak to delay
d200.addLeft(setDelay);
d300.addLeft(setDelay);
d400.addLeft(setDelay);
d100.addLeft(setDelay);
       
        menu.moveDown();//On ce déplace du menu root, vers le menu Settings (setings est en dessous du menu root)
}
//Si on a apeler la fonction menu.Use()
void menuUseEvent(MenuUseEvent used)
{
        lcd.setCursor(0,0);
        lcd.print("You used        ");
        lcd.setCursor(0,1);
        lcd.print(used.item.getName());
        refresh(menu.getCurrent());
}

void menuChangeEvent(MenuChangeEvent changed)
{
Serial.print("Menu change ");
Serial.print(changed.from.getName());
Serial.print(" -> ");
Serial.println(changed.to.getName());

    MenuItem newMenuItem=changed.to; //get the destination menu
    refresh(newMenuItem);
}
//La fonction qui va ce charger de "rafraichir" l'affichage du LCD lors d'un changement de menu
void refresh(MenuItem newMenuItem)
{
        Serial.println("refresh !");
        clearLine(1);
        lcd.setCursor(0,1); //set the start position for lcd printing to the second row
        if(newMenuItem.getName()==menu.getRoot().getName())
        {
            lcd.print("Main Menu        ");
        }
        else if(newMenuItem==settings)
        {
            lcd.print("Settings");
        }
        else if(newMenuItem==pin)
        {
            lcd.print("Pin");
        }
        else if(newMenuItem==debug)
        {
            lcd.print("Debug");
        }
        else if(newMenuItem==options)
        {
            lcd.print("Options");
        }
        else if(newMenuItem==setDelay)
        {
            lcd.print("Delay");
        }
        else if(newMenuItem==d100)
        {
            lcd.print("100 ms");
        }
        else if(newMenuItem==d200)
        {
            lcd.print("200 ms");
        }
        else if(newMenuItem==d300){
            lcd.print("300 ms");
        }
        else if(newMenuItem==d400){
            lcd.print("400 ms");
        }
}
void clearLine(byte line)
{
  lcd.setCursor(0, line);
  lcd.print("                ");
  lcd.setCursor(0, line);
}

void setup()
{
    lcd.begin(16, 2);
menuSetup();
    lcd.setCursor(0,0);
    lcd.print("Start");
    keypad.setDebounceTime(150);//Le temps d'appuis entre chaque touche, pour éviter les anti-rebond
    Serial.begin(9600);
    Serial.print("start");
}

void loop()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
    switch(key)
    {
      case '2'://Up
        menu.moveUp();
        break;
      case '4'://Left
        menu.moveLeft();
        break;
      case '6'://Right
        menu.moveRight();
        break;
      case '8'://Down
        menu.moveDown();
        break;
      case '*':
        menu.moveBack();
        break;
      case '#':
        menu.use();
        break;
    }
  }
}

En gros après avoir crée les objets, j'ai une fonction qui va crée les éléments et crée les relations. puis j'ai une autre fonction qui va etre appeler si on appelle la fonction menu.Use(); (elle récupère le menu courant en paramètre)
une autre fonction qui va être appeler lors d'un déplacement dans le menu. une autre fonction pour gérer l'affichage du menu dans l'afficheur LCD, la fonction setup et la fonction loop (dedans, on lit le clavier et si on a appuyer sur une touche on ce déplace dans le menu)

Voila globalement l'exemple que j'ai fait, tiré d'un code d'exemple (je crois) et modifier pour utiliser un keypad et un LCD


Donc oui cette librairie peut être utilisé avec un LCD et un clavier matriciel, il suffit d'avoir compris le fonctionnement (simple) de cette librairie

Si tu a un problème ou une question à propos de mon code ou des librairies, n’hésite pas a me contacter.


Avant de tester le code il y a une modification à apporter dans le fichier MenuBackend.h :
    ajoute la fonction : "MenuItem &getRoot() {return root;}" dans les fonction publique de la classe MenuBackend
Si sa compile pas, assure toi qu'il y est bien #include "Arduino.h" dans le fichier Keypad.h à la place de #include <WProgram>

Voila.

Timiti29
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut, c'est vraiment sympa à toi de m'aider tant
Je vais pouvoir bosser avec un bon support
J'ai effectivement changer la partie "arduino.h" car malheureusement la librairie keypad est trop ancienne pour mon ide.

a+
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 63
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Derien smiley-wink sa me fait plaisir d'avoir pu aider un membre de la communauté, je me dit que si j'aide les gens,
j'aurais peut-etre des réponses à mes problèmes smiley-wink

voila.

Timiti29

PS si encore tu a un problème/question concernant la librairie MenuBackend/Keypad/LCD je peut aider et j'en serais ravis ;-)
Logged

Pages: [1]   Go Up
Jump to: