HD44780 Character LCD Wiring Guide: I2C Backpacks, Direct Parallel, and Custom Characters
Before touchscreens and OLEDs took over maker projects, the HD44780 character LCD was the default way to show status text on a homebrew device, and it's still the right choice for a huge range of projects today: it's cheap, legible in direct sunlight, needs no framebuffer or graphics library, and survives being driven by almost anything with a few spare GPIO pins. This guide covers wiring it the easy way — over I2C with a backpack module — and the direct 6-wire parallel way, plus the custom character tricks that make a 16x2 display genuinely useful for status output.
What HD44780 Actually Means
HD44780 isn't a specific display — it's a controller chip (originally by Hitachi) that became a de facto standard. Any display advertised as "16x2," "20x4," or similar with that controller (or a pin-compatible clone like the ST7066U or KS0066) uses the same command set. That's why a library written in 2005 still works with a board you buy today.
I2C Backpack: The Easy Way
Most HD44780 modules sold now come with, or can be paired with, a small I2C backpack board built around a PCF8574 I/O expander. This collapses what would be 6+ direct GPIO connections down to 4 wires: VCC, GND, SDA, and SCL. This is almost always the right choice unless you're out of I2C bus space or specifically learning parallel interfacing.
Backpack PinConnect To (ESP32 example)Connect To (Arduino Uno example) VCC5V (most LCD panels are 5V logic)5V GNDGNDGND SDAGPIO 21 (default)A4 SCLGPIO 22 (default)A5A note on voltage: many HD44780 panels are 5V-logic parts. Wiring the SDA/SCL lines directly to a 3.3V-only microcontroller like an ESP32 works in practice on most PCF8574 backpacks because the expander's I2C pins are open-drain and pulled up separately, but check your backpack's datasheet — some assume 5V pull-ups that can exceed the 3.6V absolute maximum on ESP32 GPIO. When in doubt, run the backpack from a 5V rail but confirm the SDA/SCL pull-up resistors are pulling to a voltage your microcontroller tolerates, or use a level shifter.
Finding the I2C Address
PCF8574-based backpacks typically ship at address 0x27 or 0x3F. Rather than guess, run an I2C scanner sketch first — a short loop that pings every address from 0x03 to 0x77 and reports which one ACKs. This saves the classic "blank screen, is it wiring or is it the address" debugging loop.
Library and Basic Use (Arduino/ESP32)
The LiquidCrystal_I2C library (search Library Manager for it, or the actively maintained fork by johnrickman/marcoschwartz) handles the PCF8574 command translation. A minimal sketch:
- LiquidCrystal_I2C lcd(0x27, 16, 2); — address, columns, rows
- lcd.init(); lcd.backlight(); in setup()
- lcd.setCursor(0, 0); lcd.print("Hello, shop!"); to write text at a specific position
On a Raspberry Pi, the RPLCD Python library talks to the same PCF8574 backpack over the Pi's hardware I2C bus (smbus2 as the backend), so the wiring and addressing steps are identical — only the software API differs.
Direct Parallel Wiring (No Backpack)
If you're not using a backpack, the HD44780 can run in 4-bit mode using just 6 digital pins (RS, EN, D4, D5, D6, D7) instead of the full 8-bit data bus. This is the classic Arduino tutorial wiring:
LCD PinFunctionNotes 1 (VSS)GND 2 (VDD)5V 3 (V0)ContrastWire through a 10kΩ potentiometer to GND — this is the #1 cause of "blank white boxes, no text" when skipped 4 (RS)Digital pinRegister select 5 (RW)GNDTie low for write-only operation 6 (EN)Digital pinEnable/clock 11-14 (D4-D7)Digital pins4-bit data bus (D0-D3 left unconnected) 15 (A), 16 (K)Backlight +/-Often through a resistor already built into the panelCustom Characters
The HD44780 supports up to 8 user-defined 5x8 pixel characters stored in CGRAM, which is what makes a plain character display genuinely useful for icons — a WiFi bar indicator, a degree symbol, a battery glyph, a spinner animation frame. Define each as an array of 8 bytes (one per row) representing the lit pixels, load it with lcd.createChar(slot, bitmap), then print it like any other character with lcd.write(slot). Several free "LCD custom character generator" web tools let you draw the glyph on a grid and copy out the byte array directly.
Troubleshooting
SymptomFix Backlight on, no text, or solid black boxesContrast pot needs adjustment — this is the single most common issue Garbled or random charactersLoose data line, wrong I2C address, or missing lcd.init() call Nothing lights up at allCheck VDD/VSS aren't reversed — this is a common pinout trap since it's opposite some other module families Works on breadboard, fails once wired permanentlyCold solder joint on data lines, or contrast pot vibrated out of adjustment — consider a fixed-resistor divider once you've found a good contrast valueFor a shop status panel, print server display, or a quick debug readout on any GPIO-based project, the HD44780 remains hard to beat for the five minutes of wiring it costs you. Pair it with a rotary encoder for a simple menu system, and you've got a complete standalone status/config interface without needing a full graphics stack.