':u[l].cells[i].innerHTML='
',jQuerypix[i][l]&&(e[l]+=1<l&&(r+="0b"+decbin(e[l],5).toString(2),jQueryyl-1>l&&(r+=",
"))}y[2].cells[0].innerHTML=r}function init(){for(var r=0;jQueryyl>r;r++)for(var e=0;jQueryxl>e;e++)jQuerypix[e][r]=0}for(var jQueryxl=5,jQueryyl=8,jQuerypix=Array(jQueryxl),jQueryx=0;jQueryxl>jQueryx;jQueryx++)jQuerypix[jQueryx]=Array(jQueryyl) window.addEventListener("load",function(){init()},!1)

Interfacing 16×2 Character LCD Module with Arduino

Do you want your Arduino projects to display status messages or sensor readings? Then these LCD displays can be a perfect fit. They are extremely common and fast way to add a readable interface to your project.

This tutorial will help you get up and running with not only 16×2 Character LCD, but any Character LCD (16×4, 16×1, 20×4 etc.) that is based on Hitachi’s LCD Controller Chip – HD44780.

Because the Arduino community has already developed a library to handle HD44780 LCDs, you can interface them in no time.

Do you know?

LCD is short for Liquid Crystal Display. It is basically a display unit that uses liquid crystals to form a visual image.

When current is applied to these crystals, they become opaque, blocking the backlight that resides behind the screen. As a result that particular area will be dark compared to the others. And this is how the characters are displayed on the screen.

Hardware Overview

True to their name, these LCDs are ideal for displaying only text/characters. A 16×2 character LCD, for example, has an LED backlight and can display 32 ASCII characters in two rows of 16 characters each.

16x2 Character LCD 5x8 Pixel Matrix Grid
Each rectangle contains grid of 5×8 pixels

If you look closely you can see tiny rectangles for each character on the display and the pixels that make up a character. Each of these rectangles is a grid of 5×8 pixels.

They come in many sizes and colors: for example, 16×1, 16×4, 20×4, white text on a blue background or black text on a green and many others.

The good news is that all of these displays are ‘swappable’, which means if you build your project with one you can just unplug it and use another size/color LCD of your choice. Your code will have to change a bit but at least the wiring remains the same!

16×2 Character LCD Pinout

Before diving into the hookup and example code, let’s take a look at the pinout first.

16x2 Character LCD Display Pinout

GND is connected to the ground of the Arduino.

VCC is the power supply for the LCD which we connect to the 5V pin on the Arduino.

Vo (LCD Contrast) controls the contrast and brightness of the LCD. Using a simple voltage divider with a potentiometer, we can make fine adjustments to the contrast.

RS (Register Select) pin is set to LOW when sending commands to the LCD (such as setting the cursor to a specific location, clearing the display, etc.) and HIGH when sending data to the LCD. Basically this pin is used to separate the command from the data.

R/W (Read/Write) pin allows you to read data from the LCD or write data to the LCD. Since we are only using this LCD as an output device, we are going to set this pin LOW. This forces it into WRITE mode.

E (Enable) pin is used to enable the display. When this pin is set to LOW, the LCD does not care what is happening on the R/W, RS, and data bus lines. When this pin is set to HIGH, the LCD processes the incoming data.

D0-D7 (Data Bus) pins carry the 8 bit data we send to the display. For example, if we want to see an uppercase ‘A’ character on the display, we set these pins to 0100 0001 (as per the ASCII table).

A-K (Anode & Cathode) pins are used to control the backlight of the LCD.

Testing a Character LCD

Now we are on to the interesting stuff. Let’s test the LCD.

First, connect the 5V and GND pins from the Arduino to the breadboard power rail and plug your LCD into the breadboard.

Now we will power the LCD. The LCD has two separate power connections; One for the LCD (pin 1 and pin 2) and the other for the LCD backlight (pin 15 and pin 16). Connect pins 1 and 16 of the LCD to GND and 2 and 15 to 5V.

Most LCDs have a built-in series resistor for the LED backlight. You’ll find this near pin 15 on the back of the LCD. If your LCD does not include such a resistor or you are not sure if your LCD has one, you will need to add one between 5V and pin 15. It is safe to use a 220 ohm resistor, although a value this high may make the backlight a bit dim. For better results you can check the datasheet for maximum backlight current and select a suitable resistor value.

Next we will make the connection for pin 3 on the LCD which controls the contrast and brightness of the display. To adjust the contrast we will connect a 10K potentiometer between 5V and GND and connect the potentiometer’s center pin (wiper) to pin 3 on the LCD.

Testing 16x2 Character LCD Contrast By Turning Potentiometer
Adjusting LCD contrast by rotating potentiometer knob

