LCD menu

This page explains how to implement a menu system using the existing TextLCD library (found here: and RPG library (found here: This was motivated by a need for an easy to implement and modular menu system. It lessens the difficulties of hardcoding menus. The system keeps track of cursor positions, input logic, and displays. Inspired in part by the Menbed project by Kyle Gilpin. His project can be seen here: Our system is a lot more lightweight, and slightly limited, but is easier to understand.

Below is an example.





The image above details an example set up.

Each menu that appears on the lcd screen are Menu objects, and Menu contains Selections. You can create as many menus, sub menus, and selections as you want and each selection can be tied to different functions. The navigator is what allows you to scroll through these menus and select selections through the aid of the RPG. The navigator can read whether the user wants to move up (CCW) or down (CW) and adjust the selection on the screen accordingly.

The basic calls are:

  • Menu menuName(menuID) This creates a menu object. Note, menuID is a character array (string):
  • Selection selection(function, position, child, text) This creates a selectable item, but is not attached to any menu.
    • Selections can be tied to functions, which is how this system incorporates program flow. Simply create a "function" for a set of code you want to execute, and tie it to a selection to have it execute when the RPG is depressed and the cursor is pointing that selection.
  • menuName.add(selection) This adds a selection to a menu.
    • It is easier to add and declare a selection at the same time: like so menuName.add(Selection(function, position, child, text))
      • The position parameter will soon be deprecated, but it's a good idea to increment as you add selections
  • Navigator navigator(rootMenu, RPG, LCD) A menu configuration must always include a root menu.

(Refer to the source for more details. Some objects must be passed by reference, in particular the LCD)

Basic Steps

To create the system similar the example program

  • Create a root menu Menu rootMenu("root menu");
  • Create any submenus Menu ledMenu("LED menu");
    • Add any selections ledMenu.add(Selection(&toggleLED1, 0, NULL, "Toggle LED1"));
    • Remember to add a selection to go back up in the menu hierarchy. Do this by letting the child menu point to the previous menu *ledMenu.add(Selection(NULL, 1, &rootMenu, "Go back");
  • Add submenus to the root (as selections with child parameters set to the submenus) rootMenu.add(Selection(NULL, 0, &ledMenu, "LED menu");
  • Assuming RPG and LCD are set up as below, create the Navigator Navigator navigator(&rootMenu, rpg, &lcd);
  • In a while loop (not recommended with a ticker, at least not yet), call navigator.poll(), which polls the system for user input

Sample program

Repository: lcd_menu


Import libraryMenu

Library of menu structure


Pin numberTextLCD pinsmbed pins
3VO0V, via 1k resistor
7D0not connected
8D1not connected
9D2not connected
10D3not connected
Pin numberRPG pinsmbed pins
  • When looking from the top, the RPG pin are:

[A] [C] [B]


[1] [2]


Tect LCD Cookbook:

RPG Cookbook:

Author's notes

Comments welcome!

Possible changes in the future:

  • Compatibility with other LCDs
  • Allow selections to be associated with variables for watching or modifying (similar to Kyle Gilpin's project)
  • More functionality such as methods for opening files

2 comments on LCD menu:

09 Dec 2013

This reads a lot like a menu system I intend to develop, in my case I'll be using a VFD with a few "bells and whistles" that regular LCD modules don't support and I'll need to support numeric parameters.

I do wonder if its possible to declare some of the data as constants rather than having to build the data-structure at run-time?

02 Jul 2015

How to replace rotary encoder with simple up, down and select buttons?

Please log in to post comments.