Creation d'un menu déroulant à choix multiples

bonjour a tous

voila je me presente je m apelle mathieu tout nouveau dans le monde de la programmation j'ai un projet de création d une bombe factice pour mon association airsoft.Mais voila mais connaissance sont très limiter au niveau de la programation et je n arrive pas a comprendre comment créer un menu j'ai déjà inclus un affichage et mon keypad mais pour le menu c le drame esce que quelqu un pourrait m aider ou même m apprendre par ou commencer merci beaucoup par avance

Salut,

je fais un projet équivalent pour ma voiture télécommandée: je fais remonter des infos de la voiture (vitesse, direction...) sur l'écran OLED que j'ai installé entre 2 joysticks.

Si déjà tu as pu allumer l'écran et y pousser ton propre affichage, tu es sur de bonnes bases!
Pour des affichage de type "menu" c'est un peu compliqué au début (je n'arrive pas à faire tout ce que je voudrais) mais il faut globalement que tu divises ton écran en zone d'affichage (le plus simple serait: une zone pour chacune des 8 lignes de ton écran).
Ensuite, tu crées une valeur qui sera ton "pointeur de zone" et tu l'associes à ta zone n°1 (par exemple la 1ère ligne de l'écran).
tu peux alors envoyer depuis l'arduino l'affichage que tu souhaites sur cette zone. Ton pointeur de zone saura que tu es sur la 1ère ligne.

Tu peux alors faire de l'arithmétique sur ce pointeur de zone (EDIT: j'entends par là, une commande a été reçue pour se déplacer dans le menu: flèche du clavier, mouvement du joystick....) : Ajoute lui 1 pour le faire descendre d'une zone, retire 1 pour le faire remonter (et met des sécurité pour qu'il ne dépasse jamais le nombre de ligne de l'écran, ou remet le à sa valeur initiale pour qu'il remonte à la 1ère ligne).

Si tu relances l'affichage vers l'écran avec une valeur différente de ton pointeur de zone, tu afficheras tes infos sur la ligne correspondante.

à l'inverse, imagine la 1ère ligne qui affiche "BOMBE en COURS" et sur laquelle on ne peut pas agir, et la ligne 2 qui affiche " Désamorcer (D) / Activer (A)" qui invite à entrer une lettre du keypad.
Si mon pointeur de zone est égal à la 1ère ligne, et que je reçois une info (genre "A"), je sais qu'il ne faut rien faire.
Si mon pointeur de zone est égale à la 2ème ligne et que je reçois une infos, je la filtre (est-ce qu'elle vaut D ou A?) et je peux lancer une action depuis l'arduino.

tout ça n'est peut etre pas très clair, mais j'espère que ça te donnera des idées pour développer ton code.

Bonjour @mat60190

Fil de discussion mis à sa place : dans la partie principale du forum francophone , comme défini dans les Bonnes Pratiques du Forum Francophone à consulter impérativement pour savoir où et comment demander de l'aide.

Quand tu maitriseras le sujet , il sera alors possible de rédiger et déposer un tutoriel dans la zone qui leur est réservée :wink:

merci beaucoup et désoler pour cette erreur

pas de problème, il n'est pas facile en arrivant de bien prendre d'emblée toutes ses marques !

merci pour ta réponse et désoler pour cette réponse tardive j était en déplacement après je comprend pas tout sa fait 5 jour que je suis dessus et je craque lol je pence que je vais chercher quelqu'un qui pourras me créer mon code ou je pence que je vais tout abandonner car je ne penser pas sa aussi complexe j'ai essayer plusieurs formule et rien ne fonctionne a chaque fois j'ai beaucoup de mal a comprendre ou il faut placer mes ligne et quelle mot employer la base en faite

c surtout que je pence que je vais abandonner ou trouver une personne qui puisse me créer mon codage car sa me fait craquer je pence que je pouvez y arriver mais c très compliquer

voici le code que j'ai écrit pour le menu mais je n arrive toujours pas a entrée dans le sous menu

#include <LiquidCrystal.h>
#include <Adafruit_Keypad.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = A0, en = A2, d4 = A3, d5 = A4, d6 = A5, d7 = A6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte ROWS = 4; // rows
const byte COLS = 4; // columns
uint8_t rowPins[] = { 13, 12, 11, 10 };
uint8_t colPins[] = {9, 8, 7, 6};
//define the symbols on the buttons of the keypads
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}

};

byte rowsPins[ROWS] = {13, 12, 11, 10}; //connect to the row pinouts of the keypad
byte colsPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

const byte LCD_A = 0x3F; // adresse du LCD en 0x3F
const byte LCD_L = 4; // 4 Lignes
const byte LCD_C = 16; // de 20 caractères

/* GESTION SIMPLE D'UN MENU */

