LCD Menu library

Hi all,

I created an LCD menu library for a project I was working on, and I figured others may be able to reuse it so I have published it under a BSD license on github. (Just let me know if you want a different license, I am happy to re-publish for you)

The library is designed to make it easy to create a menu-driven interface on a simple LCD such as a 16x2 or 16x4. The library depends on the Liquid Crystal library to do all the drawing, but abstracts away some of the menu-intensive code.

The user is responsible for hooking up hardware navigation buttons/devices to the menu code, so you can choose when to pass control to the Menu library to do your menu navigation, and when to do do your own thing with the LCD.

For instance, if you have an app that is using the LCD to do its primary output, you can use this library to create a Settings UI to do some tweaking (code below is for a Sous vide monitor):

  //Set up the root node first
  MenuEntry * p_menuEntryRoot = new MenuEntry("Settings", NULL, NULL);
  g_menuManager.addMenuRoot( p_menuEntryRoot );
  g_menuManager.addChild( new MenuEntry("Temp ", NULL, TempCallback) );
  g_menuManager.addChild( new MenuEntry("Time", NULL, TimeCallback ) );
  g_menuManager.addChild( new MenuEntry("Beep Off", (void *)&g_beep, MenuEntry_BoolFalseCallbackFunc) );
  g_menuManager.addChild( new MenuEntry("Beep On", (void *)&beep, MenuEntry_BoolTrueCallbackFunc) );
  g_menuManager.addChild( new MenuEntry("Back", (void *)&g_MenuManager, MenuEntry_BackCallbackFunc) );\

There is also some support for getting a number from the user:

void TempCallback( char* menuText, void *userData )
{
  char *label = "Temp F";
  int numLabelLines = 1;
  int min = 100;
  int max = 200;
  int start = 135;
  //Each user input action (such as a turn of rotary enocoder or push of button
  //will step this amount
  int iStep = 1;
  
  g_menuManager.DoIntInput( min, max, start, step, &label, numLabelLines, &g_temp );
}

That code will get a number from the user and set it in the g_temp variable.

This code was designed to work with an LCD and a clickable rotary encoder, such as this one: Rotary Encoder - COM-09117 - SparkFun Electronics. To use the rotary encoder, you can detect rotate up, rotate down, and click. You pass these events to the MenuManager as "Menu_UP", "Menu_Down", and "Menu_Select" actions. If you have a seperate hardware back button, you can pass this as "Menu_Back", or you can add "Back" items to all your menus to support backing up.

The code works well for simple use cases, but I hope to add more functionality soon.

The setup is a bit tough to read for more complicated menus, so if you have suggestions for a simpler way to declare tree structures such as the menus built here, I would be all ears.

The code includes an fairly complex sample stopwatch/timer. You can get it here: GitHub - DavidAndrews/Arduino_LCD_Menu: This library creates menu systems primarily useful for 16x2 or 16x4 LCD displays.

Please give it a try and let me know what you think. The coding style is all over the place. I am trying to clean it up as I go, but I am not there yet. I will [soon] remove all the hungarian and try to settle on something consistent. My corporate coding style is showing, but I am working on exercising it from my brain.

Testing has been a bit ad-hoc, but I will try to address bugs quickly or accept submitted bug fixes even quicker.

We are creating an open hardware project to go along with this, which should be ready in time for Maker Faire, so keep an eye open at http://www.authenticinvention.com for announcements.

David

David,

Very nice! Would you put up some videos to show case your library? I know a few of us also have our own menu/user interface libraries. Here is mine for your information:

I also integrated some features of my library on a display/keypad panel produce I designed last summer:

Hi
Good work and nice video.

In the last month i have seen several Menu Lib announced in the Arduino forum. I would suggest to add the Menu-Lib also to
Arduino Playground - InterfacingWithHardware so that we get an overview on the existing implementations.

Oliver

Thanks for the feedback. I am definitely going to check out the phi libraries. That library looks very full featured and I especially like the broad range of input gathering code. I have added LCD Menu to the playground as well, thanks for the suggestion.

If anyone has an LCD/Arduino sitting around already wired and using Liquid Crystal, I'd love feedback on whether it compiles and works on your setup, even just the sample sketch provided. I haven't been able to run it on anything except my one configuration, but I think it should work on just about anything Liquid Crystal supports. I think it should just work for a 4 line display, but I also haven't been able to test that yet either.

David

I did get it to work using fm's replacement LiquidCrystal library running in 4 bit mode.
(rather than using the stock Arduino LiquidCrystal library)
https://bitbucket.org/fmalpartida/new-liquidcrystal/overview

