Connecting the Raspberry PI to a LCD display can be a tricky. Here is how to get a 2 line LCD display connected. Most LCD displays use the same pins and protocol but it uses a minimum of 6 GPIO pins.
Wiring the LCD
The display I am using is the POWERTIP PC1602LRS-FWA-B-Q this is a two line display with back-light it required a 5 volt power supply but the data can be 3.3 volts. I bought this from Element 14The LCD display connections are as below this is the same for most displays of this type.
Pin
|
Signal
|
Description
|
1
|
Vss
|
Power
Supply - (Ground)
|
2
|
Vdd
|
Power
Supply + (5 volts)
|
3
|
Vo
|
LCD
Contrast - (Via resistor)
|
4
|
RS
|
Register
Selection High or Low
|
5
|
R/W
|
Read/Write
mode 1=Write 0=Read
|
6
|
E
|
Enable
signal to read or write data
|
7
|
DB0
|
Data
Bit 0 Not used in 4 bit mode
|
8
|
DB1
|
Data
Bit 1 Not used in 4 bit mode
|
9
|
DB2
|
Data
Bit 2 Not used in 4 bit mode
|
10
|
DB3
|
Data
Bit 3 Not used in 4 bit mode
|
11
|
DB4
|
Data
Bit 4
|
12
|
DB5
|
Data
Bit 5
|
13
|
DB6
|
Data
Bit 6
|
14
|
DB7
|
Data
Bit 7
|
15
|
A
|
LED
backlight power supply +
|
16
|
K
|
LED
backlight power supply -
|
The strange thing about this particular display is that the pins are in a strange order on the actual board. The actual pin order is 14 down to 1,16,15 it is indicated on the specification sheet and the back of the PCB but not very well as you can see below (I marked the pin numbers in red). So check the pin outs before wiring.
Signal
|
Description
|
GPIO
|
RPI
Pin
|
|
1
|
Vss
|
Power Supply - (Ground)
|
GND
|
6
|
2
|
Vdd
|
Power Supply + (5 volts)
|
5V
|
2
|
3
|
Vo
|
LCD Contrast - (Via resistor)
|
1.9K
to GND
|
6
|
4
|
RS
|
Register Selection High or Low
|
25
|
22
|
5
|
R/W
|
Read/Write mode 1=Write 0=Read
|
GND
|
6
|
6
|
E
|
Enable signal to read or write data
|
24
|
18
|
11
|
DB4
|
Data Bit 4
|
23
|
16
|
12
|
DB5
|
Data Bit 5
|
27
|
13
|
13
|
DB6
|
Data Bit 6
|
15
|
10
|
14
|
DB7
|
Data Bit 7
|
14
|
8
|
15
|
A
|
LED backlight power supply +
|
5V
|
2
|
16
|
K
|
LED backlight power supply -
|
GND
|
6
|
Here are the bread board connections
Python program explained
First import the required functions. GPIO is obvious and I will also be using the system time functions. We are using the BCM notation to indicate what pins to use. Also using variables for the GPIO pins means its easy if you want to change a pin later the same for the delays.
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
LCD_RS = 25 #LCD Reset
LCD_E = 24 #LCD Enable
LCD_D4 = 23 #LCD Bit 4
LCD_D5 = 27 #LCD Bit 5
LCD_D6 = 15 #LCD Bit 6
LCD_D7 = 14 #LCD Bit 7
LCD_WIDTH = 16 #LCD Device Width
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
import time
GPIO.setmode(GPIO.BCM)
LCD_RS = 25 #LCD Reset
LCD_E = 24 #LCD Enable
LCD_D4 = 23 #LCD Bit 4
LCD_D5 = 27 #LCD Bit 5
LCD_D6 = 15 #LCD Bit 6
LCD_D7 = 14 #LCD Bit 7
LCD_WIDTH = 16 #LCD Device Width
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
How the the LCD interface works
- Send LCD Line address to be written.
- Set the RS to Low
- Set high address in DB 4 to DB7 (Line 1 is 0xC0 so High bits 1100)
- Toggle Enable
- Set low address in DB 4 to DB7 (Line 1 is 0xC0 so Low bits 0000)
- Toggle Enable
- Send ASCII characters to be written
- Set the RS to High
- Set ASCII high bits in DB 4 to DB7 for character ("A" High bits 0100)
- Toggle Enable
- Set ASCII low bits in DB 4 to DB7 for character ("A" Low bits 0001)
- Toggle Enable
- Go to 7 and send the next ASCII character
Function to write the Bytes to the LCD using High and Low bits and toggling the enable pin.
def lcd_byte(bits, mode):
# Send byte to
data pins
# bits = data
# mode = True for character
# = False for command
GPIO.output(LCD_RS, mode)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# bits = data
# mode = True for character
# = False for command
GPIO.output(LCD_RS, mode)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
Function to send ASCII character strings to the lcd_byte function
def
lcd_string(message):
#
Send string to display
message = message.ljust(LCD_WIDTH," ")
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
A function to initialise the LCD this will be used to clear the display on start-up.
def lcd_init():
# Initialise display
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)
# Initialise display
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)
The main program block that will call these functions works a follows
- Set the GPIO pins to output mode.
- Initialise LCD
- Write a starting message
- Enter a while loop
- Wait 1 second
- Get the current date and time and store them
- Write the time to line 1 and date to line 2
- Return to loop start
- If keyboard interrupt exit loop (CTRL+C on keyboard)
- Write last message
- Clean up GPIO pins and exit.
Here is the main function code
if __name__=='__main__':
try:
# LCD GPIO Setup
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
# Initialise display
lcd_init()
LCDLine1 = "Hello World!"
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
while True:
#Wait 1 seconds
time.sleep(1)
PiTime = time.strftime("Time: %H:%M:%S", time.localtime())
PiDate = time.strftime("Date:%d %b %Y", time.localtime())
LCDLine1 = PiDate
LCDLine2 = PiTime
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(LCDLine2)
except KeyboardInterrupt:
pass
# Shutdown
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(" Goodbye :)")
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(" ")
GPIO.cleanup()
try:
# LCD GPIO Setup
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
# Initialise display
lcd_init()
LCDLine1 = "Hello World!"
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
while True:
#Wait 1 seconds
time.sleep(1)
PiTime = time.strftime("Time: %H:%M:%S", time.localtime())
PiDate = time.strftime("Date:%d %b %Y", time.localtime())
LCDLine1 = PiDate
LCDLine2 = PiTime
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(LCDLine2)
except KeyboardInterrupt:
pass
# Shutdown
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(" Goodbye :)")
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(" ")
GPIO.cleanup()
If you are using a 4 line LCD display usually 20 characters long change the following
LCD_WIDTH = 20 #LCD Device Width
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
LCD_LINE_3 = 0x94 #LCD RAM address for the 3rd Line
LCD_LINE_4 = 0xD4 #LCD RAM address for the 4th Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
LCDLine3 = ""
LCDLine4 = ""
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
LCD_LINE_3 = 0x94 #LCD RAM address for the 3rd Line
LCD_LINE_4 = 0xD4 #LCD RAM address for the 4th Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
LCDLine3 = ""
LCDLine4 = ""
Video of the display working
Here is a video of the display working
Here is the complete program in one block.
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
LCD_RS = 25 #LCD Reset
LCD_E = 24 #LCD Enable
LCD_D4 = 23 #LCD Bit 4
LCD_D5 = 27 #LCD Bit 5
LCD_D6 = 15 #LCD Bit 6
LCD_D7 = 14 #LCD Bit 7
LCD_WIDTH = 16 #LCD Device Width
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
import time
GPIO.setmode(GPIO.BCM)
LCD_RS = 25 #LCD Reset
LCD_E = 24 #LCD Enable
LCD_D4 = 23 #LCD Bit 4
LCD_D5 = 27 #LCD Bit 5
LCD_D6 = 15 #LCD Bit 6
LCD_D7 = 14 #LCD Bit 7
LCD_WIDTH = 16 #LCD Device Width
LCD_LINE_1 = 0x80 #LCD RAM address for the 1st Line
LCD_LINE_2 = 0xC0 #LCD RAM address for the 2nd Line
E_PULSE = 0.00005 #LCD Pulse Time
E_DELAY = 0.00005 #LCD Delay Time
LCD_CHR = True
LCD_CMD = False
LCDLine1 = ""
LCDLine2 = ""
def lcd_init():
# Initialise display
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)
# Initialise display
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)
def lcd_string(message):
# Send string to display
message = message.ljust(LCD_WIDTH," ")
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)
def lcd_byte(bits, mode):
# Send byte to data pins
# Send byte to data pins
# bits = data
# mode = True for character
# = False for command
GPIO.output(LCD_RS, mode)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# mode = True for character
# = False for command
GPIO.output(LCD_RS, mode)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
# 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
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
if __name__=='__main__':
try:
# LCD GPIO Setup
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
# Initialise display
lcd_init()
LCDLine1 = "Hello World!"
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
while True:
#Wait 1 seconds
time.sleep(1)
PiTime = time.strftime("Time: %H:%M:%S", time.localtime())
PiDate = time.strftime("Date:%d %b %Y", time.localtime())
LCDLine1 = PiDate
LCDLine2 = PiTime
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(LCDLine2)
except KeyboardInterrupt:
pass
# Shutdown lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(" Goodbye :)")
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(" ")
GPIO.cleanup()
try:
# LCD GPIO Setup
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
# Initialise display
lcd_init()
LCDLine1 = "Hello World!"
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
while True:
#Wait 1 seconds
time.sleep(1)
PiTime = time.strftime("Time: %H:%M:%S", time.localtime())
PiDate = time.strftime("Date:%d %b %Y", time.localtime())
LCDLine1 = PiDate
LCDLine2 = PiTime
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(LCDLine1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(LCDLine2)
except KeyboardInterrupt:
pass
# Shutdown lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(" Goodbye :)")
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(" ")
GPIO.cleanup()
how to run this particular file
ReplyDeleteA little more information would be helpful.
DeleteBut here is my best bet.
Create a file LCD.py copy the contents from one of the examples, place the file in the home folder and run program using the command line (LX Termina) "sudo python LCD.py"
For more basic information check these two posts thar show how to get a basic GPIO program running
http://robsraspberrypi.blogspot.com.au/2016/01/raspberry-pi-basics-part-2-power-on-and.html
http://robsraspberrypi.blogspot.com.au/2016/01/raspberry-pi-basics-controlling-io.html
If this does not help please give me the error and more detail
This is my 20st tutorial how to run lcd display on raspberry pi, but every time just backlight is turn on and first line is on. when run some python program it do nothing (just backlight and first line is on)
ReplyDeletesomeone have idea how to fix it??
btw. I have 1602 LCD module and raspberry pi 2 model B
I had a quick look at the 1602 display specification sheet and it seems to be the similar to the one I used but the connections are in order 1 to 16. Pin 3 is important to be connected or the display will be blank you could try connecting directly to GND without a resistor as a test (It could need a different value).
DeleteIf you are copy the code from the example you may need to re-do the tabs to the left as copy and paste tends to change tabs to spaces.
I did find that the last example had some formatting errors I have corrected that so check that it looks the same.
I would use the last complete example code as that has all that is required to make the LCD work.
If it still does not work then you may have a bad LCD.
I hope this helps!
Think you, still not working but at least I know where is problem.
DeleteThank you for making a guide for this particular application. I have a frustratingly frequent issue with missed steps in my soldering and coding that should hopefully become far less common of an occurrence after looking over your article. I am planning on designing some robot toys for my young son and this guide was just the help I needed.
ReplyDeleteBrian Hopkins @ Micro Tips USA
You are welcome :)
Deletenice post
ReplyDelete