/* un menu est composé de plusieurs lignes de commandes /
/
chaque ligne présente un texte, à une touche d'activation et une fonction à appeler /
struct t_LigneMenu {
const char
valide; // le texte à afficher
const char A; // la touche du keypad à appuyer
void (*action)(char); // la fonction a apppeler en cas d'appui, avec en paramètre la touche de commande
};

struct t_menu {
const uint8_t nbLignes; // le nombre de lignes actives dans le menu
t_LigneMenu menu[LCD_L]; // les lignes, au maximum le nombre de lignes du LCD
};

// on a la notion de menu actif, celui qui s'affiche quand
// on appele la fonction afficheMenu()
// si ce menuActif est NULL c'est qu'on n'a pas de menu à afficher.

t_menu* menuActif = NULL;

// on a deux fonctions utilitaires, une pour afficher le menu en cours
// l'autre pour gérer les interactions avec le Menu (s'il est non NULL)

// retourne true si un menu était à afficher
bool afficheMenu()
{
if (menuActif == NULL) return false; // pas de menu

// sinon on efface l'écran et présente le menu
lcd.clear();
for (uint8_t c = 0; c < menuActif->nbLignes; c++) {
lcd.setCursor(0, c);
lcd.print(menuActif->menu[c].valide);
}
return true;
}

// retourne true si un menu a été déclenché, la fonction aura été appelée
bool gestionMenu()
{
if (menuActif == NULL) return false; // pas de menu

// sinon on regarde si elle correspond à une touche autorisée
bool executionMenu = false;
for (uint8_t c = 0; c < menuActif->nbLignes; c++) {

  executionMenu = true; // on dit qu'on a effectué une action
  break; // pas la peine d'aller voir plus loin, on sort du for
}

}

// ***********************************************************
// le menu appelle des fonctions qui sont de signature 'void f(char) {...}'
// on pré-définit ces fonctions pour pouvoir déclarer les menus

void actionsSousMenu(char c);
void actionsA(char c);
void actionsB(char c);

// maintenant on définit les menus
t_menu menuPrincipal = {
3, // 2 entrées actives
{
{"[A] DEMINAGE", 'key A', actionsSousMenu},
{"[B] MISSILE", 'key B', actionsSousMenu},
{NULL, '\0', NULL},
{NULL, '\0', NULL},

}
};

t_menu sousMenuA = {
3, // 3 entrées actives
{
{"[1] fonction A1", '1', actionsA},
{"[2] fonction A2", '2', actionsA},
{"[3] fonction A3", '3', actionsA},
{NULL, '\0', NULL}
}
};

t_menu sousMenuB = {
4, // 4 entrées actives
{
{"[1] fonction B1", '1', actionsB},
{"[2] fonction B2", '2', actionsB},
{"[3] fonction B3", '3', actionsB},
{"[4] fonction B4", '4', actionsB}
}
};

t_menu sousMenuC = {
4, // 4 entrées actives
{
{"[1] fonction B1", '1', actionsB},
{"[2] fonction B2", '2', actionsB},
{"[3] fonction B3", '3', actionsB},
{"[4] fonction B4", '4', actionsB}
}
};

// On définit ce que doivent faire les fonctions.
// ici le menu principal (A/B) affiche un sous menu associé
// qui appelleront soit la fonction actionsA ou actionsB
// avec en paramètre la touche de déclenchement ce qui permet de savoir quoi faire

void actionsSousMenu(char c)
{
Serial.print(F("Appel sous menu, touche ["));
Serial.write(c);
Serial.println(F("]"));
switch (c) {

case 'A':
  menuActif = &sousMenuA; // on choisit le prochain menu
  break;

case 'B':
  menuActif = &sousMenuB; // on choisit le prochain menu
  break;

default: // ne devrait pas arriver on conserve le même menu
  break;

}
}

void actionsA(char c)
{
Serial.print(F("Actions A — choix ["));
Serial.write(c);
Serial.println(F("]"));
menuActif = &menuPrincipal; // on revient au menu principal
}

void actionsB(char c)
{
Serial.print(F("Actions B — choix ["));
Serial.write(c);
Serial.println(F("]"));
menuActif = &menuPrincipal; // on revient au menu principal
}

// ----------------------

void setup()
{

lcd.begin(16, 2);
Serial.begin(9600);
lcd.clear();
Serial.begin(9600);
customKeypad.begin();

menuActif = &menuPrincipal; // on dit quel est le menu actif
afficheMenu(); // et on l'affiche
}

void loop()
{
if (gestionMenu()) afficheMenu();// si un déclenchement a été fait, il y a peut-être un nouveau menu

// ici on peut faire autre chose
// ne pas toucher l'affichage si un menu est actif bien sûr (sinon le menu disparait)
{
// put your main code here, to run repeatedly:
customKeypad.tick();
while(customKeypad.available()){
keypadEvent e = customKeypad.read();
Serial.print((char)e.bit.KEY);
if(e.bit.EVENT == KEY_JUST_PRESSED) Serial.println(" pressed");
else if(e.bit.EVENT == KEY_JUST_RELEASED) Serial.println(" released");
}
delay(10);
}
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.