Arduino and LCD Keypad Shield

Arduino LCD Menu Library – Coding Menus the Easy Way

You may have used an electronic device with a small Liquid Crystal Display (LCD) which has a textual hierarchical menu system for setting device configuration parameters. If you have tried writing menu code for your Arduino projects, you will recognise the challenge in developing a generic menu system for an open prototyping platform. This is because there are many input and display devices available, and a generic menu system must be independent of whichever input and display devices you wish to use. With our Arduino menu library, this independence is achieved by having the menu manager code use callback methods for handling user input and rendering the menu display.

To keep things simple, all coding examples have been targeted to work with an R3 Arduino Uno/Leonardo/Mega2560, and an LCD keypad shield similar to one illustrated above. There are numerous manufacturers of LCD keypad shields that have the same or similar pin connections, and you must ensure that the sample menu code uses the pin connections that are right for your shield. If the keypad buttons of your shield give different analog readings, you’ll need to make changes to file LcdKeypad.h. Bear in mind that the analog readings are not always consistent, which can lead to the occasional misreporting of a button press. Once you become familiar with the menu library, adapting it for use with other input and display devices should be straight-forward.

With numerous menu libraries readily available, why use this Arduino menu library? We think it is easier to use thanks to our online code generator, and has better memory efficiency with its use of PROGMEM. Watch the short video clip below and see for yourself.

Follow a Few Simple Steps to Build a LCD Menu

Step 1 – Download LCD Menu Sample Project

Download the following Arduino sample project for testing out your menus. You’ll need to find and install the TimerOne library for the code to compile.

Step 2 – Use Online Menu Builder

Our free online menu builder allows you to paste in a simple Xml representation of your menu, from which the Arduino menu source code is generated automatically. Use the sample Xml included in the project you just downloaded to get started.

Step 3 – Build Arduino Project

Copy the generated code and paste in to MenuData.h file of your Arduino project, overwriting existing content. Build and upload your Arduino project.

Step 4 – Test Your Menu

After successfully uploading your Arduino project, test out your menu. Now that you have a menu in place, you can work on the main logic of your application. If you need to rework your menu in the future, the MenuData.h file has a copy of the xml that was used to generate it, which you can copy and paste in to the online menu builder.

Using Menus in Your Own Code

You can use the downloaded sample Arduino project as a starting point for your own coding requirements. You will need to write your own code in the body of method processMenuCommand(byte cmdId) to determine what must be done when a menu item is selected. The cmdId parameter is the Id you associate with a menu item in your menu Xml file. Callback method getNavAction() handles user input, and callback method refreshMenuDisplay(byte refreshMode) renders the menu. To work with other input and display devices you’ll need to re-write the code in these methods. Some LCD keypad shields are not suited for hardware PWM backlight control, and as such the coding example uses a soft PWM alternative.

LCD Countdown Timer with Menu System

The source code for an Arduino countdown timer with multiple profiles can be downloaded from the link below:

The Select button on the LCD shield starts/stops a timer, with a long press resetting the timer. A long press of Up enters the menu. Up/Down/Right buttons are for navigating the menu, and Select for choosing a menu item. When an item is selected, Up/Down are used for changing values. When the Reset menu item is displayed, a long press of Select loads default configuration values. Digital pin 2 is used for activating a beeper for the alarm. Examining the source should give you good insight for using the menu system in your own projects. If you find this Arduino menu library guide useful, please share it.

New! Want to control your Arduino with an internet browser? Check out our new Arduino Web Server

Share on LinkedInShare on Google+Tweet about this on TwitterShare on Facebook

