Submenu on lcd display problem

Hi,
I am beginner in Arduino programming, and i have little problem with my code. I want to navigate through my lcd display menu with 4 buttons. I already did something "working" but I don´t know how to program the function to solve this problem. If I choose subMenu "chooseFile" it will print on display subMenu of "chooseSpool".... I tried a lot of functions and watched a lot of codes but as beginner I don´t understand it yet. I want to ask if it is possible to change this or I must rewrite the code.
Here is the code without function that provides the "chooseFile" subMenu selection. If you know how to write the function I will be so glad for you.

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
 
LiquidCrystal_I2C lcd (32,16,2);
bool vybrane; //choosed 
bool vybrane2; //choosed2
int tlacitko_ok =11; //Enter Button
int tlacitko_spat = 10; //Back Button
int tlacitko_dole = 12; // Down Button
int tlacitko_hore = 13; //Up Button
unsigned int menu;
unsigned int subMenu;
unsigned int subMenu2;
//////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
lcd.init();
lcd.backlight();
pinMode (10, INPUT_PULLUP);
pinMode (11, INPUT_PULLUP);
pinMode (12, INPUT_PULLUP);
pinMode (13, INPUT_PULLUP);
menu= 1;
subMenu=1;
subMenu2=1;
updateMenu();
}

////////////////////////////////////////////////////////////////////////////////////////
void loop() {
if (!vybrane){ 
  if (!digitalRead(tlacitko_dole)){
    menu++;
    updateMenu();
    delay(100);
    while (!digitalRead(tlacitko_dole));
  }
  if (!digitalRead(tlacitko_hore)){
    menu--;
    updateMenu();
    delay(100);
    while (!digitalRead(tlacitko_hore));
}
} else {
  if (!digitalRead(tlacitko_dole)){
  subMenu++;
  updateSubMenu();
  delay(100);
  while (!digitalRead(tlacitko_dole));
}
if (!digitalRead(tlacitko_hore)){
  subMenu--;
  updateSubMenu();
  delay(100);
  while (!digitalRead(tlacitko_hore));
}
}
  if(!digitalRead(tlacitko_ok)){
    if (!vybrane){
      subMenu = 1;
  vybrane = true;
  updateSubMenu();
    } else{
      chooseSpool();
      delay(100);
      while(!digitalRead(tlacitko_ok));
    }
  }
  if (!digitalRead(tlacitko_spat)){
    if (vybrane){
      vybrane = false;
      updateMenu();
    }else {
      delay(100);
      updateMenu();
      while (!digitalRead(tlacitko_spat));
    }
  }
}
///////////////////////////////////////////////////////////////////////////////////
void updateMenu(){
  switch (menu){
    case 1:
    lcd.clear();
    lcd.print(">Choose spool");
    lcd.setCursor(0,1);
    lcd.print("Choose file");
    break;
    case 2 :
    lcd.clear();
    lcd.print("Choose spool");
    lcd.setCursor(0,1);
    lcd.print(">Choose file");
    break;
    case 3:
    menu= 1;
    updateMenu();
  }
}
void updateSubMenu(){
  switch (subMenu){
    case 1 :
    lcd.clear();
    lcd.print(">ABS");
    lcd.setCursor(0,1);
    lcd.print("PLA");
    break;
    case 2 :
    lcd.clear();
    lcd.print("ABS");
    lcd.setCursor(0,1);
    lcd.print(">PLA");
    break;
    case 3 :
    lcd.clear();
    lcd.print("PLA");
    lcd.setCursor(0,1);
    lcd.print(">PETG");
    break;
  }
}
void chooseSpool (){
  switch (subMenu){
    case 1 :
    lcd.clear();
    lcd.print(">ABS");
    lcd.setCursor(0,1);
    lcd.print("PLA");
    break;
    case 2 :
    lcd.clear();
    lcd.print("ABS");
    lcd.setCursor(0,1);
    lcd.print(">PLA");
    break;
    case 3 :
    lcd.clear();
    lcd.print("PLA");
    lcd.setCursor(0,1);
    lcd.print(">PETG");
    break;
  }
}
void updateSubMenu2(){
  switch (subMenu2){
    case 1 :
    lcd.clear();
    lcd.print(">From SD");
    break;
  }
}
void chooseFile(){
  switch (subMenu2){
    case 1 :
    lcd.clear();
    lcd.print(">From SD");
    break;
}
}

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

LiquidCrystal_I2C lcd (32, 16, 2);
bool vybrane=false; //choosed
bool vybrane2=false; //choosed2
int Key_ok = 11; //Enter Button
int Key_Back = 10; //Back Button
int Key_Down = 12; // Down Button
int Key_Up = 13; //Up Button
unsigned int menu;
unsigned int subMenu;
unsigned int subMenu2;
//////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  lcd.init();
  lcd.backlight();
  pinMode (10, INPUT_PULLUP);
  pinMode (11, INPUT_PULLUP);
  pinMode (12, INPUT_PULLUP);
  pinMode (13, INPUT_PULLUP);
  menu = 1;
  subMenu = 1;
  subMenu2 = 1;
  updateMenu();
}

