Unresponsiveness in Nested Menus - ESP32 & Arduino - OLED & Rotary Encoder

Hi all,

I’m working on an ESP32 based project which uses a rotary encoder to control a number of menus displayed on an OLED screen.

I have finished most of the sub-menu’s as stand alone functions, and have been trying to organize them into a series of switch-cases.

My idea is to have the menus run as functions, returning integer values which will control the next menu to go to, or to go back. I’ve never done a project like this, so I’m unsure if that’s the proper way to structure menus.

I’m running into a responsiveness issue with second and third layers of nested menus. I’ve stripped down the program for this post, currently only the “About Menu” is functioning as an example.

I made a video that explains the issue here:

Sketch .ino file is attached, thanks for any input!

-tbb

ardQ_01.ino (9.38 KB)

i don't see anything obviously wrong, but suggest some simplifications

in loop(), aboutMenu() always gets called twice. why not

   while (! aboutMenu())
        ;

but why repeatedly call anoutMenu() each iteration of loop()?

why not have aboutMenu() simply return the result of buttonPress()

    return buttonPress()

i had to stare at buttonPress() for a while to figure out what it's doing. don't see anything wrong, but it seems unnecessarily complicated. you might consider

int buttonPress() {
    while (buttonState != (reading = digitalRead(buttonPin))
        delay (20);

    buttonState = reading;

    if (buttonState == HIGH) {
        Serial.println("the button has been pressed");
        piezoBeep();
    }

    return buttonState;
}

don't understand why aboutMenu() isn't handled in mainMenu() and why the extra code in loop(). why isn't loop() simply waiting on input events

void loop() {
  if (buttonPress() || rotaryEncoder()) {
    mainMenu();
  }
}

i think having an array for menu strings is good, but the code in mainMenu() is repetitious. the index, "i" should be updated based on an encode event and that index used to update the display.

you can also create a structure that contains menu strings and actions, a function pointer (e.g. (void) (*act)(int)), to further make menu processing table driven

bottom line is it seems the odd behavior of the aboutMenu() is due to the separate way it is handled

Thanks for taking the time gcjr, I'm going through googling and trying to implement some of your suggestions.

I'm certainly a novice, and getting things to work efficiently is much harder than just getting them to work :slight_smile:

make it work, make it right, make it fast and Bumper-sticker Computer Science

less complicated code is easier to read, understand and debug

gcjr:
but why repeatedly call anoutMenu() each iteration of loop()?

It turns out this was the source of the error! I changed the switch case 3 from:

       case 3:
        Serial.println("case 3");
        do {
          aboutMenu();
        } while (aboutMenu() == false);
        break;

To:

      case 3:
        Serial.println("case 3");
        do {
            aboutMenuStatus = aboutMenu();
        } while (aboutMenuStatus == false);
        break;

Adding the aboutMenuStatus instead of calling the menu a second time cleared up any delay.

Thanks again for the input, I'm still trying to implement the other suggestions you made.