31 thoughts on “Arduino LCD Menu Library – Coding Menus the Easy Way

    1. Kashif Baig Post author

      Thanks Patrik for pointing out the Timer1 library. I’ll update the page accordingly.

      Reply
  1. Cameron H

    Hi,
    Love your menu templates. Is there a reasonably simple way of altering Template 4 to follow:

    Right button: descends down through menu tree which it does currently.
    Left button: ascends back through menu tree.
    Select button: performs functions.

    This would be the same as a Joystick with X/Y axis (operating like L and R buttons), and a stick push down (operating as the select button).

    these changes would really suit a home project I am working on.

    Regards,

    Cam H.

    Reply
    1. Kashif Baig Post author

      Hi Cameron. In the main project file there is a function getNavAction(). There is a line that is commented out regarding left button press. If you uncomment it, the left button will ascend up the tree. You should be able to further change the logic in this function to do as you require.

      I hope that helps.

      Reply
      1. Cameron H

        OK. Thanks. I will have to do some more stuff to try and change the function. I need the BACK button to do what the SELECT bottom does in moving up and down the menu.

        Reply
  2. John Hutchison

    Kashif, thanks for providing an awesome menu framework that is easy to use and set up.

    I am currently building a project on a Teensy 3.5 and the menu is working for all of the functions implemented so far but now I am adding a frequency counter to it and the TimerOne lib conflicts with the FreqMeasure lib for the teensy with the following message:

    /home/john/Downloads/arduino-1.8.1/hardware/teensy/avr/libraries/FreqMeasure/util/FreqMeasureCapture.h:126: multiple definition of `ftm1_isr’
    /tmp/arduino_build_880203/libraries/TimerOne/TimerOne.cpp.o:/home/john/Downloads/arduino-1.8.1/hardware/teensy/avr/libraries/TimerOne/TimerOne.cpp:34: first defined here
    /home/john/Downloads/arduino-1.8.1/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/bin/ld: Disabling relaxation: it will not work with multiple definitions
    collect2: error: ld returned 1 exit status

    Commenting out the TimerOne include fails as there are calls to things that don’t exist in the FreqMeasure lib:

    PFT_OS:97: error: ‘Timer1’ was not declared in this scope
    Timer1.initialize();
    ^
    &&
    ‘Timer1’ was not declared in this scope

    What in TimerOne is necessary as I would like to remove it if possible?

    Reply
    1. Kashif Baig Post author

      Hi John

      The TimerOne library is only used for display brightness, as some LCD shields have a problem with hardware PWM for brightness control. It should be straight forward to remove the dependency on TimerOne for brightness control. I hope that helps.

      Reply
    2. John Hutchison

      Kashif,

      I changed to using TimerThree and it now compiles. Still need to test it on the unit but I believe this will work.

      Reply
        1. John Hutchison

          Awesome, I removed all of the TimerOne deps and it’s working without any hacks. Thanks again.

          Reply
  3. John Hutchison

    Kashif, I am having an issue where the menu may jump intermittently to the previously selected item or all the way back to root when a button is pressed. This can happen with a short press, a hold (does not jump while held but may upon release), or a firm press (this actually works best but it still may jump). The menu does not jump while no buttons are pressed.

    Using a analogRead sketch I’ve found the buttons values are: 1, 223, 528, 782, 929, and 1023 for none.

    In the LcdKeypad.h I have set the buttons to 10, 235, 538, 792, and 939.

    Reply
    1. Kashif Baig Post author

      Hi John. In LcdKeypad.cpp, find the method buttonHandlerCycle(). Try performing a further analogRead(BUTTON_PIN) before assigning to analogReading variable, like so:

      analogRead (BUTTON_PIN);
      int analogReading = analogRead (BUTTON_PIN);

      Reply
      1. John Hutchison

        That worked, but I also had to set the sample time to 100 (probably does not need to be that high) in order to tighten it up a bit more.

        The (hopefully last) thing I am trying to get my head around is to clear rows 1-3 when moving up or down in the menu tree so the last displayed lcd.print() data is not displayed until another function is selected. I am using a 20×4 lcd, so only the first line is cleared. I’m eyeballing “width + 1” but am too tired to try any more tonight.

        Reply
  4. Dave OBrien

    Hi. Code looks great but is it possible to modify to use a rotary encoder ?

    I need a menu to run on a 20×4 LCD on a reprap discount smart controller that attaces to a ramps board with these pins :
    #define LCD_PINS_RS 16 // LCD control
    #define LCD_PINS_ENABLE 17 // LCD enable pin
    #define LCD_PINS_D4 23 // LCD signal pin
    #define LCD_PINS_D5 25 // LCD signal pin
    #define LCD_PINS_D6 27 // LCD signal pin
    #define LCD_PINS_D7 29 // LCD signal pin
    #define BTN_EN1 37 // Encoder left direction
    #define BTN_EN2 35 // Encoder right direction
    #define BTN_ENC 31 // Encoder Click

    Regards
    Dave

    Reply
    1. Kashif Baig Post author

      Hi Dave

      The best place to start would be the LcdMenuTemplate.ino source code file. There is a method getNavAction() where you can map rotary encoder input values to menu navigation commands. Once your code changes work, you’ll need to modify the refreshMenuDisplay() method to output to your 20×4 LCD. There is some code commented out there which when uncommented will output menus to the serial monitor. When you’ve understood how that works, you should be in a position to making the necessary changes to work with your LCD. Hope that helps.

      Kashif

      Reply
  5. Ben Owen

    Hi Kashif

    I was wondering how easy it would be to make this program work on a 20X4 display and have 4 menus to select from on one display

    Thank You

    Ben

    Reply
    1. Kashif Baig Post author

      Hi Ben. It is possible (but not easy) to make this work with 20×4 display. What I suggest you do (if you haven’t already) is to uncomment the code in refreshMenuDisplay() in the main file of the LcdMenuTemplate. This will output the menus to the serial monitor, and should help you understand how to display multiple menu items. You can try outputting to the serial monitor values from Menu1.getCurrentItemIndex(). I hope that helps.

      Reply
  6. Dimuthu

    How i connect “relay” this divice? Becouse i need to time off switch using relay.
    But i dont no where is the output pin i connect it.
    I am amateur to Arduino
    please help me to build it.
    i am sorry, my english is not well.

    Reply
  7. Jake

    Just love the work you have done with this menu Kashif. Still trying to figure it out though. I have 4 menu groups with 3 sub-menus in each and one menu option at the very end that has no sub-menus at all.
    Is there a limit to the number of main menu items? If so can it be changed and from where? Every time I paste my xml into the code generator on your website it errs with “There is an error in XML document (31, 7).” This line and col are at my final tag in the xml file which is followed by the last <Item Id= statement in the menu which will put the software into run mode after the initial system configuration via the menu.
    Any help you could provide would be greatly appreciated.

    Thanks in advance
    Jake

    Reply
    1. Kashif Baig Post author

      Thanks Jake. I don’t recall a limit in the number of items, so that shouldn’t be a problem. You could try pasting your xml in an online xml validator to see if you get more specific details. If not, share a link to your xml and I’ll see if I can spot the problem.

      Reply
      1. Barry Godusky

        Kashif, found the problem. Thanks for the quick reply. All working good at least in these first steps of using your menu system. If I have further questions(which I’m sure I will) I’ll ask. Somewhat of a beginner with this tuff but have quit a bit of programming in VB 6 used in SCADA Systems of which never really gets down to this level of the hardware. So I’m sure I’ll be asking more questions.
        Thanks again for the quick reply.
        Oh and don’t worry none of this is being used to control any machinery. I’m retired and love dabbling around this stuff. Just wish I would have got into it more in depth while I was still working. More like a hobby to occupy my time when I can’t be on the golf course.

        Jake

        Reply
  8. FrankO

    Tks for your amazing work.
    I followed your steps to copy and create the Menu

    Error when compiling in the Arduino IDE
    Archiving built core (caching) in: C:\Users\Frank\AppData\Local\Temp\arduino_cache_352800\core\core_arduino_avr_uno_576b18f4a57fe4e153f99a344cacb86b.a
    C:\Users\Frank\AppData\Local\Temp\ccIz3ZIc.ltrans0.ltrans.o: In function `main’:

    D:\Program Files (x86)\arduino-1.8.2\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `setup’

    D:\Program Files (x86)\arduino-1.8.2\hardware\arduino\avr\cores\arduino/main.cpp:46: undefined reference to `loop’

    collect2.exe: error: ld returned 1 exit status

    Reply
    1. Kashif Baig Post author

      Hi Frank, do you get the same error when compiling the LCD timer sketch that uses menus?

      Reply
  9. Robin

    Hi Kashif, the sytem that I’m working with has three main menus and eight sub-menus each. I need to modify the code such that when a submenu is selected a HIGH needs to be written to three different LEDs indicating which main menu is seleted. I am have problems doing this and any help would be greatly appreciated.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *