Arduino – gestion de menus avec un LCD Keypad shield

Après une longue absence, et un retour annoncé qui n’a jamais eue lieu, je viens aujourd’hui vous proposez un nouveau programme, pour Arduino.

Ce programme n’est pas encore terminé, et a encore besoin d’être optimisé…

Il servira de base à mes futurs projet sur Arduino, et m’as surtout permis d’avoir une première approche de ce shield assez intéressant.

Voici la vidéo du rendu : http://youtu.be/H1aOC_nkEsI

Je vais vous annoncer les grandes ligne du code, afin que vous puissiez comprendre son fonctionnement. Les commentaires du code vous servirons à mieux le comprendre.

Pour cette gestion de menu, je me suis dit que le mieux, serai de se promener dans un tableau, avec les indices qui seraient incrémentés par l’appui d’un bouton.

Rien de compliqué, un simple tableau de char fait l’affaire. On fait donc un tableau de char, tri dimensionnel : char menu_text [nombre de lignes][nombre de colonnes][nombre de caractères].

Le nombre de s’élève à 15, puisque c’est la limite d’affichage de l’écran LCD par ligne.

Pour ma part, afin de rendre le programme plus pratique à utiliser, j’ai rajouté une colonne, contenant le mot : null. Ceci me permet, lors du déplacement dans le tableau, de savoir si la ligne possède une ou plusieurs colonne.  On peut donc faire un tableau avec plusieurs colonnes sans pour autant changer tout le code.

C’est bien beau de se balader dans ton tableau, mais il faut aussi accéder à des valeur, et pouvoir les modifier !

Oui, c’est vrai. Pour ce faire, j’ai créer un second tableau tri-dimensionnel, cette fois de type int. De la même taille que celui de char, il stockera les valeurs que vous voulez modifier avec votre menu. De la même façon que le tableau du menu, on placera des -1 là où il n’y aura pas de valeur.

Je n’aborderai pas le fonctionnement de l’écran LCD, ni de l’utilisation des boutons, puisque les exemples Arduino et une simple recherche sur le net permette d’avoir le code approprié.

Une fois que le menu est créer, il faut avoir accès aux valeur, les modifier, et les enregistrer. J’utilise le bouton SELECT pour accéder a la valeur voulu, les boutons RIGHT et LEFT pour la modifier, et SELECT pour l’enregistrer.

Lors de cette étape, il se pose un problème : Si on veux réutiliser le code de gestion du clavier ( fait avec un switch ), cela modifiera les valeur qui sont utiliser pour se promener dans le tableau du menu. Ce qui provoquera un grand nombre d’erreur ingérable. J’ai opté pour la solution d’un booléan, qui à true modifiera la valeur du tableau de int. Le petit plus de cette solution, permet de protégé aussi lors de cette phase le dépassement des plages de valeur lors de l’appui. On sécurise ainsi les variables pour les tableaux.

voili voilou !

Je pense avoir aborder les plus grosse difficulté de la gestion d’une menu avec sous menu et valeur modifiable.

Edit : le code a été corrigé, et permet maintenant de ne plus dépasser les limites du tableau.

C’est en faite une simple division de deux valeurs obtenu grâce à sizeof : taille du tableau complet / taille d’une ligne.

Je laisse place au code :

#include <LiquidCrystal.h>

/*******************************************************

Gestion de menu – v1
Par Yersinia Programs
https://yersiniaprograms.wordpress.com/

Note : la v0.9 permettait de sortir du tableau
du menu pour les valeur < 0. Sera corrigé pour
la v1.

********************************************************/

// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;

bool choix;
int up;
int ancien_boutton;
int droit;
int select;
int valeur;
int ancienne_valeur;

// initialisation du menu
char menu_text [3][4][15] = {
{
{« Son        => »}, {« intensite »},      {« null »},   {« null »}
},
{
{« bouh ! »},        {« null »},          {« arriere »}, {« null »}
},
{
{« lumiere    => »}, {« intensite  => »}, {« avant »},   {« null »}
}
};

int menu_valeur [3][4][3] = {
{
{-1}, {0}, {-1}, {-1}
},
{
{0}, {-1}, {0}, {-1}
},
{
{-1}, {0}, {0}, {-1}
}
};
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0);      // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
lcd.setCursor(0,0);
//lcd.print(adc_key_in);
// For V1.0 us this threshold
if (adc_key_in < 50)   return btnRIGHT;
if (adc_key_in < 195)  return btnUP;
if (adc_key_in < 380)  return btnDOWN;
if (adc_key_in < 555)  return btnLEFT;
if (adc_key_in < 790)  return btnSELECT;

return btnNONE;  // when all others fail, return this…
}

bool gestion_valeur()
{
if (bouton (read_LCD_buttons()) == true)
{
if (ancien_boutton != btnSELECT)
{
choix = true;
lcd.setCursor(6,1);
lcd.print(valeur);
lcd.print( »   « );
return false;
}
else
{
choix = false;
return true;
}
}
}

