I have nearly a working Base for my project. But if I uncomment the Item 5 to have the same structure as the other menus, the display remains black. I dont get my mistake.
Who can give me a hint?
I want to let it run on a Nano.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// OLED width and height
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// OLED reset pin (usualy do not use)
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Rotary Encoder pins
const int encoderPinA = 2;
const int encoderPinB = 4;
const int encoderButtonPin = 3;
class Menu {
private:
char** items;
int numItems;
int currentIndex;
char* title;
Menu* parentMenu;
public:
Menu(char** menuItems, int itemCount, char* menuTitle, Menu* parent = nullptr) {
items = menuItems;
numItems = itemCount;
currentIndex = 0;
title = menuTitle;
parentMenu = parent;
}
void nextItem() {
currentIndex = (currentIndex + 1) % numItems;
}
void previousItem() {
currentIndex = (currentIndex - 1 + numItems) % numItems;
}
void setCurrentIndex(int index) {
currentIndex = index;
}
char* selectItem() {
return items[currentIndex];
}
void displayMenu() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(title);
display.setTextSize(1);
int start = max(0, currentIndex - 2);
int end = min(numItems, start + 5);
for (int i = start; i < end; i++) {
if (i == currentIndex) {
display.fillRect(0, 14 + (i - start) * 12, SCREEN_WIDTH, 14, WHITE);
display.setTextColor(BLACK);
} else {
display.setTextColor(WHITE);
}
display.setCursor(0, 17 + (i - start) * 12);
display.print(items[i]);
}
display.display();
}
Menu* getParentMenu() {
return parentMenu;
}
int getCurrentIndex() {
return currentIndex;
}
};
// Menu Items
const char* mainMenuItems[] = { "Item A", "Item B", "Item C", "Item D", "Item E" };
const char* subMenu1Items[] = { "SubItem A1", "SubItem A2", "SubItem A3", "Back" };
const char* subMenu2Items[] = { "SubItem B1", "SubItem B2", "SubItem B3", "Back" };
const char* subMenu3Items[] = { "SubItem C1", "SubItem C2", "SubItem C3", "Back" };
const char* subMenu4Items[] = { "SubItem D1", "SubItem D2", "SubItem D3", "Back" };
const char* subMenu5Items[] = { "SubItem E1", "SubItem E2", "SubItem E3", "Back" };
const int numMainMenuItems = sizeof(mainMenuItems) / sizeof(mainMenuItems[0]);
const int numSubMenu1Items = sizeof(subMenu1Items) / sizeof(subMenu1Items[0]);
const int numSubMenu2Items = sizeof(subMenu2Items) / sizeof(subMenu2Items[0]);
const int numSubMenu3Items = sizeof(subMenu3Items) / sizeof(subMenu3Items[0]);
const int numSubMenu4Items = sizeof(subMenu4Items) / sizeof(subMenu4Items[0]);
const int numSubMenu5Items = sizeof(subMenu5Items) / sizeof(subMenu5Items[0]);
// Menu objects
Menu mainMenu(mainMenuItems, numMainMenuItems, "Main Menu");
Menu subMenu1(subMenu1Items, numSubMenu1Items, "SubMenuA", &mainMenu);
Menu subMenu2(subMenu2Items, numSubMenu2Items, "SubMenuB", &mainMenu);
Menu subMenu3(subMenu3Items, numSubMenu3Items, "SubMenuC", &mainMenu);
Menu subMenu4(subMenu4Items, numSubMenu4Items, "SubMenuD", &mainMenu);
Menu subMenu5(subMenu5Items, numSubMenu5Items, "SubMenuE", &mainMenu);
// Variable that holds the current menu
Menu* currentMenu = &mainMenu;
// Rotary Encoder Variables
volatile long encoderValue = 0;
long lastencoderValue = 0;
bool buttonPressed = false;
void buttonPress() {
buttonPressed = true;
}
// Encoder read function
void updateEncoder() {
int ENCB = digitalRead(encoderPinB);
if (ENCB > 0) {
encoderValue++;
} else {
encoderValue--;
}
}
/*void selectedItemFunc(const char* item) {
char buffer[40];
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Selected:");
display.setCursor(0, 30);
display.print(item);
display.display();
delay(1000);
}*/
void setup() {
Serial.begin(115200);
// OLED starting
display.begin(SSD1306_EXTERNALVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();
// Set Rotary Encoder pins as input
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
pinMode(encoderButtonPin, INPUT_PULLUP);
// Set interrupt operation for encoder inputs
attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, RISING);
attachInterrupt(digitalPinToInterrupt(encoderButtonPin), buttonPress, FALLING);
// Show menu item at startup
currentMenu->displayMenu();
}
void loop() {
// Check encoder value and update menu
if (encoderValue != lastencoderValue) {
if (encoderValue > lastencoderValue) {
currentMenu->nextItem();
} else {
currentMenu->previousItem();
}
lastencoderValue = encoderValue;
currentMenu->displayMenu();
}
// Select item when Encoder button is pressed
if (buttonPressed) {
buttonPressed = false;
if (currentMenu == &mainMenu) {
switch (currentMenu->getCurrentIndex()) {
case 0:
currentMenu = &subMenu1;
currentMenu->setCurrentIndex(0);
break;
case 1:
currentMenu = &subMenu2;
currentMenu->setCurrentIndex(0);
break;
case 2:
currentMenu = &subMenu3;
currentMenu->setCurrentIndex(0);
break;
case 3:
currentMenu = &subMenu4;
currentMenu->setCurrentIndex(0);
break;
/*case 4: currentMenu = &subMenu5; currentMenu->setCurrentIndex(0);
break;*/
/*default: selectedItemFunc(currentMenu->selectItem());
break;*/
}
} else if (currentMenu == &subMenu1) {
switch (currentMenu->getCurrentIndex()) {
case 3:
currentMenu = currentMenu->getParentMenu();
break;
}
} else if (currentMenu == &subMenu2) {
switch (currentMenu->getCurrentIndex()) {
case 3:
currentMenu = currentMenu->getParentMenu();
break;
}
} else if (currentMenu == &subMenu3) {
switch (currentMenu->getCurrentIndex()) {
case 3:
currentMenu = currentMenu->getParentMenu();
break;
}
} else if (currentMenu == &subMenu4) {
switch (currentMenu->getCurrentIndex()) {
case 3:
currentMenu = currentMenu->getParentMenu();
break;
}
}
/*else if (currentMenu == &subMenu5) {
switch (currentMenu->getCurrentIndex()) {
case 3: currentMenu = currentMenu->getParentMenu();
break;
}
}*/
currentMenu->displayMenu();
}
}