Raspberry Pi Pico I2C LCD: Wiring, Code and Simulator

To build this Raspberry Pi Pico I2C LCD project you need a Raspberry Pi Pico and a 16x2 LCD. machine.I2C on GP0/GP1 finds the LCD backpack at 0x27 and drives it with a 30-line driver. Make the 4 connections in the wiring table, upload the MicroPython code, and read the driver: each I2C byte sets the backpack pins, and E pulses latch each nibble.

Open this circuit in the free Raspberry Pi Pico simulator

Parts list

QtyPartWhat it does
1Raspberry Pi Picothe microcontroller board
116x2 LCDCharacter LCD (HD44780). Wiring "full": RS, E and D4–D7 to pins (LiquidCrystal). Wiring "i2c": SDA to A4, SCL to A5 (LiquidCrystal_I2C, address 0x27).

Wiring

#FromTo
1Raspberry Pi Pico GP016x2 LCD SDA
2Raspberry Pi Pico GP116x2 LCD SCL
3Raspberry Pi Pico VBUS16x2 LCD VCC
4Raspberry Pi Pico GND16x2 LCD GND

Step by step

  1. Open the simulator. Open the BitForBytes Embedded Lab in your browser and start from the Raspberry Pi Pico. No install or account is needed.
  2. Add the parts. Add a 16x2 LCD from the parts palette.
  3. Wire 1. Connect Raspberry Pi Pico GP0 to 16x2 LCD SDA.
  4. Wire 2. Connect Raspberry Pi Pico GP1 to 16x2 LCD SCL.
  5. Wire 3. Connect Raspberry Pi Pico VBUS to 16x2 LCD VCC.
  6. Wire 4. Connect Raspberry Pi Pico GND to 16x2 LCD GND.
  7. Paste the MicroPython code. Paste the MicroPython code below into the code editor.
  8. Run it. Press Run. Read the driver: each I2C byte sets the backpack pins, and E pulses latch each nibble.

MicroPython code

# I2C LCD: a 16x2 display with a PCF8574 backpack on I2C0 (SDA = GP0, SCL = GP1).
# MicroPython has no LCD library built in, so the driver is right here: every
# byte on the bus sets the backpack's 8 pins, which are wired to the LCD as
# P0 = RS, P2 = E, P3 = backlight, P4-P7 = D4-D7.
from machine import Pin, I2C
import time

i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=100000)
print("I2C devices found:", [hex(a) for a in i2c.scan()])
ADDR = 0x27
BACKLIGHT = 0x08

def nibble(value, rs):
    data = (value << 4) | BACKLIGHT | rs
    i2c.writeto(ADDR, bytes([data | 0x04, data]))  # pulse E high, then low

def send(value, rs=0):
    nibble(value >> 4, rs)
    nibble(value & 0x0F, rs)

def init():
    time.sleep_ms(50)
    for _ in range(3):
        nibble(0x03, 0)
        time.sleep_ms(5)
    nibble(0x02, 0)          # 4-bit mode
    send(0x28)               # 2 lines, 5x8 font
    send(0x0C)               # display on, cursor off
    send(0x06)               # move right after each character
    send(0x01)               # clear
    time.sleep_ms(2)

def write(text, row=0):
    send(0x80 | (0x40 * row))  # cursor to the start of the row
    for ch in text:
        send(ord(ch), 1)

init()
write("Hello from Pico")
count = 0
while True:
    write("Count: {}   ".format(count), 1)
    count += 1
    time.sleep(1)

What to try

Read the driver: each I2C byte sets the backpack pins, and E pulses latch each nibble.

Frequently asked questions

How do I wire the I2C LCD project on a Raspberry Pi Pico?

Make 4 connections: Raspberry Pi Pico GP0 to 16x2 LCD SDA; Raspberry Pi Pico GP1 to 16x2 LCD SCL; Raspberry Pi Pico VBUS to 16x2 LCD VCC; Raspberry Pi Pico GND to 16x2 LCD GND.

What parts do I need for this Raspberry Pi Pico project?

A Raspberry Pi Pico and a 16x2 LCD.

Can I simulate this Raspberry Pi Pico project online for free?

Yes. The BitForBytes Embedded Lab runs this exact circuit and MicroPython code in your browser for free, with no install and no hardware. The RP2040 is emulated and runs the official firmware.

What does the code do?

machine.I2C on GP0/GP1 finds the LCD backpack at 0x27 and drives it with a 30-line driver.

More Raspberry Pi Pico projects