What I wanted to do but was not able to do was to run it on a i2c or ShiftRegister interface
to the LCD.
This was because of the linkage that assumes a LiquidCrystal type constructor.

If you want to support fm's library to allow support for other interfaces other than 4 bit,
have a look a different library done recently that works with fm's library for
how the linkage works.
http://code.google.com/p/arduino-lcd-bitmap/

I also noticed that when I renamed the .ino file back to .pde to try it on 0022,
the sketch and code would not compile. It failed on the references to new and delete.
Not sure how this changed in 1.0

--- bill

To use properly the fm library you must use, inside the library, the LCD abstract class.
That allows you, in the sketch, to use the different "sublibraries" (as, for instance, the I2c) and their related subclasses (for instance LiquidCrystal_I2C).
I use such an approach in my MENWIZ menu library and it works fine.
By the way, if you are interested you can find my lib at GitHub - brunialti/MENWIZ: ARDUINO LCD menu library: short user code to manage complex menu structures
Here attached you can find a quick tour to menwiz (sorry for my english).

QUICK TOUR.pdf (89.2 KB)

I see some more entries on Playground. Thanks for that!

Oliver

Hi liudr - I took a look at the phi libraries. Very nice! If it was available for commercial use, I would move over to yours. I have looked it the way it works and taken some inspiration, so thanks!

David

DavidAndrews:
Hi liudr - I took a look at the phi libraries. Very nice! If it was available for commercial use, I would move over to yours. I have looked it the way it works and taken some inspiration, so thanks!

David

Thanks David. Just drop a reply on my blog if you want commercial use. I don't charge more than an arduino board for a license to use all my libraries any amount of times in commercial products.

Someone asked if we could post a video of the library working. You can see it in operation here: http://www.kickstarter.com/projects/988159748/robotic-minion-start-kit-arduino-compatible (This is a link to our kickstarter video, sorry, I don't have anything else built to show it off :frowning: )

David

I'm kind of wondering how to "exit" the menu.. when i select a menu entry, i want it to execute a callback (which works), then NOT return to the menu.. the callback will change the interface to a "page" of settings - i'm envisioning 4 columns with top row of labels and bottom row of values.

Otherwise, this is working pretty well.. I also would like to see some kind of input subclassing like phi prompt.. I tried the PHI library, but it also takes Mu control over my app so I'm not really able to accomplish what i want. Plus the init code in that library is pretty nastyy..

yes i think it is the best way that my friend said, add this Arduino Playground - InterfacingWithHardware into your menu

good luck my friend

I think this library is a fantastic resource once a keyboard is integrated into the code and I found that very simple to do using a class I built for a 5 button analog keyboard that supports auto typing if arrow keys are held down and a Long Press on the Select key to act as a back button.

Its been a long time since I have played with Arduino and once I got going with this library, I ran out of memory before I completed building my menu.

I have found some very inefficient code that duplicates strings passed to the function that I think doubles memory usage in the MenuEntry constructor.

So when building a menu you make calls like this:

 g_menuManager.addChild( new MenuEntry("Set Home", NULL, HomeSetCallback) )

and then the constructor promptly creates another copy on the stack like this:

  m_menuText = strdup(menuText);

It is easy enough to halve memory usage by first defining the menu prompts as static strings and modify the constructor so it does

 m_menuText = menuText;

but ideally it would be good to be able to use PROGMEM F() strings which will further reduce stack usage. I tried something like changing the definition from

MenuEntry::MenuEntry( char * menuText, void * userData, MENU_ACTION_CALLBACK_FUNC func)

to

MenuEntry( const __FlashStringHelper * menuText, void * userData, MENU_ACTION_CALLBACK_FUNC func);

And calling it with

 g_menuManager.addChild( new MenuEntry(F("Set Home"), NULL, HomeSetCallback) )

but I ran into compiler errors.

It has been 20 odd years since I have done much with C and I am struggling with the complex casts to get this to work. a few tips would be appreciated as a Flash memory version of this would be great and should not require too much effort.

Hi,

is this library going to be updated? I've got it to work but the Arduino IDE still shows many warnings and I'm hesitant to use it.

It should ...
I hope to delivery the next version on Xmas time...
Let me know about the IDE warning/errors

brunialti:
It should ...
I hope to delivery the next version on Xmas time...
Let me know about the IDE warning/errors

I just took the sample code and when I compile I got this a lot (for every string):

warning: deprecated conversion from string constant to 'char*'

and some others too. I removed the library for the time being, so I don't have it right now.