In my previous post I had used an 8 bit i2c port expander to drive the 16x2 LCD. It saved precious GPIO pins but added complexity and cost. In this post I will be using the RPi.GPIO library and Python to control the LCD.The LCD used in this post is based on Hitachi HD44780 LCD controller.Although the LCD has 16 pins available for interfacing, using the 4 bit mode only 6 GPIO pins are required ( RS,E,D4,D5,D6,D7).

LCD Pin Pi Pin
01 <------> GPIO-06
02 <------> GPIO-02
03 <------> GPIO-06
04 <------> GPIO-26
05 <------> GPIO-06
06 <------> GPIO-24
07
08
09
10
11 <------> GPIO-22
12 <------> GPIO-18
13 <------> GPIO-16
14 <------> GPIO-12
15 +5V
16 <------> GPIO-06
NOTE : With the help of RW pin the device can be set to read/write mode.Setting [R/W=0] will write to the register and setting [R/W=1] will read from the register.To display data on LCD read access is not required,so the RW in connected to GND. This ensures that there is no outbound data from HD44780 as Pi cannot tolerate 5V.
You can check the pinout of Pi from here.
Code:-
HD44780 based display can be controlled using any programming environment.Here I have used Python & RPi.GPIO library to provide access to the GPIO.

LCD Pin Pi Pin
01 <------> GPIO-06
02 <------> GPIO-02
03 <------> GPIO-06
04 <------> GPIO-26
05 <------> GPIO-06
06 <------> GPIO-24
07
08
09
10
11 <------> GPIO-22
12 <------> GPIO-18
13 <------> GPIO-16
14 <------> GPIO-12
15 +5V
16 <------> GPIO-06
You can check the pinout of Pi from here.
Code:-
HD44780 based display can be controlled using any programming environment.Here I have used Python & RPi.GPIO library to provide access to the GPIO.
#!/usr/bin/python import RPi.GPIO as GPIO from time import sleep class HD44780: def __init__(self, pin_rs=7, pin_e=8, pins_db=[25, 24, 23, 18]): self.pin_rs=pin_rs self.pin_e=pin_e self.pins_db=pins_db GPIO.setmode(GPIO.BCM) GPIO.setup(self.pin_e, GPIO.OUT) GPIO.setup(self.pin_rs, GPIO.OUT) for pin in self.pins_db: GPIO.setup(pin, GPIO.OUT) self.clear() def clear(self): """ Blank / Reset LCD """ self.cmd(0x33) # $33 8-bit mode self.cmd(0x32) # $32 8-bit mode self.cmd(0x28) # $28 8-bit mode self.cmd(0x0C) # $0C 8-bit mode self.cmd(0x06) # $06 8-bit mode self.cmd(0x01) # $01 8-bit mode def cmd(self, bits, char_mode=False): """ Send command to LCD """ sleep(0.001) bits=bin(bits)[2:].zfill(8) GPIO.output(self.pin_rs, char_mode) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4): if bits[i] == "1": GPIO.output(self.pins_db[::-1][i], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False) for pin in self.pins_db: GPIO.output(pin, False) for i in range(4,8): if bits[i] == "1": GPIO.output(self.pins_db[::-1][i-4], True) GPIO.output(self.pin_e, True) GPIO.output(self.pin_e, False) def message(self, text): """ Send string to LCD. Newline wraps to second line""" for char in text: if char == '\n': self.cmd(0xC0) # next line else: self.cmd(ord(char),True) if __name__ == '__main__': lcd = HD44780() lcd.message("Raspberry Pi\n Take a byte!")
cool
ReplyDeleteNice code :)
ReplyDeleteone little improvement would be to clean up the GPIO at the end :)
if __name__ == '__main__':
lcd = HD44780()
lcd.message("Raspberry Pi\n Take a byte!")
GPIO.cleanup()
This will help prevent these warning's from being produced:
file.py:14: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(self.pin_e, GPIO.OUT)
file.py:15: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(self.pin_rs, GPIO.OUT)
file.py:17: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(pin, GPIO.OUT)
Other than that great help :)
Regards
Tim
Traceback (most recent call last):
ReplyDeleteFile "raspi.py", line 51, in
lcd = HD44780()
File "raspi.py", line 9, in __init__
GPIO.setmode(GPIO.BCM)
AttributeError: 'module' object has no attribute 'setmode'
--------------------------------------------------------------------------
Can anyone help me please? I don't know where is problem.
use sudo while executing python script
DeleteWhat i find difficult is to discover a blog that may capture me for a minute but your blog is different. Bravo.
ReplyDeleteDreambox Cccam | Dreambox Cardsharing
Thanks!
ReplyDeleteI took a one-line-16-chars display from a fax machine, and it worked like a charm.
Funny thing - it acts like a two-lines display, of 8 chars each (to show "1234567890" you need to use message("1234578\n90")).
This script worked for me, but I have 20x4 LCD and this version of script is for 16x2 LCD.. help please...
ReplyDeleteThanks ! .. worked. But if i am using 20x4 display like JHD204A.. which has same number of pins... what changes has to be done in the code...
ReplyDeleteHi, Thanks for code!
ReplyDeleteFor 4x20 display, just change message function as following:
def message(self, text):
for char in text:
if char == '\1':
self.cmd(0xC0) # next line
elif char == '\2':
self.cmd(0x94)
elif char == '\3':
self.cmd(0xD4)
else:
self.cmd(ord(char),True)
and in main while loop use:
lcd.message(" "+s[:20]+"\1"+s[20:40]+"\2"+s[40:60]+"\3"+s[60:80])
No other changes needed.
I've reproduced it on my PaspPi within 10 min, thanks a lot!
ReplyDelete