Switch case submenu issues

Hello all,

I am currently writing out a menu that I plan to later integrate into an automated hydroponics project I’ve been working on. I have successfully made the base menu and am now attempting to add submenus, which will lead to executable actions. Some of the code I currently have is more or less just a place holder, but I have run into some issues with the sub menus and the using of switch cases.

Essentially when I select a menu option the selected function under the menuSelect function wont even load unless there is a delay present, and then after the delay the program returns to the main menu. My goal is that when I select an option from the main menu it will load the selected option and allow me to interact with a submenu. That sub menu will later go to another screen that will allow variables to be changes or actions to be executed.

Example:

Main Menu:

Return;
pH Controls;
EC Controls;
Restart Program;

pH Controls

pH Controls:

Run pH Down;
Run pH Up;

Run pH Up

“pH Up Executed”
runpHUP();

Returns to pH Controls Submenu

;

Pretty much my biggest issue is once I select an action under a switch case that action does not load, or does load if there is a delay and then auto returns before I can make an selections on the submenu

*also once my code completely works and is ready to be integrated into my main project I plan to take out all delays, it’s just easier to develop with delays

#include <LiquidCrystal_I2C.h> // LCD Library
#include <rotary.h> // Rotary Dial Library

int menu = 1;
int programSubmenu = 1;
uint8_t arrow[8] = {0x00, 0x04, 0x06, 0x1f, 0x06, 0x04, 0x00};
LiquidCrystal_I2C lcd(0x27, 20, 4); // decalre lcd
Rotary r = Rotary(11, 10, 2); // Rotary(DialDT Pin,DialCLK Pin, Button Pin)

void setup() {

  lcd.init(); // initiate LCD
  lcd.backlight(); // turn on backlight
  lcd.createChar(0, arrow);
  updateMenu();
}

void loop() {

  volatile unsigned char val = r.process();
  if (val)
  {
    if (val == r.clockwise())
    {
      menu++;
      updateMenu();
      delay(250);
    }
    else if (val == r.counterClockwise())
    {
      menu--;
      updateMenu();
      delay(250);
    }
  }
  if (r.buttonPressedReleased(20))
  {
    menuSelect();
    updateMenu();
    delay(100);
  }
}


void updateMenu() {

  switch (menu) {
    case 0:
      menu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("> Return to Main");
      lcd.setCursor(0, 1);
      lcd.print("  Edit Program");
      lcd.setCursor(0, 2);
      lcd.print("  pH Controls");
      lcd.setCursor(0, 3);
      lcd.print("  Nutrient Controls");
      break;
    case 2:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  Return to Main");
      lcd.setCursor(0, 1);
      lcd.print("> Edit Program");
      lcd.setCursor(0, 2);
      lcd.print("  pH Controls");
      lcd.setCursor(0, 3);
      lcd.print("  Nutrient Controls");
      break;
    case 3:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  Return to Main");
      lcd.setCursor(0, 1);
      lcd.print("  Edit Program");
      lcd.setCursor(0, 2);
      lcd.print("> pH Controls");
      lcd.setCursor(0, 3);
      lcd.print("  Nutrient Controls");
      break;
    case 4:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  Return to Main");
      lcd.setCursor(0, 1);
      lcd.print("  Edit Program");
      lcd.setCursor(0, 2);
      lcd.print("  pH Controls");
      lcd.setCursor(0, 3);
      lcd.print("> Nutrient Controls");
      break;
    case 5:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("  Edit Program");
      lcd.setCursor(0, 1);
      lcd.print("  pH Controls");
      lcd.setCursor(0, 2);
      lcd.print("  Nutrient Controls");
      lcd.setCursor(0, 3);
      lcd.print("> Light Adjustment");
      break;
    case 6:
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(" pH Controls");
      lcd.setCursor(0, 1);
      lcd.print(" Nutrient Controls");
      lcd.setCursor(0, 2);
      lcd.print(" Light Adjustment");
      lcd.setCursor(0, 3);
      lcd.print("> Restart");
      break;
    case 7:
      menu = 6;
      break;
  }
}

void menuSelect() {

  switch (menu) {
    case 1:
      returnToProgram();
      break;
    case 2:
      lcd.clear();
      editProgramSubmenu();
      break;
    case 3:
      //action3();
      break;
    case 4:
      //action4();
      break;
    case 5:
      //action5();
      break;
    case 6:
     // action6();
      break;
  }
}

/*
   ACTION
    ONE
*/


