Utility To Control 1602 LCD On Raspberry Pi Via A PCF8574 I2C Backpack Module
Described here is a utility that allows a common HD44789 based LCD display to be controlled from a Raspberry Pi over the i2c bus by means of a cheap. PCF8574 backpack module
It came about as the result of the need for a 1602 LCD on my recent Raspberry Pi server project, but should also work with LCDs of different geometry such as 1602 or 2002.
1. Usage
The utility is simple to use. Typing lcdi2c
or lcdi2c -h
displays the usage information:
Usage: lcdi2c [options] "string to display"
Display string on a HD44780 LCD which is connected by the i2c bus via a PCF8574 port expander
Options:
-a address - use this i2c (hexidecimal) address (default 0x27)
-i - initialise (reset) the lcd
-r rows - set the number of rows (default 2)
-c cols - set the number of columns (default 16)
-x col - move cursor to this column (default 0)
-y row - move cursor to this row (default 0)
-b [01] - turn backlight on (1) or off (0) (default off)
-l - clear the screen
-s [012] - turn cursor off (0), on (1), or blink (2) (default off)
-h - display this help message
- The
-r
and-c
options set the number of rows and columns as used to determine where the text should wrap. These don’t need to be used on a 1602 display as this is the default, but need to be set when using 1604 or 2002 displays for example.
- The
-i
option resets the display. This generally only need to be done once, before using the LCD. This can be put in a startup script.
-b
controls the backlight. Note that the utility does not keep track of backlight state, so if you want it to be on, then include the-b 1
option in every command.
- The utility needs to be run as root: either by user
root
, or viasudo
, or by making the binary setuid 0.
1.1. Examples
lcdi2c -b 1 -l -x 2 -y 1 "Hello World"
Turns the backlight on, clears the screen, and displays the text “Hello World” on the second row, starting at the third position.
lcdi2c -l "$(printf "%-16s %-16s" $(date +"%T") $(date +"%D"))"
Clears the screen and displays the current time on the first line, and current date on the second. The printf
utility from the coreutils
package is very handly for formatting text on the command line.
2. Installing The Hardware
The i2c bus on the Pi runs at 3.3 volts and at 5 on the backpack, so using a level converter module between them is advisable. Some people have reported success using a direct connection, but do so at your own risk as it might cause damage to the Pi.
With the i2c-tools
packaged installed, the i2cdetect
utility can be used to display a table of which i2c devices are present at the various addresses:
>sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: .. .. .. .. .. .. .. .. .. .. .. .. ..
10: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
20: .. .. .. .. .. .. .. 27 .. .. .. .. .. .. .. ..
30: .. .. .. .. .. .. .. .. .. .. .. UU .. .. .. ..
40: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
50: 50 .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
60: .. .. .. .. .. .. .. .. UU .. .. .. .. .. .. ..
70: .. .. .. .. .. .. .. ..
Shows the device present as expected, at its default address of 0×27. (The UU indicated devices for which a kernel driver is installed. The device at 0×50 is an unused i2c eeprom).
3. Download and Compiling
The i2c communication from the Pi is done with the use of Gordon’s excellent WiringPi libary, and so this needs to be installed prior to compiling and/or running the utility. Installation instruction are here.
The lcdi2c
binary, compiled on Raspbian, is available here and should run on most machines.
The lcdi2c
source code is available here on github and can be compiled by simply issuing the make
command.
3.1. Using Modules With Different Pinouts
If you are using a module that has wiring between the LCD and the backpack module different to the one shown here, then you’ll need to change the following lines in lcd_i2c.c
as follows:
// pcf8574 bit positions of the lcd control pins
// bits 4 to 7 are the data bits
#define LCD_I2C_RS 0
#define LCD_I2C_RW 1
#define LCD_I2C_E 2
#define LCD_I2C_BACKLIGHT 3
...
// set the data nibble -
// note: will need to change this for devices with different wiring.
#define LCD_I2C_DATA_NIBBLE(lcd_p, x) lcd_p->output= (x<<4 | (lcd_p->output & 0x0f))
4. Links and Resources
- lcdi2c binary for Raspbian
- lcdi2c source code on GitHub.
5. Conclusion
In practice, I call the utility from a Perl script which maintains the state of the backlight, and allows the display of several pages of text which are contained in files. Other scripts keep the files up to date. The user can cycle through them by means of a push button mounted beneath the LCD.
I hope people find this useful; please let me know if you do.