In this post we will connect the LCD to GPIO (General Purpose Input Output) pins of PI to display characters on it. We will write a program in PYTHON to send the appropriate commands to the LCD through GPIO and display the needed characters on its screen. This screen will come in handy to display sensor values, interrupt status and also for displaying time. We will be using 4 pin method.
For more details on Pi GPIO pins refer my post here.
Components required
- Raspberry Pi ( any version). I have used Pi 2 B
- 16*2 LCD Module
- 1KΩ resistor ( 2p)
- 10 K Pot
- 1000 μf capacitor
- Miscellaneous ( Breadboard, connecting pins etc.)
Explanation
As shown in the Circuit Diagram, we have Interfaced Raspberry Pi with LCD display by connecting 6 GPIO pins of PI to the 16*2 LCD’s Control and Data Transfer Pins. We have used GPIO Pin 26,19,13,06,05 and 11. Pin 26 and 19 are control pins.
16×2 LCD Module has 16 pins, which can be divided into five categories, Power Pins, contrast pin, Control Pins, Data pins and Backlight pins.
|
Category |
Pin NO. |
Pin Name |
Function |
|
Power Pins |
1 |
VSS |
Ground Pin, connected to Ground |
|
|
2 |
VDD or Vcc |
Voltage Pin +5V |
|
Contrast Pin |
3 |
V0 or VEE |
Contrast Setting, connected to Vcc thorough a variable resistor. |
|
Control Pins |
4 |
RS |
Register Select Pin, RS=0 Command mode, RS=1 Data mode |
|
Control Pins |
5 |
RW |
Read/ Write pin, RW=0 Write mode, RW=1 Read mode |
|
Control Pins |
6 |
E |
Enable, a high to low pulse need to enable the LCD |
|
Data Pins |
7-14 |
D0-D7 |
Data Pins, Stores the Data to be displayed on LCD or the command instructions |
|
Backlight Pins |
15 |
LED+ or A |
To power the Backlight +5V |
|
|
16 |
LED- or K |
Backlight Ground |
Usually the LCD requires 8 data lines to provide data to Bits 0-7. However the device can be set to a “4 bit” mode which allows you to send data in two chunks (or nibbles) of 4 bits. This reduces the number of GPIO connections you require when interfacing with your Pi.
Following table will show how I have wired.
|
LCD Pin |
Function |
Pi GPIO Pin |
Pi Pin |
|
01 |
GND |
GND |
Pi -06 |
|
02 |
+5v |
+5v |
Pi-02 |
|
03 |
Contrast |
GND |
Pi -06 |
|
04 |
RS |
GPIO 26 |
Pi-37 |
|
05 |
RW |
GND |
Pi-06 |
|
06 |
E |
GPIO 19 |
Pi-35 |
|
07 |
Data 0 |
|
|
|
08 |
Data 1 |
|
|
|
09 |
Data 2 |
|
|
|
10 |
Data 3 |
|
|
|
11 |
Data 4 |
GPIO 13 |
Pi-33 |
|
12 |
Data 5 |
GPIO 06 |
Pi-31 |
|
13 |
Data 6 |
GPIO 05 |
Pi-29 |
|
14 |
Data 7 |
GPIO 11 |
Pi-23 |
|
15 |
+5v via VR 1K |
+5V |
|
|
16 |
GND |
GND |
Pi-06 |
Since RW pin allows the device to be be put into read or write mode. I wanted to send data to the device but did not want it to send data to the Pi so I tied this pin to ground. Contrast pin has been set to ground but can be connected to VCC through VR.