////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  if (!vybrane) {
    if (!digitalRead(Key_Down)) {
      menu++;
      if(menu==3)menu=1;
      updateMenu();
      delay(100);
      while (!digitalRead(Key_Down));
    }
    if (!digitalRead(Key_Up)) {
      menu--;
      if(menu==0)menu=2;
      updateMenu();
      delay(100);
      while (!digitalRead(Key_Up));
    }
  } else {
    if (!digitalRead(Key_Down)) {
      subMenu++;
      if(subMenu==4)subMenu=1;
      updateSubMenu();
      delay(100);
      while (!digitalRead(Key_Down));
    }
    if (!digitalRead(Key_Up)) {
      subMenu--;
      if(subMenu==0)subMenu=2;
      updateSubMenu();
      delay(100);
      while (!digitalRead(Key_Up));
    }
  }
  if (!digitalRead(Key_ok)) {
    if (!vybrane) {
      subMenu = 1;
      vybrane = true;
      updateSubMenu();
    } else {
      if (subMenu==1)chooseSpool();
      if (subMenu==2)chooseFile();
      delay(100);
      while (!digitalRead(Key_ok));
    }
  }
  if (!digitalRead(Key_Back)) {
    if (vybrane) {
      vybrane = false;
      updateMenu();
    } else {
      delay(100);
      updateMenu();
      while (!digitalRead(Key_Back));
    }
  }
}

void updateMenu() {
  switch (menu) {
    case 1:
      lcd.clear();
      lcd.print(">Choose spool");
      lcd.setCursor(0, 1);
      lcd.print("Choose file");
      break;
    case 2 :
      lcd.clear();
      lcd.print("Choose spool");
      lcd.setCursor(0, 1);
      lcd.print(">Choose file");
      break;
  }
}
void updateSubMenu() {
  switch (subMenu) {
    case 1 :
      lcd.clear();
      lcd.print(">ABS");
      lcd.setCursor(0, 1);
      lcd.print("PLA");
      break;
    case 2 :
      lcd.clear();
      lcd.print("ABS");
      lcd.setCursor(0, 1);
      lcd.print(">PLA");
      break;
    case 3 :
      lcd.clear();
      lcd.print("PLA");
      lcd.setCursor(0, 1);
      lcd.print(">PETG");
      break;
  }
}
void chooseSpool () {
        lcd.clear();
      lcd.print("Hier is the");
      lcd.setCursor(0, 1);
      lcd.print("third level menu");
}

void chooseFile() {
        lcd.clear();
      lcd.print(">From SD");
 }

Thank you for your responde, but that third level menu is working in my code but i want to help with problem : If i "choose File" on the menu it prints on the display the "choose Spool" submenu not the one what is supposed to print.

what happen if you choose other submenu?

In your modified code when i choosed the subMenu "choose File" it printed this :

void chooseSpool () {
        lcd.clear();
      lcd.print("Hier is the");
      lcd.setCursor(0, 1);
      lcd.print("third level menu");

instead of this :

void chooseFile() {
        lcd.clear();
      lcd.print(">From SD");
 }

In my original code it was the same but with my custom lcd.print code. If you know what I mean.

i changed only text. menu order is still same. now you know what to change. you'r welcome

Yeah, but both of the submenus prints the same
after i clicked on Choose spool :

and after i clicked on Choose File it printed the same

but I want that if I click on the choose File text it will print : "From SD" text.

U can try it if you dont trust me :confused:

You code does call function updateMenu(); recursively.
recursievly means you are calling the function inside exact this function

function updateMenu() calls updateMenu(); this will lead to memory problems
and will have strange sideeffects because whenever the function comesback from the last
call of updateMenu() the code will go on executing at where it was before with its own set
of local variables.

void updateMenu() {
  switch (menu) {
    case 1:
...
      break;
    case 2 :
...
      break;
    case 3:
      menu = 1;
      updateMenu(); // <<< DON'T ! call the function itself from inside the function
  }
}

you have to organise your code in a way that is NON-recursive

if you rebuild your project using the WOKWI-simulator

everybody can participate and test your code without registering to tinkercad

you could organise your code to have one function that does only print the menu-lines
and another one that does
print a space where the ">" momentare is (to delete the ">"-symbol
and then
prints the ">" at the other line

This printing can even be done depending on a number 1 or 2 which you use for the line and for the function that shall be executed

best regards Stefan

here is the project on the side you told me :

very good.
I made a copy and added serial debug-output

This makes visible what values your variables haveand which lines of code get executed
best regards Stefan

thats nice, but after all i still dont know ho to fix my problem :smiley:
now i can see what is happening in arduino, but how to change the code to fix that issue.

where you get this sketch?

what do you mean for "this sketch" ?

a sktech means the file with the code. The *.ino-file that you are writing in the arduino-IDE

In your first posting you posted your code

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
 
LiquidCrystal_I2C lcd (32,16,2);
bool vybrane; //choosed 
bool vybrane2; //choosed2
int tlacitko_ok =11; //Enter Button
....
void chooseFile(){
  switch (subMenu2){
    case 1 :
    lcd.clear();
    lcd.print(">From SD");
    break;
}
}

This file with all the code is called "the sketch"

best regards Stefan

oh I understand it now, thank you.
The first sketch I posted thats my own code. I wrote it.

well, write new sketch. try this time not remake complete display message but moving only one symbol ">". we already show enough examples to learn from.

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