Menu for Thermstat project

I was looking for a way to get a menu tree like this into Arduino. It is simple in theory but trying to code it is a pain in the butt. >:(

Here is a diagram of how the menu flows. Text in 's is input fields with up/down on a 5-way switch providing a increment or decrement. Time blocks can be set in number, that is one can have three or eight times the program temp changes in a day. It’d be nice if the menu cycle would omit any block not needed. Maybe there is an example or code on gitHub but I’d like advice on which to use if you’ve implemented menus yourself.

The menu pasted below does NOT match the code line-for-line. I am always making changes so here is most up-to-date.

The hardware is an UNO, Dallas DS18B20, dIY 3 channel relay board, some LEDs, a 16x2 LCD, and a 5-way switch.

Menu Root
+ Time Settings
 + Use NTP Server
  - [*YES* / No]
 + Set Time
  - [HH:MM]
 + Set Timeouts for Fan/Temp Changes
  - [HH:MM]
+ Lock On / Off
  - *YES* / No
+ Fan Settings
 - On All Time
 - On with H/C
 + Postmix
  - [HH:MM]
+ Schedule Settings
 + Set # timeblocks
  - [n]
 + Set Timeblock (A...)
  - [HH:MM]
...
 + Set temp for (A...)
  - [n]
...

Here is what I got so far… it works so-so but I’m missing stuff.

void menuM() {
  String lcdOut0;
  String lcdOut1;
  char mainM[3][20] = { "Time Settings", "Lock On/Off", "Schedule Settings" };
  char timeM[3][20] = { {"Time Set"}, {"Auto/NTP Time Set"}, {"Temp/Fan Timeouts"} };
  char scheduleM[3][20] =  { {"Set # of blocks"}, {"Select Block"}, {"Set block X time"} };
  char fanM[3][20] = { {"On with H/C"}, {"On all time"}, {"On every"}};
  char tempM[3][20] = { {"Hysteresis"}, {"Temp. Alerts"} };
  if (menuIndex < 0) menuIndex = 2;   //Keep from running outside array bounds
  if (menuIndex > 2) menuIndex = 0;   //Keep from running outside array bounds
  if (menuIDa == 0) {   //IDa = 0 for root menu
    switch (menuIDb) {
      case 0: //Main Menu
        lcdOut0 = mainM[menuIndex];
        lcdOut1 = mainM[menuIndex + 1];
        break;
      case 1: //Time Menu
        lcdOut0 = timeM[menuIndex];
        lcdOut1 = timeM[menuIndex + 1];
        break;
      case 2: //Schedule Menu
        lcdOut0 = scheduleM[menuIndex];
        lcdOut1 = scheduleM[menuIndex + 1];
        break;
      case 3: //Fan Menu
        break;
        lcdOut0 = fanM[menuIndex];
        lcdOut1 = fanM[menuIndex + 1];
      case 4: //Temperature Menu
        lcdOut0 = tempM[menuIndex];
        lcdOut1 = tempM[menuIndex + 1];
    }
    if (menuIDa == 1) //time menu {
      switch (menuIDb) {
        case 0: //Time Menu
          break;
        case 1: //Set time
          //polls current time and displays it like "*22* : 34" with stars around which to change
          //An up cursor will increment hour
          //A left cursor will select minutes to change
          break;
        case 2: //Auto/NTP Timeset
          lcdOut0 = "Auto/NTP Timeset";
          if (ntpOn == 0) {
            lcdOut1 = "On / *OFF*";
          }
          else {
            lcdOut1 = "*ON* / Off";
          }
          //Select/left will change state of ntpOn
          break;
        case 3: //Temperature & Fan Change timeouts
          break;
      }

  }
  lcdOut0 = "*" + lcdOut0; //cursor

  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");
}

listen to the guy with the accent.

rotary encoder menu

dave-in-nj:
listen to the guy with the accent.

rotary encoder menu

Hey, thanks!

It looks like I got down the bits about menuID and I am handling frames already the way they should be! It's just the iterations from menu branch up and down that are beyond my grasp.