A well-designed menu system transforms a simple microcontroller project into a professional, user-friendly device. Using an LCD display with a rotary encoder, you can build intuitive multi-level navigation for settings, data display, and device control. This guide covers designing and coding a complete, reusable menu engine for Arduino.
Why Build a Menu System
- Almost every embedded product has a menu (thermostats, 3D printers, oscilloscopes)
- A menu makes your project configurable without reprogramming
- Users can adjust settings, view data, and trigger actions
- One encoder replaces multiple buttons for a cleaner interface
Hardware: LCD + Rotary Encoder
- 16×2 or 20×4 LCD with I2C: Proven, affordable, easy to read
- Rotary encoder with push button: Rotate to navigate, press to select/enter
- Only 4 wires for LCD (I2C) + 3 wires for encoder = 7 total GPIO pins
Menu Architecture Design
Structure your menu as a tree:
Main Menu
|- Settings
| |- Brightness [0-100]
| |- Contrast [0-100]
| |- Language [EN/HI]
|- Sensors
| |- Temperature
| |- Humidity
|- System
| |- Reset
| |- About
| |- WiFi Config
Each menu item can be a sub-menu (opens more items), a value editor (adjust a number), or an action (execute a function).
Implementing the Menu Engine
struct MenuItem {
const char* label;
MenuItem* subMenu;
int subMenuSize;
void (*action)();
int* value;
int minVal, maxVal;
};
void navigateMenu(MenuItem* menu, int size) {
int selection = 0;
while(true) {
lcd.clear();
lcd.setCursor(0,0); lcd.print(">");
lcd.print(menu[selection].label);
if(selection+1 0 && selection < size-1) selection++;
if(dir 0) selection--;
if(buttonPressed()) {
if(menu[selection].subMenu)
navigateMenu(menu[selection].subMenu, menu[selection].subMenuSize);
else if(menu[selection].action)
menu[selection].action();
}
}
}
Sub-Menus and Settings Pages
Sub-menus open when the user presses the encoder on a menu item that has children. Value editing allows the user to rotate the encoder to adjust a numeric value (brightness, threshold, timer duration) and press to confirm.
Saving Settings to EEPROM
Save user settings to Arduino EEPROM so they persist across power cycles:
#include <EEPROM.h>
void saveSettings() {
EEPROM.put(0, brightness);
EEPROM.put(4, contrast);
}
void loadSettings() {
EEPROM.get(0, brightness);
EEPROM.get(4, contrast);
}
Making the Menu Library Reusable
Package your menu code as a reusable class that can be dropped into any project. Define menu structures as arrays and pass them to the menu engine. This way, you write the menu engine once and reuse it across all your projects with different menu structures.
Recommended LCD and Encoder Modules
Frequently Asked Questions
Can this menu system work with OLED displays?
Yes. Replace the LCD print commands with OLED drawing functions. The menu logic is identical — only the display output changes.
How many menu levels can I have?
As many as Arduino’s RAM allows. In practice, 3-4 levels deep is sufficient for most projects. Deeper menus become confusing for users.
Is a rotary encoder better than buttons?
For menus, yes. One encoder replaces 3 buttons (up, down, select) and provides smooth, fast scrolling through long lists.
Shop Display Modules at Zbotic.in
India’s trusted source for OLED, LCD, TFT, LED matrices, and more. Fast shipping across India.
Add comment