A 16×2 LCD with an I2C “backpack” needs only four wires instead of the twelve a bare LCD takes. On the Uno everything is 5 V, so the backpack wires straight to the board.
The sketch prints a title on the first line and counts uptime on the second, overwriting old digits with spaces instead of clearing the screen — that avoids flicker.
Wiring
| Arduino Uno R3 | 16×2 LCD + I2C backpack | Wire | Notes |
|---|---|---|---|
| GND | GND | black | |
| 5V | VCC | red | |
| SDA | SDA | blue | Same signal as A4 |
| SCL | SCL | yellow | Same signal as A5 |
5 V (3.3 V versions exist) part, 5 V board. Most of these LCDs need 5 V for good contrast, and the backpack pulls SDA/SCL up to its own VCC. On ESP32 or Pico, put a BSS138 level shifter between the board and the backpack instead of wiring SDA/SCL directly.
Board quirks
- The SDA/SCL pins next to AREF are the same signals as A4/A5 — use one pair, not both.
- Backlight on but a blank screen? Turn the blue contrast trimmer on the backpack until the characters appear.
- Backpacks answer at 0x27 or 0x3F. If nothing shows, run the I2C scanner and change the address in the sketch.
Code
// 16x2 LCD with a PCF8574 I2C backpack on an Arduino Uno R3.
// GND → GND, VCC → 5V, SDA → SDA (A4), SCL → SCL (A5). Address 0x27 (or 0x3F).
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(F("FlashReady"));
lcd.setCursor(0, 1);
lcd.print(F("Uptime:"));
Serial.println(F("LCD ready at 0x27"));
}
void loop() {
lcd.setCursor(8, 1);
lcd.print(millis() / 1000);
lcd.print(F("s ")); // trailing spaces clear old digits
delay(1000);
}// 16x2 LCD with a PCF8574 I2C backpack on an Arduino Uno R3.
// GND → GND, VCC → 5V, SDA → SDA (A4), SCL → SCL (A5). Address 0x27 (or 0x3F).
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(F("FlashReady"));
lcd.setCursor(0, 1);
lcd.print(F("Uptime:"));
Serial.println(F("LCD ready at 0x27"));
}
void loop() {
lcd.setCursor(8, 1);
lcd.print(millis() / 1000);
lcd.print(F("s ")); // trailing spaces clear old digits
delay(1000);
}Library: LiquidCrystal I2C (Frank de Brabander) — compiled with LiquidCrystal I2C 1.1.2.
Expected serial output
LCD ready at 0x27LCD ready at 0x27
Common errors
Backlight on, only white blocks on the top row
Contrast too high or wrong address. Turn the trimmer, then check the address with the I2C scanner.
Nothing at all, not even the backlight
Check 5V and GND, and the backlight jumper on the backpack (it must be fitted).