DEV Community

Hedy
Hedy

Posted on

How to Make a Menu on Arduino Nano?

You make a menu on an Arduino Nano by doing two things:

  1. Decide where the menu is shown (Serial Monitor? LCD? OLED?).
  2. Write a simple state machine that reacts to user input and changes “screens”.

Let me show you a very clear example using the Serial Monitor (no extra hardware needed), then briefly how you’d adapt it to an LCD + buttons.

1. Serial Monitor menu (simplest way)
Idea

  • Show a text menu in the Serial Monitor.
  • The user presses keys like 1, 2, 3…
  • The code runs different actions based on that input.

We’ll build a menu like this:

  • 1 → Blink LED
  • 2 → Read analog value from A0
  • 3 → Go into a small “settings” submenu
  • b → Back to main menu when in submenu

Wiring

For this basic example:
No extra wiring needed.

  • Use the built-in LED on pin 13 (LED_BUILTIN)
  • Optionally connect a potentiometer to A0:
    • One side → 5V
    • Other side → GND
    • Middle pin → A0

Full example code

// Simple menu for Arduino Nano via Serial Monitor

enum MenuState {
  MENU_MAIN,
  MENU_SETTINGS
};

MenuState currentMenu = MENU_MAIN;

const int ledPin = LED_BUILTIN;
const int analogPin = A0;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  while (!Serial) {
    ; // Wait for Serial on some boards (not strictly needed on Nano)
  }

  Serial.println(F("=== Arduino Nano Menu Demo ==="));
  printMainMenu();
}

void loop() {
  // Check if the user entered something
  if (Serial.available() > 0) {
    char c = Serial.read();

    // Ignore line endings
    if (c == '\n' || c == '\r') {
      return;
    }

    if (currentMenu == MENU_MAIN) {
      handleMainMenuInput(c);
    } else if (currentMenu == MENU_SETTINGS) {
      handleSettingsMenuInput(c);
    }
  }
}

// ---------------- Main Menu ----------------

void printMainMenu() {
  Serial.println();
  Serial.println(F("===== MAIN MENU ====="));
  Serial.println(F("1) Blink LED once"));
  Serial.println(F("2) Read analog A0"));
  Serial.println(F("3) Settings submenu"));
  Serial.println(F("x) Stop LED (turn off)"));
  Serial.print(F("Select option: "));
}

void handleMainMenuInput(char choice) {
  switch (choice) {
    case '1':
      Serial.println(F("\n[Blink] LED will blink once."));
      blinkLedOnce();
      printMainMenu();
      break;

    case '2':
      Serial.println(F("\n[Analog] Reading A0..."));
      readAnalogOnce();
      printMainMenu();
      break;

    case '3':
      Serial.println(F("\n[Settings] Entering settings menu."));
      currentMenu = MENU_SETTINGS;
      printSettingsMenu();
      break;

    case 'x':
    case 'X':
      Serial.println(F("\n[LED] Turning LED off."));
      digitalWrite(ledPin, LOW);
      printMainMenu();
      break;

    default:
      Serial.println(F("\n[Error] Invalid choice."));
      printMainMenu();
      break;
  }
}

// ---------------- Settings Menu ----------------

void printSettingsMenu() {
  Serial.println();
  Serial.println(F("===== SETTINGS MENU ====="));
  Serial.println(F("a) Turn LED ON"));
  Serial.println(F("b) Back to main menu"));
  Serial.print(F("Select option: "));
}

void handleSettingsMenuInput(char choice) {
  switch (choice) {
    case 'a':
    case 'A':
      Serial.println(F("\n[Settings] LED is now ON."));
      digitalWrite(ledPin, HIGH);
      printSettingsMenu();
      break;

    case 'b':
    case 'B':
      Serial.println(F("\n[Settings] Returning to main menu."));
      currentMenu = MENU_MAIN;
      printMainMenu();
      break;

    default:
      Serial.println(F("\n[Error] Invalid choice in settings."));
      printSettingsMenu();
      break;
  }
}

// ---------------- Helper functions ----------------

void blinkLedOnce() {
  digitalWrite(ledPin, HIGH);
  delay(300);
  digitalWrite(ledPin, LOW);
  delay(300);
}

void readAnalogOnce() {
  int raw = analogRead(analogPin);
  float voltage = raw * (5.0 / 1023.0);

  Serial.print(F("Raw A0 = "));
  Serial.print(raw);
  Serial.print(F("  | Voltage ≈ "));
  Serial.print(voltage, 2);
  Serial.println(F(" V"));
}
Enter fullscreen mode Exit fullscreen mode

How to use it

  1. Upload the sketch to your Arduino Nano.
  2. Open Serial Monitor (Ctrl+Shift+M).
  3. Set baud rate to 9600.
  4. You’ll see the MAIN MENU.
  5. Type 1, 2, 3, x, a, b, etc. and press Enter.

You just built a simple text-based menu system with:

  • A main menu
  • A submenu
  • Different actions for each item

2. How to turn this into an LCD + buttons menu

Once you have the state machine idea, moving to an LCD is just about changing I/O:

  • Instead of Serial.print(...) → use lcd.print(...) with the LiquidCrystal library.
  • Instead of reading Serial.read() → read buttons:
    • “UP” button → decrease menu index
    • “DOWN” button → increase menu index
    • “SELECT” button → choose current item

Pseudo-logic:

int menuIndex = 0;
const int menuCount = 3;

void loop() {
  if (buttonUpPressed()) {
    menuIndex--;
    if (menuIndex < 0) menuIndex = menuCount - 1;
    drawMenu();
  }

  if (buttonDownPressed()) {
    menuIndex++;
    if (menuIndex >= menuCount) menuIndex = 0;
    drawMenu();
  }

  if (buttonSelectPressed()) {
    runMenuItem(menuIndex);
  }
}
Enter fullscreen mode Exit fullscreen mode

Where:

  • drawMenu() redraws text on the LCD,
  • runMenuItem() runs the selected action.

3. Key takeaway

A menu on Arduino Nano is just:

  • A current state (MENU_MAIN, MENU_SETTINGS, or a menuIndex)
  • A way to print that state (Serial, LCD, OLED)
  • A way to read user input (Serial characters, buttons, encoder)
  • A switch / if block that runs different code for each choice

Top comments (0)