bool bouton (int btn_appuye)
{
lcd_key = read_LCD_buttons();
if (ancien_boutton != lcd_key) // permet d’in/décrémenter que de 1 lors de l’appuie d’un bouton
{
switch (lcd_key)
{
case btnRIGHT:
{
if (choix == false) droit++;
else valeur++;
break;
}
case btnLEFT:
{
if (choix == false)
{
if (droit > 0) droit–;
}
else
{
if (valeur > 0) valeur–;
}
break;
}
case btnUP:
{
if (choix == false && up < (sizeof(menu_text)/sizeof(menu_text[0]) – 1)) up++;
break;
}
case btnDOWN:
{
if (choix == false)
{
if (up > 0) up–;
}
break;
}
case btnSELECT:
{
select++;
break;
}
case btnNONE:
{
break;
}
}
ancien_boutton = lcd_key;
return true;
}
return false;
}

void setup()
{
lcd.begin(16, 2);              // start the library
lcd.setCursor(0,0);
lcd.print(« menu »); // print a simple message
choix = false;
}

void loop()
{

lcd.setCursor(0,1);
if (bouton (read_LCD_buttons()) == true)
{
lcd.setCursor(0,1);
lcd.print( »                   « );
lcd.setCursor(0,1);
if (strcmp(menu_text[up][droit], « null ») == 0) // le test pour savoir si il y a un sous menu
{
droit = 0;
}
if (select != 0)
{
valeur = *menu_valeur[up][droit];
lcd.setCursor(0,0); lcd.print(« menu – « ); lcd.print(menu_text[up][droit]);
lcd.setCursor(0,1); lcd.print(« <=            => »);
if (*menu_valeur[up][droit] != -1) // Savoir si il y a une valeur à modifier
{
while (gestion_valeur() != true) {} // tant qu’on est dans la gestion de la valeur (modification)
}
lcd.setCursor(5,0);
lcd.print( »             « ); // on efface ce qu’il y a après menu sur la première ligne du LCD
*menu_valeur[up][droit] = valeur;
select = 0;
}
else
{
lcd.print(menu_text[up][droit]);
}
}

}

Publicités
Cette entrée a été publiée dans Arduino.

11 commentaires sur “Arduino – gestion de menus avec un LCD Keypad shield

  1. Pierre dit :

    Bonjour,
    J’ai le projet d’automatiser mon barbecue. Mon idée est de faire cuire la viande x temps sur une face et de la retourner puis de la refaire cuire x temps sur l’autre face; puis recommencer plusieurs fois. Je voudrais pouvoir selectionner mon type de viande qui aura sa cuisson prédéfinis ainsi que le temps de retournement, ou que l’on choisissent un temps manuellement.

    Je possède une Carte DFRduino Romeo et se Shield LCD 2×16 DFR0009. J’ai également un motoreducteur que j’arrive à controller.
    J’ai du mal sur la partie de programation pour me promener dans mon menu.
    Pouvez vous m’aidez en répondant par mail
    Merci d’avance
    Pierre

  2. Guillaume dit :

    Bonjour, vous utilisez quel version d’Arduino?
    Si je copie votre code directement la vérification bloque et me donne des informations du genre:
    sketch_mar23a:118: error: stray ‘\’ in program
    sketch_mar23a:122: error: stray ‘\’ in program
    sketch_mar23a:128: error: stray ‘\’ in program
    sketch_mar23a:135: error: stray ‘\’ in program
    sketch_mar23a.ino: In function ‘bool bouton(int)’:
    sketch_mar23a:118: error: expected `;’ before ‘u2013′
    sketch_mar23a:122: error: expected `;’ before ‘u2013′
    sketch_mar23a:128: error: expected `)’ before ‘u2013′
    sketch_mar23a:128: error: expected `)’ before ‘;’ token
    sketch_mar23a:135: error: expected `;’ before ‘u2013’

    Si vous avez une piste.

    Bonne journée

  3. John dit :

    Quand tu copies colle le code, les – – sont remplacés par un seul – donc le compilateur ne les comprends pas.

  4. Bastien dit :

    bonjour,
    j’ai le même problème et je n’arrive pas à le reglé, je ne comprend pas trop l’arduino 😥

  5. LAGUIGNE DIDIER dit :

    Bonjour

    Merci pour votre article, j’ai des problèmes lors de la compilation peut ton trouver votre programme complet sur votre site.

    Merci d’avance pour votre aide

  6. LAGUIGNE DIDIER dit :

    Bonjour

    Merci pour votre réponse, je pense que c’est dû à un copier coller mais impossible de mettre le doigt dessus. Message d’erreur stray\342 in program et me mais en sur brillance la ligne if (up > 0) up–;

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s