arduino lcd display tutorial

Arduino LCD Tutorial, Display Menu System, Scrolling Menu w/ Changeable Variables for Projects

In this Arduino LCD Tutorial we will be looking at a way to build a menu system. We will be looking at how you can incorporate a fully scrollable menu with changing variables into your projects. We will look at proper ways to design the menu system, how the button presses are handled and how the correct row is being pulled from the array.

LCD Menu Systems in the Real World

arduino lcd tutorialI’ve worked with many systems which have the 2 row x 16 column LCD screen. Most commonly, these are Variable Frequency Drives and other peripherals. Typically, they require the user (or engineer) to scroll through a list of parameters and set them to the appropriate value. Although this process may seem tedious on a small LCD screen; these devices don’t require constant configuration. In other words, the benefit of having a touch screen for a drive does not outweigh the benefit of cost savings.

Arduibo LCD Tutorial – Fundamentals

I went over the fundamentals of how to displays strings on an LCD before. If you aren’t comfortable with the pace of this particular tutorial, or are looking for something more basic, refer to the link below:
LCD Tutorial: Click Here

Hardware & Software for the Project

You are going to need a few things for the project; you can find them through the following links:

The full program we will be implementing in this project is available here: Arduino LCD Menu. The Arduino IDE used is version 1.6.9.

Arduino LCD Menu Screens Implementation

In this section, we will be going over the program which was written for this tutorial. Each section will be explained in detail. If you have any questions after you’ve gone through the tutorial, feel free to post them in the comments below.

The connections are made as follows:
arduino lcd display

LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
const int numOfInputs = 4;
const int inputPins[numOfInputs] = {8,9,10,11};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW,LOW,LOW,LOW};
bool inputFlags[numOfInputs] = {LOW,LOW,LOW,LOW};
long lastDebounceTime[numOfInputs] = {0,0,0,0};
long debounceDelay = 5;

The first task we have is to properly instantiate all of our peripherals. The above code includes the Arduino LCD Library and creates a LiquidCrystal instance. The specified pins are for the data transmission, the enable as well as the R/W pins on the LCD. If you want to learn more, please refer to the LCD Library (Click Here).

After the LCD setup, we have a section for utility functions which hold out inputs, their states as well as the debounce timers & settings. All of these were explained in the previous video I did on Advanced I/O Control (Click Here), so make sure to refer to it if anything is confusing or new to you.

const int numOfScreens = 10;
int currentScreen = 0;
String screens[numOfScreens][2] = {{"Motor Voltage","Volts"}, {"Motor Current", "Amps"},
{"Motor Rated HP","HP"},{"Overload Temp.","degC"}, {"Accel Time", "Secs"}, {"Restart Time","Mins"},
{"Analog Out. Curr.","mA"},{"Input Temp.","degC"}, {"Run Time", "Hours"}, {"Start Times","times"}};
int parameters[numOfScreens];

The above code is responsible for all of the Menu Logic. It is what makes this Arduino LCD tutorial possible & effective. We have a total of 10 different screens. Each one has a “Title” section which will appear on the first row, and a “Value” section which will appear after the variable. The said variables will be stored in the parameters array which is also initialized.

void setup() {
for(int i = 0; i < numOfInputs; i++) { pinMode(inputPins[i], INPUT); digitalWrite(inputPins[i], HIGH); // pull-up 20k } lcd.begin(16, 2); } void loop() { setInputFlags(); resolveInputFlags(); }

The setup function is nearly identical to the one I used in the last video on Input control. It initializes all of the buttons we will be using and makes sure we have a pull-up resistor enabled on each one. The lcd.begin() call makes sure that we are specifying the beginning of out "transmission" to the screen as well as the number of rows and columns of out particular device.

Last, but not least, the loop function is making a call to two distinct functions which will be explained below.

void setInputFlags() {
for(int i = 0; i < numOfInputs; i++) { int reading = digitalRead(inputPins[i]); if (reading != lastInputState[i]) { lastDebounceTime[i] = millis(); } if ((millis() - lastDebounceTime[i]) > debounceDelay) {
if (reading != inputState[i]) {
inputState[i] = reading;
if (inputState[i] == HIGH) {
inputFlags[i] = HIGH;
lastInputState[i] = reading;

The "setInputFlags()" function takes care of debouncing our inputs. This function allows us to have much better Arduino Button Control and receive reliable signals back to our board. It will keep waiting until the button state is "LOW" and wait "debouceDelay" (50ms) before taking it into account. If at that time, the input is still low, it will wait for the button to be released before registering a flag.

Using flags is crucial. You can implement such flags and only react to them when you desire. In a way, this is as close as you can get to multithreaded programming on a micro controller. In order words, because the program is not using any timers or wait instructions, you can rely on these flags to be set and resolved at a later time.

void resolveInputFlags() {
for(int i = 0; i < numOfInputs; i++) { if(inputFlags[i] == HIGH) { inputAction(i); inputFlags[i] = LOW; printScreen(); } } }

Resolving the flags we've previously created is crucial. Our goal is to store a flag bit until we are able to apply the logic and get rid of it. The above function does exactly that. This functionality is what gives our implementation such a smooth transition through the LCD Menu which we've implemented.

void inputAction(int input) {
if(input == 0) {
if (currentScreen == 0) {
currentScreen = numOfScreens-1;
}else if(input == 1) {
if (currentScreen == numOfScreens-1) {
currentScreen = 0;
}else if(input == 2) {
}else if(input == 3) {
void parameterChange(int key) {
if(key == 0) {
}else if(key == 1) {

The two functions above resolve the flags we set to "HIGH". We have 4 distinct inputs and thus we need to process each one separately. The first two buttons scroll up/down through our menu, but the challenge was in making sure that as the user goes "out of bounds", they would need to wrap around and come back to the correct screen. The seconds set of buttons is responsible to increment & decrement the parameters at each and every screen.

The parameterChange() call makes sure that we only work with the parameter at the current screen.

void printScreen() {
lcd.print(" ");

Our code only updates the screen when needed. In other words, only if an input has been detected. This minimizes the "load" on the Arduino and makes sure we don't constantly run un-important code which isn't changing. The function above will pull from the array we've initialized at the beginning and print out the message for the user.

Conclusion - Arduino LCD Menu System Implemented

At this point, you should have a fully working LCD Menu System on your screen! It has 10 screens which you can add to, and allows the user to change different parameters. Although this system is just the beginning, it can be extended much more.

Link to FULL SOFTWARE: Click Here

Thank you for reading & watching,
- EEEnthusiast

Comments 2

  1. Dear sir,
    very nice work but all commands not stored in eeprom it is only a demo of menu system so your advice is required for same sketch but with eeprom facility. Hopefully you help me.

  2. Post

    Hi Asif, very good point. I’m actually going to work on a tutorial on how to make that happen. It will most likely be live by next monday.

    – Vlad

Leave a Reply

Your email address will not be published.

CommentLuv badge