That’s it. Now turn on the Arduino. You will see the backlight lit up. Now as you turn the knob on the potentiometer, you will start to see the first row of rectangles. If that happens, Congratulations! Your LCD is working fine.

Wiring a 16×2 Character LCD to an Arduino

Let’s finish connecting the LCD to the Arduino. We have already made the connections to power the LCD, now all we have to do is make the necessary connections for communication.

We know that there are 8 data pins that carry data to the display. However, HD44780 based LCDs are designed in such a way that we can communicate with the LCD using only 4 data pins (4-bit mode) instead of 8 (8-bit mode). This saves us 4 pins!

So to interface the LCD using 4-bit mode we only need to connect 6 pins: RS, EN, D7, D6, D5, and D4.

Connect the LCD’s four data pins (D4-D7) to Arduino’s digital pins #5-2, the EN pin to digital pin #11 and the RS pin to digital pin #12.

The following diagram shows you how to wire everything up.

Arduino Wiring Fritzing Connections with 16x2 Character LCD
Wiring connections of 16×2 character LCD and Arduino UNO

Difference between 4-bit and 8-bit mode

8-bit mode is much faster than 4-bit mode because it takes half the time. In 8-bit mode you write the data in one go. Whereas in 4-bit mode you have to split a byte into 2 nibbles and perform two write operations.

4-bit mode is often used to save I/O pins. However, 8-bit mode is best used when speed is required in an application and there are at least 10 I/O pins available.

Arduino Example Code

The following example sketch prints the message ‘Hello World’ on the LCD. Give the sketch a try first and then we’ll dissect it in some detail.

// include the library code:
#include <LiquidCrystal.h>

// Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() 
{
	// set up the LCD's number of columns and rows:
	lcd.begin(16, 2);

	// Clears the LCD screen
	lcd.clear();
}

void loop() 
{
	// Print a message to the LCD.
	lcd.print(" Hello world!");

	// set the cursor to column 0, line 1
	// (note: line 1 is the second row, since counting begins with 0):
	lcd.setCursor(0, 1);
	// Print a message to the LCD.
	lcd.print(" LCD Tutorial");
}

If all goes well, you should see something like this on the display.

Interfacing 16x2 character LCD with Arduino Hello world Program output

Code Explanation:

The sketch begins by including the LiquidCrystal library. The Arduino community has a library called LiquidCrystal which makes programming of LCD modules less difficult. You can find more information about the library on Arduino’s official website.

// include the library code:
#include <LiquidCrystal.h>

First we create a LiquidCrystal object. This object uses 6 parameters and specifies which Arduino pins are connected to the LCD’s RS, EN, and four data pins.

// Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

Once you have declared a LiquidCrystal object, you can access the object methods specific to the LCD.

In the ‘setup’ we call two functions. The first function is begin(). It is used to specify the dimensions (number of columns and rows) of the display. If you are using a 16×2 character LCD, pass the 16 and 2; If you’re using a 20×4 LCD, pass 20 and 4. You got the point!

The second function is clear() . This clears the LCD screen and moves the cursor to the top left corner.

lcd.begin(16, 2);
lcd.clear();

In the ‘loop’ we first print the ‘Hello World’ message on the LCD using the print() function.

// Print a message to the LCD.
lcd.print(" Hello world!");

After that we set the cursor position to the second row by calling the function setCursor(). The cursor position specifies the location where you want the new text to be displayed on the LCD. The upper left corner is assumed to be col=0, row=0.

lcd.setCursor(0, 1);
lcd.print(" LCD Tutorial");

Other useful functions in LiquidCrystal Library

There are some useful functions you can use with LiquidCrystal objects. Some of them are listed below:

  • lcd.home() function is used to position the cursor in the upper-left of the LCD without clearing the display.
  • lcd.blink() function displays a blinking block of 5×8 pixels at the position at which the next character is to be written.
  • lcd.cursor() displays an underscore (line) at the position at which the next character is to be written.
  • lcd.noBlink() function turns off the blinking LCD cursor.
  • lcd.noCursor() hides the LCD cursor.
  • lcd.scrollDisplayRight() function scrolls the contents of the display one space to the right. If you want the text to scroll continuously, you have to use this function inside a for loop.
  • lcd.scrollDisplayLeft() function scrolls the contents of the display one space to the left. Similar to above function, use this inside a for loop for continuous scrolling.

Custom Character Generation for 16×2 Character LCD

If you find the characters on the display dull and boring, you can create your own custom characters (glyphs) and symbols for your LCD. They are extremely useful when you want to display a character that is not part of the standard ASCII character set.

As discussed earlier in this tutorial a character is made up of a 5×8 pixel matrix, so you need to define your custom character within that matrix. You can use the createChar() function to define a character.

