The SerialMenu library: make menus on your serial console in seconds!

If you need to read user input on the serial console for your Arduino program, this is it! Just make a menu they can choose options from.

SerialMenu is a helper library to make quick work of creating menus and sub-menus on the Serial console. It is also extremely memory efficient!

I wrote it to help me quickly write prototyping code for an animatronics project where I kept changing the menu and it was becoming tedious to manage. This allows me to set values for the motor limits and enable/disable movement.

Benefits:

  • Very concise way to declare menus and associated callback functions
  • Low memory footprint (5 bytes per menu entry)
  • Supports storing menu text in Flash memory - PROGMEM to save RAM
  • Supports Lambda functions
  • Simple sub-menu arborescence creation

Menus are defined in an array, so the whole definition is localized, compact and quick to implement. This helps greatly supportability of your project.

This library supports RAM and PROGMEM/Flash menu text storage, so you don't waste precious memory, and you can make complex menus by only spending 5 bytes per menu entry. There is a small ~ 43B one time cost overhead.
The library is compatible with a "doing many things at the same time" multitasking approach. The Serial port is checked at every loop() iteration for new user input, but exits right away if no activity is detected.
The menus have callbacks that only trigger when an input is detected. Those can be declared as a concise lambda function or call a function you declare normally.

Internally the library defines 2 classes, one using 5 bytes for each menu entry that holds a string pointer, function pointer and key, and one singleton class which requires 12 bytes, that tracks which menu is current and handles the I/O and running the callback functions.

Spread the word. Help me help people find this tool when they need it!

Vote Karma if you like the libraries I am contributing.

Example

#include <SerialMenu.hpp>

// Some globals you want to update sometimes.
float f = 0;
int16_t i = 0;

void bar() {
Serial.println("choice bar");
i = menu.getNumber<int16_t>("enter integer: ");
}

// We can use lambda functions to keep menu callback with the menu, aka {code}
// or you can use a normal function just by passing its name, like bar for this example.
const SerialMenuEntry mainMenu[] = {
{"Bar", false, 'm', bar },
{"One", false, '1', { Serial.println("choice 1"); } },
{"Menu", false, 'm', { menu.show(); } },
{"Float", false, 'F', { f = menu.getNumber("enter float: "); } }
};

// Auto-compute there are 4 menu entries
constexpr uint8_t menuSize = GET_MENU_SIZE(mainMenu);

// Main arduino code: what follows is the only thing you need to add
// to display and run the menu.

void setup() {
menu.load(mainMenu, menuSize);
menu.show();
}

void loop() {
// Tell menu how long is the delay for the loop or put 1.
menu.run(100);
// Add your code to do actuall stuff
delay(100);
}

Here's a video of the menu in action:

Screen Shot 2019-11-14 at 3.37.41 AM.png

Screen Shot 2019-11-14 at 3.37.41 AM.png