Problem with creating a menu with a Sub-menu

Hi Everyone!

I’m currently working on a project that requires me to create a main menu as well as a sub-menu for each option in said main menu. The project can be very easily done without creating a menu however the user interface aspect of the project is crucial.

After a little research, I found out that I could use arrays or the “SWITCH CASE” statements. For the purposes of my project, neither the main menu nor will the submenu ever have more than 3 or 4 options. Hence, I felt that the switch case statement would be easier and went with it.

The menu was very simple and basically worked by displaying a certain set of options depending on a specific variable and each value corresponded to a specific “option” in the menu; said variable would sort of represent a “page number” of the menu if you know what I mean, and said variable is incremented or decremented depending on whether the up or down button was pressed.

After creating the main menu everything would work fine, then I set out to create a Sub-menu just for the first option in my main menu and after I can get it working once then I can just replicate the same logic for the other submenus.

After changing the code to include the first sub menu, the “menu system” stopped working properly(i.e. the down button seems to access the submenu with some consistency, as well as the ‘back’ button sometimes also selects a menu option ). I know that the core logic behind the menu works because as I was trying to troubleshoot the code I kept commenting out certain parts of the code to narrow down what the cause might be and both menu’s work great when the other is commented out which I’m pretty sure means that I missed a silly mistake in updating a variable or might be a small spelling mistake (i.e pritn insted of print) or such and I have been staring at the code for a couple of days now to no avail and I would really appreciate a fresh set of eyes.

Thanks in advance!

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

int upButton = 2;
int downButton = 3;
int selectButton = 4;
int bckButton = 5;

int menu = 1;
int submenu = 1;

void setup() {
  lcd.begin();
  lcd.backlight();
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(selectButton, INPUT_PULLUP);
  pinMode(bckButton, INPUT_PULLUP);
  updateMenu();
  updateSubMenu();
}

void loop() {
  if (!digitalRead(downButton)){
    menu++;
    updateMenu();
    delay(100);
    while (!digitalRead(downButton));
  }
  if (!digitalRead(upButton)){
    menu--;
    updateMenu();
    delay(100);
    while(!digitalRead(upButton));
  }
  if (!digitalRead(selectButton)){
    displaySub();
    updateMenu();
    delay(100);
    while (!digitalRead(selectButton));
  }
}

void updateMenu() {
  switch (menu) {
    case 0:
      menu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.print(">F.Lungs");
      lcd.setCursor(0, 1);
      lcd.print(" B.Lungs");
      lcd.setCursor(0, 2);
      lcd.print(" Heart");
      lcd.setCursor(0, 3);
      lcd.print(" Stomach");      
      break;

      
    case 2:
      lcd.clear();
      lcd.print(" F.Lungs");
      lcd.setCursor(0, 1);
      lcd.print(">B.Lungs");
      lcd.setCursor(0, 2);
      lcd.print(" Heart");
      lcd.setCursor(0, 3);
      lcd.print(" Stomach");      
      break;

      
    case 3:
      lcd.clear();
      lcd.print(" F.Lungs");
      lcd.setCursor(0, 1);
      lcd.print(" B.Lungs");
      lcd.setCursor(0, 2);
      lcd.print(">Heart");
      lcd.setCursor(0, 3);
      lcd.print(" Stomach");      
      break;

      
    case 4:
      lcd.clear();
      lcd.print(" F.Lungs");
      lcd.setCursor(0, 1);
      lcd.print(" B.Lungs");
      lcd.setCursor(0, 2);
      lcd.print(" Heart");
      lcd.setCursor(0, 3);
      lcd.print(">Stomach");      
      break;
      
    case 5:    
      menu = 4;
      break;
  }
}

/*
void executeAction() {
  switch (menu) {
    case 1:
      action1();
      break;
    case 2:
      action2();
      break;
    case 3:
      action3();
      break;
    case 4:
      action4();
      break;
  }
}*/

void updateSubMenu() {
  switch (submenu) {
    case 0:
      submenu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.print(">Song# 1");
      lcd.setCursor(0, 1);
      lcd.print(" Song# 2");
      lcd.setCursor(0, 2);
      lcd.print(" Song# 3");
      lcd.setCursor(0, 3);
      lcd.print(" Song# 4");      
      break;

      
    case 2:
      lcd.clear();
      lcd.print(" Song# 1");
      lcd.setCursor(0, 1);
      lcd.print(">Song# 2");
      lcd.setCursor(0, 2);
      lcd.print(" Song# 3");
      lcd.setCursor(0, 3);
      lcd.print(" Song# 4");      
      break;

      
    case 3:
      lcd.clear();
      lcd.print(" Song# 1");
      lcd.setCursor(0, 1);
      lcd.print(" Song# 2");
      lcd.setCursor(0, 2);
      lcd.print(">Song# 3");
      lcd.setCursor(0, 3);
      lcd.print(" Song# 4");      
      break;

      
    case 4:
      lcd.clear();
      lcd.print(" Song# 1");
      lcd.setCursor(0, 1);
      lcd.print(" Song# 2");
      lcd.setCursor(0, 2);
      lcd.print(" Song# 3");
      lcd.setCursor(0, 3);
      lcd.print(">Song# 4");      
      break;
      
    case 5:    
      submenu = 4;
      break;
  }
}

void displaySub(){
  //updateSubMenu();
   while (1){
    if (!digitalRead(downButton)){
      submenu++;
      updateSubMenu();
      delay(100);
      while (!digitalRead(downButton));
    }
    if (!digitalRead(upButton)){
      submenu--;
      updateSubMenu();
      delay(100);
      while(!digitalRead(upButton));
    }
    if (!digitalRead(selectButton)){
      //PLAY SONG
      delay(100);
      while (!digitalRead(selectButton));
    }
    if (digitalRead(bckButton) == LOW) {
      break;
  }
}
}

When you are inside a submenu, pushing the buttons should not manipulate the menu variable. Your code basically inceements menu and then draws the menu. But if you are in a submenu of menu1 then you need to detect that and NOT change menu at that time.

Change

  if (!digitalRead(downButton)){
    menu++;
    updateMenu();

To something like this...

  if (!digitalRead(downButton)){
    if(insideSubmenu) {
      submenuPos ++;
    } else {
      menu++;
    }
    updateMenu();

Your method of printing the menus is very wasteful. If you need to change "stomach" to "abdomen" then you have to change it in 5 places. Instead print each menu without the ">" and then print the cursor afterwards.

Thanks a lot for your help and your feedback man! Much Appreciated