How to Connect an LCD Display to Raspberry Pi for OpenClaw Agent Output
Raspberry Pi boards support three main types of LCD display, each with different wiring, cost, and capability tradeoffs. This guide walks through I2C character LCDs, SPI TFT color screens, and the official DSI touchscreen with wiring diagrams, Python code, and practical advice for using each display as an always-on readout for sensor data, system status, or OpenClaw agent output.
Three Types of Raspberry Pi LCD, Three Different Jobs
The Raspberry Pi Foundation's official documentation covers the 7-inch DSI touchscreen, but that's only one of three display categories worth knowing. The $3 I2C character LCD and the $8 SPI TFT color screen fill different roles that the official touchscreen can't. Most tutorials pick one type and ignore the rest, which leaves you guessing whether you chose the right display for your project.
Character LCDs (the classic 16x2 or 20x4 modules built around the Hitachi HD44780 controller) are the simplest option. They display text in fixed rows and columns, draw minimal power, and cost under $5 with an I2C backpack included. They're the right choice when you need a quick readout: CPU temperature, IP address, sensor values, or status messages from an OpenClaw agent running on the Pi.
SPI TFT displays use a different protocol and support full-color graphics. Common sizes range from 1.3 inches (240x240) to 3.5 inches (480x320), with controller chips like the ST7789 or ILI9341. They're better for dashboards, charts, or any interface that goes beyond plain text. The tradeoff is more wiring, more configuration, and higher power draw.
The official Raspberry Pi Touch Display is a 7-inch, 800x480 capacitive touchscreen that connects over DSI. It supports 10-point multitouch, draws about 200mA at 5V, and works out of the box on all full-size Pi models. It's the right choice when you need an interactive GUI, but it costs around $60 and won't fit in a compact enclosure.
The decision comes down to what you're displaying. Text-only status output calls for I2C. Color graphics or small dashboards call for SPI TFT. A full GUI with touch input calls for the official display.
How to Wire and Program a 16x2 Character LCD over I2C
The I2C backpack (usually a PCF8574 chip soldered to the back of an HD44780 LCD module) converts the LCD's 16-pin parallel interface into a 2-wire I2C bus. This is the standard approach for Raspberry Pi projects because it uses only two GPIO data pins instead of six or more.
Wiring Connect four wires between the Pi's GPIO header and the LCD module:
- Pin 2 (5V) to VCC on the LCD
- Pin 6 (GND) to GND on the LCD
- Pin 3 (GPIO 2, SDA) to SDA on the LCD
- Pin 5 (GPIO 3, SCL) to SCL on the LCD
Most I2C LCD modules run on 5V for full contrast, though the I2C logic levels from the Pi's 3.3V GPIO pins work fine because the PCF8574 has wide voltage tolerance on SDA and SCL.
Enable I2C and Detect the Display Open the Raspberry Pi configuration tool and enable the I2C interface:
sudo raspi-config
Navigate to Interface Options, then I2C, and select Yes to enable it. Reboot, then install the detection tools and verify the LCD is visible on the bus:
sudo apt-get install -y i2c-tools python3-smbus
i2cdetect -y 1
You should see an address in the grid, typically 0x27 or 0x3F depending on your backpack model. If nothing shows up, double-check your wiring and make sure SDA and SCL aren't swapped.
Python Code Install the RPLCD library, which handles HD44780 character LCDs over I2C:
pip3 install RPLCD
Then write a basic script to display text:
from RPLCD.i2c import CharLCD
lcd = CharLCD(
i2c_expander="PCF8574",
address=0x27,
port=1,
cols=16,
rows=2
)
lcd.clear()
lcd.write_string("CPU: 42C")
lcd.cursor_pos = (1, 0)
lcd.write_string("Mem: 512MB free")
Change the address parameter to match whatever i2cdetect reported. For a 20x4 LCD, set cols=20 and rows=4.
Displaying Live System Data
A more practical script polls system metrics and updates the LCD every few seconds:
import subprocess
import time
from RPLCD.i2c import CharLCD
lcd = CharLCD(
i2c_expander="PCF8574",
address=0x27,
port=1,
cols=16,
rows=2
)
def get_cpu_temp():
output = subprocess.check_output(
["vcgencmd", "measure_temp"]
).decode()
return output.split("=")[1].split("'")[0]
def get_ip():
output = subprocess.check_output(
["hostname", "-I"]
).decode().strip().split()[0]
return output
while True:
lcd.clear()
lcd.write_string(f"Temp: {get_cpu_temp()}C")
lcd.cursor_pos = (1, 0)
lcd.write_string(get_ip()[:16])
time.sleep(5)
This is the most common use case for I2C LCDs on a Pi: a cheap, always-on status display that runs headless without needing SSH or a monitor.
Give your Pi agents persistent cloud storage
Upload agent output from any Raspberry Pi to a shared workspace with an MCP-ready API for reads and writes. Starts with a 14-day free trial.
Setting Up an SPI TFT Color Display
SPI TFT screens connect to the Pi's SPI bus and support full-color graphics. The two most common controller chips are the ST7789 (found on 1.3" and 2" displays) and the ILI9341 (found on 2.4" and 2.8" displays). Both support resolutions of 240x240 up to 320x480.
Wiring an ST7789 or ILI9341 Display SPI requires more wires than I2C. A typical connection uses seven pins:
- Pin 17 (3.3V) to VCC
- Pin 20 (GND) to GND
- Pin 19 (GPIO 10, MOSI) to SDA/DIN (data in)
- Pin 23 (GPIO 11, SCLK) to SCK (clock)
- Pin 24 (GPIO 8, CE0) to CS (chip select)
- Pin 22 (GPIO 25) to DC (data/command)
- Pin 18 (GPIO 24) to RST (reset)
The DC pin is critical. SPI sends raw bytes, and the display controller uses DC to tell whether incoming data represents pixel colors or system commands. Without it, the display can't distinguish between drawing instructions and actual image data.
Some modules also have a BL (backlight) pin. Connect it to 3.3V for always-on, or to a GPIO pin if you want software-controlled brightness.
Enable SPI
Enable SPI through raspi-config the same way you enabled I2C:
sudo raspi-config
Navigate to Interface Options, then SPI, and enable it. Reboot.
Using Python with Adafruit Libraries Adafruit maintains well-tested Python libraries for both ST7789 and ILI9341 displays:
pip3 install adafruit-circuitpython-rgb-display Pillow
Here's a basic example that draws text and a colored background on an ST7789 display:
import board
import digitalio
import adafruit_st7789
from PIL import Image, ImageDraw, ImageFont
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = digitalio.DigitalInOut(board.D24)
display = adafruit_st7789.ST7789(
board.SPI(),
cs=cs_pin,
dc=dc_pin,
rst=reset_pin,
width=240,
height=240,
rotation=180
)
image = Image.new("RGB", (240, 240), color=(0, 0, 0))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20
)
draw.rectangle((0, 0, 240, 240), fill=(0, 40, 80))
draw.text((10, 10), "Agent Status:", font=font, fill=(255, 255, 255))
draw.text((10, 40), "Running", font=font, fill=(0, 255, 100))
display.image(image)
For an ILI9341 display, swap adafruit_st7789.ST7789 with adafruit_ili9341.ILI9341 and adjust the width/height to match your display (typically 320x240).
Performance Expectations SPI bus speed caps around 32MHz to 48MHz on the Pi, which translates to roughly 15-25 FPS at 320x240 resolution. That's fine for dashboards and status screens, but not suitable for video playback. For higher frame rates, the fbcp-ili9341 driver uses DMA transfers to achieve smoother rendering, though setup is more involved.
Using Device Tree Overlays
On Raspberry Pi OS Bookworm and later, you can configure SPI displays through device tree overlays in /boot/firmware/config.txt instead of writing Python:
dtparam=spi=on
dtoverlay=mipi-dbi-spi,speed=48000000
This approach mirrors the display as a Linux framebuffer, so any desktop application or terminal emulator renders on the TFT automatically.
The Official Raspberry Pi Touch Display
The official 7-inch touch display connects over the DSI (Display Serial Interface) port using a flat flexible cable. Unlike I2C and SPI displays, it works out of the box on all full-size Pi models with no driver installation.
Key specifications:
- 800x480 pixel resolution
- 10-point capacitive multitouch
- 200mA at 5V typical power draw
- 250 cd/m2 brightness, 500:1 contrast ratio
- 140-degree horizontal, 120-degree vertical viewing angles
- 20,000-hour backlight lifetime
- Operating range of -20 to +70 degrees Celsius
Physically, the display connects with two components: the DSI ribbon cable for video data and jumper wires (5V and GND) from the Pi's GPIO header for power. On Raspberry Pi 4 and earlier, the included 15-to-15 pin cable works directly. Raspberry Pi 5 requires a separate 22-to-15 pin adapter cable.
Once connected, the Pi auto-detects the display and outputs the desktop. No config.txt changes needed. On Compute Modules with a Raspberry Pi IO board, you do need to add dtoverlay=vc4-kms-dsi-7inch to /boot/firmware/config.txt for manual configuration.
The official display does not work with Pi Zero boards or the Raspberry Pi Keyboard computer because they lack DSI connectors.
For projects where you need a full desktop environment, web-based dashboards, or touch-driven interfaces, this is the straightforward choice. The tradeoff is size and price: at 193mm x 111mm and around $60, it's not a fit for compact or cost-sensitive builds.
How to Choose Between I2C, SPI, and DSI Protocols
Each protocol has clear strengths and weaknesses. Picking the wrong one means either overengineering a simple status readout or struggling to push pixels through a bus that wasn't designed for it.
I2C uses two data wires (SDA and SCL on GPIO 2 and 3). It's the simplest to wire, supports multiple devices on the same bus (each with a unique address), and works well for character LCDs where you're sending a few bytes of text. The downside is speed: the standard I2C bus on the Pi runs at 100kHz or 400kHz, which is too slow for graphics.
SPI uses four or more wires (MOSI, MISO, SCLK, and one CS per device). It's faster than I2C, running at up to 48MHz on the Pi, which makes it viable for small color displays. The cost is more GPIO pins and more complex wiring. SPI also doesn't support multi-device addressing the way I2C does: each device needs its own chip select line.
DSI is a dedicated display interface with much higher bandwidth. The official touch display uses it for 800x480 at 60 FPS, something that neither I2C nor SPI could handle. But DSI is point-to-point (one display per connector) and only works with displays specifically designed for it.
For OpenClaw and other AI agent projects running on a Pi, the I2C character LCD is often the best starting point. It takes five minutes to wire, the Python code is trivial, and it gives your agent a physical output channel that doesn't require a network connection or a separate monitor.
Displaying OpenClaw Agent Output on a Raspberry Pi LCD
A Raspberry Pi with an LCD display makes a practical output terminal for AI agents, including OpenClaw agents that run local tasks on edge hardware. The agent runs a task, writes results to a file or stdout, and a simple Python script pushes the latest output to the display. No monitor, no SSH session, no web browser needed.
Character LCD for Agent Status
For agents that produce short status messages, a 16x2 I2C LCD works well. Write the agent's current state to line 1 and the last result to line 2:
import time
from pathlib import Path
from RPLCD.i2c import CharLCD
lcd = CharLCD(
i2c_expander="PCF8574",
address=0x27,
port=1,
cols=16,
rows=2
)
status_file = Path("/tmp/agent_status.txt")
while True:
if status_file.exists():
lines = status_file.read_text().strip().split("
")
lcd.clear()
lcd.write_string(lines[0][:16])
if len(lines) > 1:
lcd.cursor_pos = (1, 0)
lcd.write_string(lines[1][:16])
time.sleep(2)
The agent writes to /tmp/agent_status.txt, and the display script reads it. This decoupled approach means the agent doesn't need to know anything about LCD hardware.
TFT Display for Richer Output
For OpenClaw agents or other AI agents that produce structured data, charts, or longer text, an SPI TFT display can show more context. You can render Pillow images with multiple lines of text, color-coded status indicators, or even small charts using matplotlib's Agg backend.
Persisting Agent Artifacts with Fast.io
When an OpenClaw agent or any agent running on a Pi produces files (logs, processed data, reports), those files are stuck on a microSD card until you retrieve them. Fast.io workspaces solve this by giving the agent a persistent cloud location to store its output. The agent writes locally, uploads to a shared workspace, and a human can review the files from any browser.
With Intelligence Mode enabled, uploaded files are automatically indexed for semantic search. You can ask questions about the agent's output without downloading anything. For teams running multiple Pi-based agents, a single Fast.io workspace becomes the central location where all agent output converges, searchable and organized.
Plans start with a 14-day free trial (Solo at $29/month, Business at $99/month), with storage, monthly credits, and workspaces scaled to each tier, enough for most Pi-based agent deployments. Files uploaded via the Fast.io API or MCP server are versioned automatically, so you have a full history of what each agent produced and when.
Alternatives like local NFS mounts or rsync scripts work for simpler setups, but they require you to manage your own infrastructure and don't include search, versioning, or access control out of the box.
Frequently Asked Questions
How do I connect an LCD display to Raspberry Pi?
The connection method depends on the display type. For a 16x2 character LCD with an I2C backpack, connect four wires (5V, GND, SDA to GPIO 2, SCL to GPIO 3), enable I2C in raspi-config, and use a Python library like RPLCD. For an SPI TFT display, connect seven wires including MOSI, SCLK, CS, DC, and RST pins, enable SPI in raspi-config, and use Adafruit's CircuitPython libraries. The official 7-inch touchscreen connects via the DSI ribbon cable and works without driver installation.
What is the difference between I2C and SPI LCD for Raspberry Pi?
I2C uses two data pins (SDA and SCL) and runs at 100-400kHz, making it ideal for text-only character LCDs. SPI uses four or more pins and runs at up to 48MHz, which provides enough bandwidth for small color TFT displays. I2C is simpler to wire and supports multiple devices on one bus. SPI is faster but requires a dedicated chip select pin for each device. Choose I2C for status readouts and SPI for graphical dashboards.
Can Raspberry Pi drive a TFT display?
Yes. The Raspberry Pi can drive SPI-based TFT displays using controller chips like the ST7789 (240x240) or ILI9341 (320x240). At SPI bus speeds of 32-48MHz, expect 15-25 FPS for a 320x240 display. Python libraries from Adafruit handle the low-level SPI communication, and the Pillow library lets you draw text, shapes, and images. For higher performance, the fbcp-ili9341 driver uses DMA transfers to improve frame rates.
Which LCD screen works best with Raspberry Pi?
It depends on the project. A $3-5 I2C 16x2 LCD is best for simple text output like temperatures, IP addresses, or agent status messages. An $8-15 SPI TFT display (ST7789 or ILI9341) is better for color graphics, small charts, or dashboards. The official $60 Raspberry Pi Touch Display is the right choice for full desktop GUIs with touch input. For headless agent projects, the I2C character LCD offers the best simplicity-to-usefulness ratio.
How do I display sensor data on a Raspberry Pi LCD?
Read the sensor value in Python (using libraries like gpiozero for temperature or adafruit-circuitpython-bme280 for environmental sensors), format it as a string, and write it to the LCD. For I2C character LCDs, use the RPLCD library's write_string method. For TFT displays, render the value onto a Pillow image and push it to the display. Wrap the whole thing in a loop with a sleep interval to refresh the reading.
Can I use multiple displays on one Raspberry Pi?
Yes. I2C supports multiple devices on the same bus as long as each has a unique address, so you can connect two I2C LCDs if they have different addresses (0x27 and 0x3F, for example). SPI supports multiple displays using separate chip select pins (CE0 and CE1 are available by default). You can also combine protocols, running an I2C character LCD alongside an SPI TFT on the same Pi.
Related Resources
Give your Pi agents persistent cloud storage
Upload agent output from any Raspberry Pi to a shared workspace with an MCP-ready API for reads and writes. Starts with a 14-day free trial.