Arduino OLED Rotary Encoder Menu System (Help)

Hi,

There's a project that I'm trying to bring to life, but I've been stuck with it for more than a week. I'm literally disappointed now as most of my efforts have not produced the desired result.

I want to create a nested menu system, whereupon selecting an option leads to further set of choices. The hardware is an Arduino Pro Mini 16MHz variant, 5-pin Rotary Encoder and an SSD1306 OLED module.

To realize this, I have tried most of the popular UI options available including Nokia5110MenuRotary, Arduino Menu System, Arduino Menu, qMenu System, Arduino OLED Menu Part III, Arduino Spot Welder and many more. I tried the examples from Arduino Menu System (Adafruit, U8G2), and also tried integrating a rotary encoder to U8G2 List code by taking cues from this dicussion. However, there hasn't been success since these codes inherit far more complexity for my programming skills. Although I've been trying to learn, and made some progress with the Nokia LCD version, but adding nested menus did not work out. At the moment I feel lost amidst all the coding mayhem I've cast upon myself in the past few days.

I really need help and guidance!

Is it possible, if this could be made to work?

The library is qMenu and I’m trying to make it work with I2C protocol while still contemplating how to implement the rotary encoder.

Please take alook at the modified code below which compiles without issues but does not show anything on the display.

/*
  ======================================
  qMenuSystem example #1
  ======================================

  1. Connect OLED in SPI mode: DATA=D8, CLOCK=D9, SS=D10
  2. Compile & upload
  3. Open Serial monitor (Ctrl+Shift+M)
  4. Use "q", "a", "s" to move across menu ("q" = up, "a" = down, "s" = select)

*/

#define _Digole_Serial_I2C_
#include <DigoleSerial.h>
#include <Wire.h>

#include <qMenuDisplay.h>
#include <qMenuSystem.h>

#include "TestMenu.h"

DigoleSerialDisp mydisp = DigoleSerialDisp(4, 5);
qMenuSystem menu = qMenuSystem(mydisp);

void setup()
{
  menu.InitMenu(mnuRoot, cntRoot, 1);
  Serial.begin(9600);
}

void loop()
{
  int keycode = 0;
  int clickedItem = 0;

  if (Serial.available() > 0)
  {
    switch (Serial.read())
    {
      case 97:
        menu.ProcessMenu(ACTION_DOWN);
        break;
      case 113:
        menu.ProcessMenu(ACTION_UP);
        break;
      case 115:
        clickedItem = menu.ProcessMenu(ACTION_SELECT);
        break;
    }
  }

  if (clickedItem > 0)
  {
    // Logic for Root menu
    if (menu.CurrentMenu == mnuRoot)
      switch (clickedItem)
      {
        case 1:
          menu.InitMenu(mnuSubmenu1, cntSubmenu1, 1);
          break;
        case 2:
          menu.InitMenu(mnuSubmenu2, cntSubmenu2, 1);
          break;
        case 3:
          menu.InitMenu(mnuSubmenu3, cntSubmenu3, 1);
          break;
        case 4:
          menu.MessageBox("Some message!");
          break;
      }
    // Logic for Submenu 1
    else if (menu.CurrentMenu == mnuSubmenu1)
      switch (clickedItem)
      {
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
          menu.MessageBox("Item clicked");
          break;
        case 6:
          menu.InitMenu(mnuRoot, cntRoot, 1);
          break;
      }
    // Logic for Submenu 2
    else if (menu.CurrentMenu == mnuSubmenu2)
      switch (clickedItem)
      {
        case 1:
          menu.MessageBox("On");
          break;
        case 2:
          menu.MessageBox("Off");
          break;
        case 3:
          menu.InitMenu(mnuRoot, cntRoot, 2);
          break;
      }
    // Logic for Submenu 3
    else if (menu.CurrentMenu == mnuSubmenu3)
      switch (clickedItem)
      {
        case 1:
          menu.MessageBox("Enabled");
          break;
        case 2:
          menu.MessageBox("Disabled");
          break;
        case 3:
          menu.InitMenu(mnuRoot, cntRoot, 3);
          break;
      }

  }
}

and the accompaining TestMenu.h

// required for "const char" and "PROGMEM"
#define _PROG_TYPES_COMPAT_
#include <avr/pgmspace.h>
#include <Wire.h>

// texts for menus

const char itmBack[] PROGMEM = "< Back";
const char itmOn[] PROGMEM = "On";
const char itmOff[] PROGMEM = "Off";
const char itmEnabled[] PROGMEM = "Enabled";
const char itmDisabled[] PROGMEM = "Disabled";

const char itmRoot[] PROGMEM = "Root menu";
const char itmSubmenu1[] PROGMEM = "Submenu 1";
const char itmSubmenu2[] PROGMEM = "Submenu 2";
const char itmSubmenu3[] PROGMEM = "Submenu 3";
const char itmMessageBox[] PROGMEM = "Message box";
const char itmItem1[] PROGMEM = "Item 1";
const char itmItem2[] PROGMEM = "Item 2";
const char itmItem3[] PROGMEM = "Item 3";
const char itmItem4[] PROGMEM = "Item 4";
const char itmItem5[] PROGMEM = "Item 5";

////////////////////////////////////////////////////////////////
// menus - first item is menu title and it does not count toward cnt

const char * mnuRoot[] = {
  itmRoot,
  itmSubmenu1,itmSubmenu2,itmSubmenu3,itmMessageBox};
const int cntRoot = 4;

const char * mnuSubmenu1[] = {
  itmSubmenu1,
  itmItem1,itmItem2,itmItem3,itmItem4,itmItem5,itmBack};
const int cntSubmenu1 = 6;

const char * mnuSubmenu2[] = {
  itmSubmenu2,
  itmOn,itmOff,itmBack};
const int cntSubmenu2 = 3;

const char * mnuSubmenu3[] = {
  itmSubmenu3,
  itmEnabled,itmDisabled,itmBack};
const int cntSubmenu3 = 3;

Thanks again.