Hello everyone. I'm trying to make a menu application with Arduino Uno. However, I couldn't get it right. I keep starting over, but I still can't reach a result. If you have any suggestions or corrections, I would appreciate it.
I will use I2C 16x2 Led Display and 5 buttons.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const int BUTTON1_PIN = 2;
const int BUTTON2_PIN = 3;
const int BUTTON3_PIN = 4;
const int BUTTON4_PIN = 5;
const int BUTTON5_PIN = 6;
LiquidCrystal_I2C lcd(0x3F, 16, 2);
enum MainMenu {
MENU_1,
MENU_2,
MENU_3,
};
enum SubMenu {
SUBMENU_1,
SUBMENU_2,
};
int variable1 = 0;
bool variable2 = false;
void setup() {
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);
pinMode(BUTTON4_PIN, INPUT_PULLUP);
pinMode(BUTTON5_PIN, INPUT_PULLUP);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Main Menu");
delay(1000);
}
void loop() {
static MainMenu mainMenu = MENU_1;
static SubMenu subMenu = SUBMENU_1;
if (readButton()) {
if (subMenu == SUBMENU_1) {
handleMainMenu(mainMenu);
if (mainMenu == MENU_2) {
subMenu = SUBMENU_2;
}
}
if (subMenu == SUBMENU_2) {
handleSubMenu(subMenu);
if (mainMenu != MENU_2) {
subMenu = SUBMENU_1;
}
}
}
}
int printMainMenu(MainMenu menu) {
lcd.clear();
switch (menu) {
case MENU_1:
lcd.print("1. Sub Menu");
lcd.setCursor(0, 1);
lcd.print("2. Sub menu");
break;
case MENU_2:
lcd.print("1. Option 1");
lcd.setCursor(0, 1);
lcd.print("2. Option 2");
lcd.setCursor(10, 1);
lcd.print("3. Option 3");
lcd.setCursor(0, 0);
lcd.print(variable1);
break;
case MENU_3:
lcd.print("1. Option 1");
lcd.setCursor(0, 1);
lcd.print("2. Option 2");
lcd.setCursor(10, 1);
lcd.print("3. Option 3");
lcd.setCursor(0, 0);
lcd.print(variable2);
break;
}
}
int handleMainMenu(MainMenu& menu) {
printMainMenu(menu);
switch (menu) {
case MENU_1:
if (digitalRead(BUTTON1_PIN) == HIGH) {
function1();
break;
}
if (digitalRead(BUTTON2_PIN) == HIGH) {
function2();
break;
}
if (digitalRead(BUTTON5_PIN) == HIGH) {
menu = MENU_2;
break;
}
break;
case MENU_2:
if (digitalRead(BUTTON1_PIN) == HIGH) {
variable1++;
break;
}
if (digitalRead(BUTTON2_PIN) == HIGH) {
variable1--;
break;
}
if (digitalRead(BUTTON3_PIN) == HIGH) {
variable2 = !variable2;
break;
}
if (digitalRead(BUTTON5_PIN) == HIGH) {
menu = MENU_3;
break;
}
break;
case MENU_3:
if (digitalRead(BUTTON1_PIN) == HIGH) {
variable2 = true;
break;
}
if (digitalRead(BUTTON2_PIN) == HIGH) {
variable2 = false;
break;
}
if (digitalRead(BUTTON5_PIN) == HIGH) {
menu = MENU_1;
break;
}
break;
}
}
int handleSubMenu(SubMenu& submenu) {
lcd.clear();
switch (submenu) {
case SUBMENU_1:
lcd.print("Sub Menu 1");
// Submenu 1 operations
break;
case SUBMENU_2:
lcd.print("Sub Menu 2");
// Submenu 2 operations
break;
}
}
int readButton() {
if (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW || digitalRead(BUTTON3_PIN) == LOW) {
return 1;
} else {
return 0;
}
}
My expectation is to have 3 main menus that I can navigate, to have submenus within these main menus and to run functions in the options in these submenus. Instead, when I upload the code to the arduino, the screen resets itself constantly or freezes.
Sounds like a wiring problem, unstable connections, etc. Please post a photo of a hand drawn wiring diagram, with pins and parts clearly labeled and a photo of your setup.
Test the setup with this program stub at the bottom, which just prints one line on the screen. Once that is working, add one tiny bit at t time.
Some of that code makes no sense, and I can't imagine why it compiles and loads.
Where is function1() defined, for example?
if (digitalRead(BUTTON1_PIN) == HIGH) {
function1();
break;
}
What does this do? Where does the pointer come from?
First, function1() function2() etc. functions will be added later.
second question : the handleButton function does not have a pointer. The function takes two arguments: MainMenu& mainMenu and SubMenu& subMenu. Here the & symbol indicates that the variables passed to the function are reference parameters. That is, the variables of type MainMenu and SubMenu passed to the function can be changed inside the function and these changes will also take effect outside. This means that they are not pointers to the function, but reference parameters.
To design, code and test a sketch for a menue and submenue function is a complex task.
Useful to do this are structured arrays and some other powerfull C++ instruction out of the OOP toolbox.