Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

16x2 I2C LCD with ESP32-C3 SuperMini — level-shifted

Run a 5 V 16x2 I2C LCD from an ESP32-C3 SuperMini: 5V supply, SDA/SCL on GPIO5/6 through a level shifter, and the Wire.begin order that keeps those pins.

Arduino C++Verified — core esp32 3.3.12, LiquidCrystal I2C 1.1.2, 3 Nov 2026Compile-only

Community draft — report a mistake

The blue 16x2 I2C LCD is a 5 V part; the SuperMini is a 3.3 V board. Powering the LCD from 3V3 gives a dim, low-contrast screen, and powering it from 5V puts 5 V on the I2C lines through the backpack’s pull-ups.

The clean fix is a cheap BSS138 level shifter between them: the LCD runs at 5 V, the C3 sees 3.3 V on GPIO5 (SDA) and GPIO6 (SCL). The sketch also shows the one software trap on this board — calling Wire.begin(5, 6) before lcd.init().

Wiring

ESP32-C3 SuperMiniOnly the pins used are shown · 3.3 V logic16×2 LCD + I2C backpackLV⇄HVLV⇄HV5VGND5 · 56 · 6GNDVCCSDASCL
Also needed: 2-channel (or 4-channel) BSS138 I2C level shifter.
Every connection
ESP32-C3 SuperMini16×2 LCD + I2C backpackWireNotes
5VVCCredThe LCD and backlight need 5 V for good contrast.
GNDGNDblack
5SDAblueVia level shifter — BSS138 module: LV → 3V3, HV → 5V, both GNDs to GND.
6SCLyellowVia level shifter — Second channel of the same shifter.

5 V (3.3 V versions exist) part, 3.3 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 PCF8574 backpack has pull-up resistors to its own VCC. At 5 V that puts 5 V on SDA/SCL, and the C3’s pins are not 5 V tolerant — hence the level shifter.
  • lcd.init() calls Wire.begin() with no pins, which on a generic C3 means GPIO8/9 (the LED and BOOT strapping pins). Calling Wire.begin(5, 6) first keeps the bus on GPIO5/6 — the core just keeps the bus that is already running.
  • If the screen is lit but blank, turn the blue contrast pot on the backpack — at 5 V it is usually set right, at 3.3 V it rarely is.
  • The backpack address is 0x27 (PCF8574T) or 0x3F (PCF8574AT). The sketch checks 0x27 and tells you if nothing answers.

Code

lcd16x2-i2c-esp32c3.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// 16x2 I2C LCD (PCF8574 backpack) on an ESP32-C3 SuperMini.
// VCC → 5V, GND → GND, SDA → GPIO5 and SCL → GPIO6 through a BSS138 level shifter
// (LV side 3V3, HV side 5V). The backpack pulls SDA/SCL up to 5 V; the C3's pins are 3.3 V only.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

constexpr int SDA_PIN = 5;
constexpr int SCL_PIN = 6;
LiquidCrystal_I2C lcd(0x27, 16, 2);  // many backpacks are 0x3F instead

void setup() {
  Serial.begin(115200);
  delay(1500);  // let the native USB serial port enumerate
  // Start Wire on our pins FIRST. lcd.init() calls Wire.begin() again with no pins;
  // the core keeps the bus that is already running, so GPIO5/6 stay in use.
  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.beginTransmission(0x27);
  if (Wire.endTransmission() != 0) Serial.println("Nothing at 0x27 — try 0x3F in the sketch");
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("ESP32-C3 Mini");
  Serial.println("LCD ready");
}

void loop() {
  lcd.setCursor(0, 1);
  lcd.printf("Up %5lu s", millis() / 1000);
  delay(1000);
}

Library: LiquidCrystal I2C (Frank de Brabander) — compiled with LiquidCrystal I2C 1.1.2.

Expected serial output

Serial Monitor · 115200Output
LCD ready

Common errors

Backlight on, only blocks or nothing

Contrast pot or wrong address. Full fix.

Only the first character prints

Old library behaviour with write(). Full fix.

“Nothing at 0x27”

Try 0x3F, and check the shifter’s LV pin is on 3V3 and HV on 5V.

↑↓ to move · Enter to open