Some people requested it, so here it is…
We want to use a 4×20 caracters Arduino LCD on the Raspberry Pi.
We will use the I²C protocol and a small python class to access the display.
As you can see in this picture, the LCD display has an included I²C board.
Wiring is based on our add a RTC clock previous tutorial . The two modules (RTC and display) could be used in pair, thanks to the I²C protocol. You could even chain more I²C devices.
Be carefull with the logic levels :
Our precious Raspberry Pi works with a 3.3V logic. The display is a 5V logic device. When the Pi’s I²C internal pull-ups are ok for the RTC clock, those won’t be enough to handle the display.
So, we’ll use a small I²C logic converter. It will be very usefull for our future projects, because it allows using 3.3V and 5V devices without worrying about I²C logic levels. A ready-to-use converter costs only a few cents, so it’s a very nice component to add to the Pi.
1- What you need
Let’s start from the converter :
5V side :
AVCC -> Pi +5v
AVCC -> display +5v
AGND -> Pi GND
AGND -> display GND
ASCL -> display SCL
ASDA -> display SDA
3.3V side :
BVCC -> Pi +3.3v
BGND -> Pi GND
BSCL -> Pi SCL
BSDA -> Pi SDA
With this wiring, one could add I²C devices, without worrying about logic levels : 5V modules connect to the converter’s A side, 3.3V modules connect to the B side. Easy.
2- Enable and setup the I²C in Raspbian
We add the modules to the startup : :
sudo nano /etc/modules
Add those 2 lines:
We reboot :
we now install the required components :
sudo apt-get install python-smbus i2c-tools
We remove the I²C modules from the blacklist :
sudo nano /etc/modprobe.d/raspi-blacklist.conf
Our Raspberry should be ready to use I²C devices after a new reboot.
3- Testing the I²C
We are going to use the i2cdetect command to list every I²C devices. This command is not the same on a Rev 1 or Rev 2 Pi (I²C bus address is different), so it’s important to choose the right one :
sudo i2cdetect -y 0 (for Rev 1)
sudo i2cdetect -y 1 (for Rev 2)
On this screenshot, you can see my Pi has 3 I²C devices :
- display with address #27
- unused AT24C32 eeprom chip with address #50
- DS1307 RTC with address #68. It is noted « UU » because it’s in use.
Your display may have another address. I’ve seen #24 and #28 but it can be something else. It should be indicated in the display’s datasheet. We need this address to setup the driver a little later.
4- Python class install
To ‘talk’ with the display, we will use a small python class. So, the prefered language to use the display will also be python.
Let’s create 2 files in a subfolder of the home directory, and copy-paste the content in each one
cd mkdir display_420 sudo nano i2c_lib.py
import smbus from time import * class i2c_device: def __init__(self, addr, port=1): self.addr = addr self.bus = smbus.SMBus(port) # Write a single command def write_cmd(self, cmd): self.bus.write_byte(self.addr, cmd) sleep(0.0001) # Write a command and argument def write_cmd_arg(self, cmd, data): self.bus.write_byte_data(self.addr, cmd, data) sleep(0.0001) # Write a block of data def write_block_data(self, cmd, data): self.bus.write_block_data(self.addr, cmd, data) sleep(0.0001) # Read a single byte def read(self): return self.bus.read_byte(self.addr) # Read def read_data(self, cmd): return self.bus.read_byte_data(self.addr, cmd) # Read a block of data def read_block_data(self, cmd): return self.bus.read_block_data(self.addr, cmd)
sudo nano lcddriver.py
import i2c_lib from time import * # LCD Address ADDRESS = 0x27 # commands LCD_CLEARDISPLAY = 0x01 LCD_RETURNHOME = 0x02 LCD_ENTRYMODESET = 0x04 LCD_DISPLAYCONTROL = 0x08 LCD_CURSORSHIFT = 0x10 LCD_FUNCTIONSET = 0x20 LCD_SETCGRAMADDR = 0x40 LCD_SETDDRAMADDR = 0x80 # flags for display entry mode LCD_ENTRYRIGHT = 0x00 LCD_ENTRYLEFT = 0x02 LCD_ENTRYSHIFTINCREMENT = 0x01 LCD_ENTRYSHIFTDECREMENT = 0x00 # flags for display on/off control LCD_DISPLAYON = 0x04 LCD_DISPLAYOFF = 0x00 LCD_CURSORON = 0x02 LCD_CURSOROFF = 0x00 LCD_BLINKON = 0x01 LCD_BLINKOFF = 0x00 # flags for display/cursor shift LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 LCD_MOVERIGHT = 0x04 LCD_MOVELEFT = 0x00 # flags for function set LCD_8BITMODE = 0x10 LCD_4BITMODE = 0x00 LCD_2LINE = 0x08 LCD_1LINE = 0x00 LCD_5x10DOTS = 0x04 LCD_5x8DOTS = 0x00 # flags for backlight control LCD_BACKLIGHT = 0x08 LCD_NOBACKLIGHT = 0x00 En = 0b00000100 # Enable bit Rw = 0b00000010 # Read/Write bit Rs = 0b00000001 # Register select bit class lcd: #initializes objects and lcd def __init__(self): self.lcd_device = i2c_lib.i2c_device(ADDRESS) self.lcd_write(0x03) self.lcd_write(0x03) self.lcd_write(0x03) self.lcd_write(0x02) self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE) self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON) self.lcd_write(LCD_CLEARDISPLAY) self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT) sleep(0.2) # clocks EN to latch command def lcd_strobe(self, data): self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT) sleep(.0005) self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT)) sleep(.0001) def lcd_write_four_bits(self, data): self.lcd_device.write_cmd(data | LCD_BACKLIGHT) self.lcd_strobe(data) # write a command to lcd def lcd_write(self, cmd, mode=0): self.lcd_write_four_bits(mode | (cmd & 0xF0)) self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0)) # put string function def lcd_display_string(self, string, line): if line == 1: self.lcd_write(0x80) if line == 2: self.lcd_write(0xC0) if line == 3: self.lcd_write(0x94) if line == 4: self.lcd_write(0xD4) for char in string: self.lcd_write(ord(char), Rs) # clear lcd and set to home def lcd_clear(self): self.lcd_write(LCD_CLEARDISPLAY) self.lcd_write(LCD_RETURNHOME)
In this lcddriver.py file, you’ll have to set the I²C address. It defaults to #27 :
# LCD Address ADDRESS = 0x27
5- Using the display
It’s the fun part…
If you want to use the display in a python script, you only have to include those 2 files your script folder.
Here is what you need to use it in you script :
# loading the class import lcddriver from time import * # lcd start lcd = lcddriver.lcd() # this command clears the display (captain obvious) lcd.lcd_clear() # now we can display some characters (text, line) lcd.lcd_display_string(" Hello world !", 1) lcd.lcd_display_string(" I am", 2) lcd.lcd_display_string(" a", 3) lcd.lcd_display_string(" Raspberry Pi !", 4)
As you can see, using this display with the Pi is very easy.
You can download these scripts on github :