To use createChar() you first set up an array of 8 bytes. Each byte in the array represents a row of characters in a 5×8 matrix. Whereas, 0 and 1 in a byte indicate which pixel in the row should be ON and which should be OFF.

All these user defined characters are stored in the CGRAM of the LCD.

CGROM and CGRAM

All Hitachi HD44780 controller based LCDs have two types of memory – CGROM and CGRAM (Character Generator ROM and RAM).

CGROM is non-volatile memory and cannot be modified whereas CGRAM is volatile memory and can be modified at any time.

CGROM is used to store all permanent fonts that are displayed using their ASCII codes. For example, if we send 0x41 to the LCD, the letter ‘A’ will be printed on the display.

CGRAM is another memory used to store user defined characters. This RAM is limited to 64 bytes. For a 5×8 pixel based LCD, only 8 user-defined characters can be stored in CGRAM. And for 5×10 pixel based LCD only 4 user-defined characters can be stored.

Custom Character Generator

Creating custom characters has never been easier! We have created a small application called Custom Character Generator. Can you see the blue grid below? You can click on any 5×8 pixel to set/clear that particular pixel. And as you click, the code for the character is generated next to the grid. This code can be used directly in your Arduino sketch.

byte Character[8] =
{
0b00000, 0b00000, 0b01010, 0b11111, 0b11111, 0b01110, 0b00100, 0b00000
};

Your imagination is limitless. The only limitation is that the LiquidCrystal library only supports eight custom characters. But don’t be discouraged, look at the bright side, at least we have eight characters.

Arduino Example Code

The following sketch shows how to display custom characters on the LCD.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// make some custom characters:
byte Heart[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};

byte Bell[8] = {
0b00100,
0b01110,
0b01110,
0b01110,
0b11111,
0b00000,
0b00100,
0b00000
};


byte Alien[8] = {
0b11111,
0b10101,
0b11111,
0b11111,
0b01110,
0b01010,
0b11011,
0b00000
};

byte Check[8] = {
0b00000,
0b00001,
0b00011,
0b10110,
0b11100,
0b01000,
0b00000,
0b00000
};

byte Speaker[8] = {
0b00001,
0b00011,
0b01111,
0b01111,
0b01111,
0b00011,
0b00001,
0b00000
};


byte Sound[8] = {
0b00001,
0b00011,
0b00101,
0b01001,
0b01001,
0b01011,
0b11011,
0b11000
};


byte Skull[8] = {
0b00000,
0b01110,
0b10101,
0b11011,
0b01110,
0b01110,
0b00000,
0b00000
};

byte Lock[8] = {
0b01110,
0b10001,
0b10001,
0b11111,
0b11011,
0b11011,
0b11111,
0b00000
};

void setup() 
{
	// initialize LCD and set up the number of columns and rows: 
	lcd.begin(16, 2);

	// create a new character
	lcd.createChar(0, Heart);
	// create a new character
	lcd.createChar(1, Bell);
	// create a new character
	lcd.createChar(2, Alien);
	// create a new character
	lcd.createChar(3, Check);
	// create a new character
	lcd.createChar(4, Speaker);
	// create a new character
	lcd.createChar(5, Sound);
	// create a new character
	lcd.createChar(6, Skull);
	// create a new character
	lcd.createChar(7, Lock);

	// Clears the LCD screen
	lcd.clear();

	// Print a message to the lcd.
	lcd.print("Custom Character");
}

// Print All the custom characters
void loop() 
{ 
	lcd.setCursor(0, 1);
	lcd.write(byte(0));

	lcd.setCursor(2, 1);
	lcd.write(byte(1));

	lcd.setCursor(4, 1);
	lcd.write(byte(2));

	lcd.setCursor(6, 1);
	lcd.write(byte(3));

	lcd.setCursor(8, 1);
	lcd.write(byte(4));

	lcd.setCursor(10, 1);
	lcd.write(byte(5));

	lcd.setCursor(12, 1);
	lcd.write(byte(6));

	lcd.setCursor(14, 1);
	lcd.write(byte(7));
}

The output looks like this.

Interfacing 16x2 LCD with Arduino Custom Character Generation Program output

Code Explanation:

After including the library, we have to define a custom character array of eight bytes like this:

byte Heart[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};

In setup we need to create custom character using createChar() function. This function takes two parameters. The first parameter is a number between 0 and 7 to reserve one of the 8 supported custom characters. The second is the name of the array.

// create a new character
lcd.createChar(0, Heart);

Next in the loop, to display the custom character we simply use the write() function and pass it the number of the character we reserved earlier.

// byte(0) represents Heart character.
lcd.write(byte(0));