void returnToProgram() {
  lcd.clear();
  lcd.print("returning");
  delay(1500); //
}

/*
   ACTION
    ONE
*/

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

/*
    ACTION
      TWO
*/

void editProgramSubmenu(){

  volatile unsigned char val = r.process();

  if (val)
  {
    if (val == r.clockwise())
    {
      programSubmenu++;
      updateEditSubmenu();
      delay(250);
    }
    else if (val == r.counterClockwise())
    {
      programSubmenu--;
      updateEditSubmenu();
      delay(250);
    }
  }
  if (r.buttonPressedReleased(20))
  {
//    editMenuSelect();
    updateEditSubmenu();
    delay(100);

  }
}

void updateEditSubmenu() {

  switch (programSubmenu) {
    case 0:
      programSubmenu = 1;
      break;
    case 1:
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("Edit Program");
      lcd.setCursor(0, 1);
      lcd.print("< Return");
      lcd.setCursor(0, 2);
      lcd.print("  pH Parameters");
      lcd.setCursor(0, 3);
      lcd.print("  EC Parameters");
      break;
    case 2:
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("Edit Program");
      lcd.setCursor(0, 1);
      lcd.print("  Return");
      lcd.setCursor(0, 2);
      lcd.print("> pH Parameters");
      lcd.setCursor(0, 3);
      lcd.print("  EC Parameters");
      break;
    case 3:
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("Edit Program");
      lcd.setCursor(0, 1);
      lcd.print("  Return");
      lcd.setCursor(0, 2);
      lcd.print("  pH Parameters");
      lcd.setCursor(0, 3);
      lcd.print("> EC Parameters");
      break;
    case 4:
      lcd.clear();
      lcd.setCursor(4, 0);
      lcd.print("Edit Program");
      lcd.setCursor(0, 1);
      lcd.print("  pH Parameters");
      lcd.setCursor(0, 2);
      lcd.print("  EC Parameters");
      lcd.setCursor(0, 3);
      lcd.print("> Program Weeks");
      break;
      case 5:
      programSubmenu = 4;
      break;
  }
}

Can you post a link to the Rotary library you are using. The ones I see only take 2 pins.

For some reason I can't seem to find a link or github, but it's by Ben Buxton. The third pin is for the button, other two are clock and data.

Click on the link near the bottom of the page.

I have been pleading for years that everyone who uses a non-standard Arduino IDE library (i.e., a library that is not part of a standard download/install) provide the download URL as a comment with its #include directive:

This would make life much easier for all of us who use/write Open Source software.

econjack:
Click on the link near the bottom of the page.

I have been pleading for years that everyone who uses a non-standard Arduino IDE library (i.e., a library that is not part of a standard download/install) provide the download URL as a comment with its #include directive:

This would make life much easier for all of us who use/write Open Source software.

That still does not have a file called rotary.h, after looking at a few different adaptations of the Ben Buxton code I still have not found the correct version, was hoping the OP would post a link eventually.

Essentially when I select a menu option the selected function under the menuSelect function wont even load unless there is a delay present, and then after the delay the program returns to the main menu.

From that description, it sounds as if the submenu actually does load, but without the delay you are returning to the main menu so fast that there is not time to see any change in the display. I had a quick look at the code, and there does not seem to be anything to keep the code within the submenu. The editProgramSubmenu() function checks the encode input, but will exit the function without doing anything if there is no new input from the encoder, then you call the updateMenu() function which overwrites the display with the main menu.

Found the link:

So how do I go about getting the code to not exit the submenu until I tell it to? Well actually in the case of the editProgramSubmenu(); I cant even get the code to access the submenu in the first place. I've tried to place delays in various places with no success. Which is actually counter productive as the end goal is to have no delay functions and just use millis.

I also tried commenting out the updateMenu function in the setup but that didn't change anything.

hydrotronics:
Found the link:
arduino/libraries/Rotary at master · buxtronix/arduino · GitHub

That link does not provide a rotary class that takes 3 pins - only 2 pins.

Post a link to the rotary encoder you have that has 3 IO pins please.

My bad, pin 2 is the interrupt pin used for the button on the rotary. The code doesn't call for it to be listed I just put it in there so I wouldn't forget it and the rotary seemed to work fine so I never took it out. The rotary is just a standard rotary from amazon. Clock pin, data pin, button pin, ground, 5 volt.
Then rotary seems to function right, it's just the switch cases I'm not fully grasping.