Once everything is connected as per the circuit diagram, we can turn ON the PI to write the program in PYHTON.
There are many different ways to do it. I will be using
We are going to import GPIO file from library, below function enables us to program GPIO pins of PI. We are also renaming “GPIO” to “IO”, so in the program whenever we want to refer to GPIO pins we will use the word ‘IO’.
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
We can refer the GPIO pins of PI, either by pin number on board or by BCM pin numbers.
GP IO.setmode (IO.BCM)
We are setting 6 GPIO pins as output pins, for Data and Control pins of LCD.
GPIO.setup(LCD_E, GPIO.OUT) # E
GPIO.setup(LCD_RS, GPIO.OUT) # RS
GPIO.setup(LCD_D4, GPIO.OUT) # DB4
GPIO.setup(LCD_D5, GPIO.OUT) # DB5
GPIO.setup(LCD_D6, GPIO.OUT) # DB6
GPIO.setup(LCD_D7, GPIO.OUT) # DB7
After writing the program and executing it, the Raspberry Pi sends characters to LCD one by one and the LCD displays the characters on the screen.
Code
#!/usr/bin/python
#--------------------------------------
#
# lcd_16x2.py
# 16x2 LCD Test
#
# Author : Pintu Shaw
#
# https://digitalab.org
#
#--------------------------------------
# The wiring for the LCD is as follows:
# 1 : GND
# 2 : 5V
# 3 : Contrast (0-5V)*
# 4 : RS (Register Select)
# 5 : R/W (Read Write) - GROUND THIS PIN
# 6 : Enable or Strobe
# 7 : Data Bit 0 - NOT USED
# 8 : Data Bit 1 - NOT USED
# 9 : Data Bit 2 - NOT USED
# 10: Data Bit 3 - NOT USED
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: LCD Backlight +5V**
# 16: LCD Backlight GND
#import
import RPi.GPIO as GPIO
import time
# Define GPIO to LCD mapping
LCD_RS = 26
LCD_E = 19
LCD_D4 = 13
LCD_D5 = 06
LCD_D6 = 05
LCD_D7 = 11
# Define some device constants
LCD_WIDTH = 16 # Maximum characters per line
LCD_CHR = True
LCD_CMD = False
LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005
def main():
# Main program block
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers
GPIO.setup(LCD_E, GPIO.OUT) # E
GPIO.setup(LCD_RS, GPIO.OUT) # RS
GPIO.setup(LCD_D4, GPIO.OUT) # DB4
GPIO.setup(LCD_D5, GPIO.OUT) # DB5
GPIO.setup(LCD_D6, GPIO.OUT) # DB6
GPIO.setup(LCD_D7, GPIO.OUT) # DB7
# Initialise display
lcd_init()
while True:
# Send some test
lcd_string("Rasbperry Pi",LCD_LINE_1)
lcd_string("16x2 LCD Test",LCD_LINE_2)
time.sleep(3) # 3 second delay
# Send some text
lcd_string("1234567890123456",LCD_LINE_1)
lcd_string("abcdefghijklmnop",LCD_LINE_2)
time.sleep(3) # 3 second delay
# Send some text
lcd_string("digitalab.org",LCD_LINE_1)
lcd_string("Projects and more...",LCD_LINE_2)
time.sleep(3)
def lcd_init():
# Initialise display
lcd_byte(0x33,LCD_CMD) # 110011 Initialise
lcd_byte(0x32,LCD_CMD) # 110010 Initialise
lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction
lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size
lcd_byte(0x01,LCD_CMD) # 000001 Clear display
time.sleep(E_DELAY)
def lcd_byte(bits, mode):
# Send byte to data pins
# bits = data
# mode = True for character
# False for command
GPIO.output(LCD_RS, mode) # RS
# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)
# Toggle 'Enable' pin
lcd_toggle_enable()
# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)
# Toggle 'Enable' pin
lcd_toggle_enable()
def lcd_toggle_enable():
# Toggle enable
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
def lcd_string(message,line):
# Send string to display
message = message.ljust(LCD_WIDTH," ")
lcd_byte(line, LCD_CMD)
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
finally:
lcd_byte(0x01, LCD_CMD)
lcd_string("Goodbye!",LCD_LINE_1)
GPIO.cleanup()
Troubleshooting and things to take care
-
Verify the wiring
-
If display is faint or very dark adjust the contrast by adding a VR of 10K
-
Verify all ground wires
-
If there is any issue in python script, make sure to run using python3.
-
Verify the indention and tab spacing in the file. You may encounter error in compiling if there issue in spacing.
Once you are successful, it can be used to display other values like temperature and other sensor data.
Happy experimenting !!!
