Sending stuff to a display is pretty cool, as are cheap Hitachi HD44780 compatible LCD character displays that can be found on ebay. They’re pretty eeasy to work with but they do use a lot (most) of the GPIO a Raspberry Pi has to offer.
This is only really here because it exists, I guess it’s for the noobs. Adding this type of display is a kind of hello world in RPi hardware, I was a nooob when I first did this stuff on an arduino so it’s fine to have something to poke at.
I wrote this very basic python library for a simple project that needed to put two lines of text on a 16×2 screen (next time I’ll be using a display that supports I²C). It’s pretty well documented and has the pin wiring included (although you are not tied to this arrangement if you override init)
#!/usr/bin/python import RPi.GPIO as GPIO from time import sleep # BCMHD44780 - A library for interfacing RPi with Hitachi 44780 driven LCD displays # Author - Terry Hurcombe # There are some sleeps in here that you might want to remove if you drive an # oled display as these update soooo much quicker than their LCD brothers # The HD44780 is a common LCD driver, a datasheet can be found at # https://www.sparkfun.com/datasheets/LCD/HD44780.pdf # # There are oleds on the market now which claim to use a # HD44780 "compatible" controller but I wasted way too much time # on that and no success yet. It definitely needs sorting though # because the oleds are far superior. # # Here are the pinouts for the LCD although I know these # off the top of my head now # # 1 GND # 2 VCC 5v # 3 Contrast via pot or tie to ground (which is what I do, works fine) # 4 Register Select (0=command, 1=data). Tie to GPIO 25 # 5 Read/Write (LCD Operates at 5v logic), tie ths to ground for the rpi's 3.3v # 6 Enable. Tie to GPIO24 # 7-10 data pins not used in 4bit operation so do not connect # 11-14 are data pins we will use, tie to GPIO 23,17,21,22 # 15 Backlight +5v (DNC if oled) # 16 Backlight GND (DNC if oled) # Caveats # very basic and coded just for 16x2 class BCMHD44780: def __init__(self, pinRs=25, pinE=24, pinsDb=[23, 17, 27, 22]): 'Object Constructor' self.pinRs = pinRs self.pinE = pinE self.pinsDb = pinsDb # use broadcom pin numbering GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) # set lcd enable and register select # as gpio outputs GPIO.setup(self.pinE, GPIO.OUT) GPIO.setup(self.pinRs, GPIO.OUT) # also set our 4 data pins to out output for pin in self.pinsDb: GPIO.setup(pin, GPIO.OUT) self.init() def init(self): 'Initialize the display' # make this a nice slow process to give the screen plenty of time self.cmd(0x28); # set 4bit mode sleep(0.5); self.cmd(0x01) # clear DDRAM sleep(0.5); self.cmd(0x0C) # display on, cursor off sleep(0.5); self.cmd(0x80) # cursor @ 0,0 sleep(0.5); self.cmd(0x06) # entry mode def off(self): 'Turn off the display' # doe not turn off backlight self.cmd(0x00); def on(self): 'Turn on the display' self.cmd(0x0C); def cmd(self, bits, dataMode=False): 'Send command to LCD' # convert our bits to a binary string left padded to 8bits bits=bin(bits)[2:].zfill(8) GPIO.output(self.pinRs, dataMode) # set all data pins off for pin in self.pinsDb: GPIO.output(pin, False) # send the first 4 bits for i in range(4): if bits[i] == "1": GPIO.output(self.pinsDb[::-1][i], True) # pulse enable/clock GPIO.output(self.pinE, True) GPIO.output(self.pinE, False) # all data lines off for pin in self.pinsDb: GPIO.output(pin, False) # send last bits for i in range(4,8): if bits[i] == "1": GPIO.output(self.pinsDb[::-1][i-4], True) # pulse clock again GPIO.output(self.pinE, True) GPIO.output(self.pinE, False) def message(self, line1,line2): 'Send a 2 line message to the LCD' # pad out to 16 chars although this should be # made more generic in the future for different # character display widths line1 = line1.ljust(16, ' '); line2 = line2.ljust(16, ' '); # sets DDRAM pointer to line 1 self.cmd(0x80); # send hex to DDRAM for each char in out strings # to do this we send the char as its UTF-16 decimal # identifier (think HTML entity) for char in line1: self.cmd(ord(char),True) self.cmd(0xC0) # set DDRAM pointer to line 2 # rinse and repeat for char in line2: self.cmd(ord(char),True)
To use
import BCMHD44780 charLCD = new BCMHD44780() charLCD.message('Text For Line 1','Text For Line 2')