Using I2C LCD display With Raspberry PI Pico and MicroPython


Adding a display to Raspberry PI Pico allows getting real time information from connected devices without using a computer from USB port. I2C LCD displays (with PCF8574 backpack) are one of best solution to keep wiring simple

In this tutorial I’m going to show you how to connect and use an I2C LCD display to Raspberry PI Pico.

i2c lcd display 1602

I2C LCD displays are common LCD displays, usually composed of 16 columns x 2 rows blocks, but also different configurations can be found. Differently from simple LCD displays, they include a small panel soldered in its backside, including chips able to reduce their connection wires. The I2C LCD display usually has a PCF8574 chip, which is a device able to convert I2C serial communication into parallel connections.

To connect an I2C LCD Display with your Raspberry PI Pico, you just need to wire the Vcc and GND PINs from display to VSYS and a GND PINs of RPI Pico, then SDA and SCL PINs from the I2C Display to a couple of SDA and SCL PINs from Raspberry PI Pico, belonging to the same I2C bus, as shown in the picture on the following wiring diagram chapter.

A working solution uses the dhylands-python_lcd module including a generic API to interface to LCD displays. But this class implements commands to be sent to the LCD without caring about how to send them. The reason is that there are many different backpacks and every solution can be implemented in many different ways. The ones created with a PCF8574 use I2C as communication protocol, in this case, you need a sort of driver able to send commands via I2C. This function is implemented with a second module from T-622 user, also available from T-622 GitHub page.

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all needed hardware, so that at the end you will be able to evaluate overall costs and decide if continue with the project or remove them from the shopping cart. So, hardware will be only:

Check hardware prices with following links:

Amazon raspberry pi boards box
amazon raspberry pi pico box
Amazon i2c LCD box
Amazon Breadboard box
Amazon Dupont Wiring box

Wiring Diagram

Please find in following picture my wiring diagram:

Raspberry pi pico i2c lcd wiring

Following pictures give some additional details on my cabling:

Raspberry pi pico i2c lcd details 01
Raspberry pi pico i2c lcd details 02
Raspberry pi pico i2c lcd details 03
Raspberry pi pico i2c lcd details 04

Step-by-Step Procedure

Prepare cabling according to the previous paragraph. Connect RPI Pico to Thonny (you can refer to my tutorial about First steps with Raspberry PI Pico).

Download required micropython modules:

You can also get them from my download area:

Download these files and save them in your Raspberry PI Pico root or under “lib” folder.

Before going into the usage explanation, you have to be sure that your LCD’s I2C address is correct. This is a unique address shared between I2C devices to make them able to talk on the same shared wire. This is usually a hexadecimal value and all devices connected to your RPI Pico can be scanned by copy-paste of the following code in your Thonny shell (you can copy all lines together):

import machine
i2c=machine.I2C(0,sda=sdaPIN, scl=sclPIN, freq=400000)
devices = i2c.scan()
if len(devices) == 0:
 print("No i2c device !")
 print('i2c devices found:',len(devices))
for device in devices:
 print("Hexa address: ",hex(device))

As I2C LCD with PCF8574 backpack use PCF8574 chip for I2C communication, you will probably get its default address (0x27). But if your project includes more PCF8574-based chips, then you will need to identify the LCD one between those that will be shown. In case of missing devices, please check your cabling.

Starting to use your LCD device, you can run a generic test with the T-622 test script, which I have pre-configured for 16×2 LCDs using I2C0 channel (ports GP0 and GP1 according to my wiring diagram). This modified script can be get from my download area (use the following link: i2c_lcd_test). Save this file in your Raspberry PI Pico root folder or in your computer and open it with Thonny IDE.

If your LCD display has a different I2C address, you will need to set it changing following line:

I2C_ADDR     = 0x27

If your LCD display has a different number of total columns or rows, you will need to set them changing following lines:


At this point, you are ready to test your display. From Tonny IDE run the “” file (F5) and you will start seeing some tests in a loop.

If you will see nothing, please check your cabling. Another common issue with I2C LCD display is getting a clean screen which is only powering on and off. This means that your connection is correct and everything is working, you have only to adjust your LCD contrast by rotating the screw positioned in your LCD backside, which controls a potentiometer managing contrast:

i2c lcd display contrast potentiometer

This should solve your issue.

Showing Special Characters

The LCD API used has a flexible feature allowing users to display also complex icons inside a single cell. Some special characters are already available and depend on your LCD ROM (Read Only Memory, space not visible to the user). You can use these chars with “lcd.putchar(chr())” function.

In your Thonny shell, paste following code (you can copy all lines together):

from machine import I2C
from lcd_api import LcdApi
from i2c_lcd import I2cLcd

I2C_ADDR     = 0x27

i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)

If you get a “π” char, then you have a Japanese ROM. If you get a “÷”, then you have an European ROM.

As reported from LCD API author, characters match ASCII characters in range 32-127 (0x20-0x7F) with a few exceptions:

  • 0x5C is a Yen symbol instead of backslash
  • 0x7E is a right arrow instead of tilde
  • 0x7F is a left arrow instead of delete

Only the ASCII characters are common between the two ROMs 32-125 (0x20-0x7D). You can refer to the HD44780 datasheet for the table of characters.

Custom Icons

The first 8 characters (from 0 to 7) character-generator RAM. This means that you can define and design any icon you want to display by identifying pixels to be put on/off for each char block, made of 8 rows and 5 columns of pixels. Each row A good description of how to define a generic icon is explained in

I’ve also prepared a simple MS Excel file that can help you designing your personal icon and generating related code to use in your script. You can download it from this link: bytearray code generator.

With this file, while you set to 1 or 0 (zero) the cells in the drawing zone, these cells will change color according to their value and the code will be generated. In this way, you will have an immediate preview of what you are drawing and related code to use:

bytearray code generator usage

You can use the generated code with “lcd.custom_char()” command. An example usage is built in my pico_i2c_lcd script. Download and open it in your Thonny IDE.

This scripts starts importing required modules:

import machine
from machine import I2C
from lcd_api import LcdApi
from i2c_lcd import I2cLcd

Then common variables are set (please remember to set according to your device, if different from mine one):

I2C_ADDR     = 0x27

The i2c instance is initialized and lcd object is initialized:

i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)

Following part is where the custom icon is generated, using the code coming from my generator. This icon is associated to custom char (with id value going from 0 to 7):

heart = bytearray([0x00,0x0a,0x1f,0x1f,0x0e,0x04,0x00,0x00])
lcd.custom_char(0, heart)

Final line uses a concatenation (the “+” operator concatenates strings in MicroPython) of text strings and custom char to be printed on LCD display:

lcd.putstr("Hello from\n"+chr(0)+" "+chr(0))

And following result comes from script running:

Raspberry pi pico i2c lcd test


How useful was this post?

Click on a star to rate it anonymously!

Average rating 4.6 / 5. Vote count: 19

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?