How to use 16×2 LCD with Raspberry Pi using Python

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

  1. Raspberry Pi ( any version). I have used Pi 2 B
  2. 16*2 LCD Module
  3. 1KΩ resistor ( 2p)
  4. 10 K Pot
  5. 1000 μf capacitor
  6. 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.

Raspberry Pi with 16*2 LCD
Raspberry Pi with 16*2 LCD

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

  1. Verify the wiring 

  2. If display is faint or very dark adjust the contrast by adding a VR of 10K

  3. Verify all ground wires

  4. If there is any issue in python script, make sure to run using python3.

  5. 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 !!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.