TinySkiff ESP32-S3 Lab · Day 25 of 30

Put words
on a screen

Today the project gets a face. You wire the LCD1602's four pins to the board, add one library to the Arduino IDE, and upload a sketch that greets you on the top row while the bottom row counts the seconds — a whole screen carried over two signal wires.

About 25 minutesArduino firstMicroPython optionalFirst I2C device
Agent assist code TSK-DAY25-LCD

Hand this to an agent so it can pull the lesson packet and coach you step by step.

01 First, know the pieces

What you need

Five things, and only four wires between them. Tap Define on any part you haven't met — the answer opens as a field note you can read and dismiss without losing your place.

Official manual photo of the ESP32-S3 development board.
Manual photo

ESP32-S3 board

The brain that runs your uploaded sketch.

Official manual image of the ESP32-S3 GPIO extension board.
Manual photo

GPIO extension board

Spreads the pins into rows you can reach and label.

Official manual photo of the I2C LCD1602 module, a sixteen-by-two character display with a four-pin I2C backpack.
Manual photo

LCD1602 module

A sixteen-by-two character screen with an I2C backpack on its back.

Official manual image of a jumper wire.
Manual photo

4 × jumper wires (F/M)

Female ends slide onto the module's pins; male ends reach the board.

Official manual screenshot of the Arduino IDE interface.
Manual screenshot

Arduino IDE

Uploads the sketch to the board.

02 Make the physical circuit

Chart the circuit

The official Freenove diagram is your chart — schematic on top, the same circuit built on a breadboard below. Click it to enlarge. Four wires today, all from the little backpack board soldered to the back of the screen.

Official Freenove circuit — C Tutorial, Chapter 18 (LCD1602), page 165.
LCD GND GND Gives the module the same zero-volt reference as the board.
LCD VCC 5V The screen and its backlight run on the full five volts.
LCD SDA GPIO 14 The data wire — every character rides in on this line.
LCD SCL GPIO 13 The clock wire that keeps sender and screen in step.

Mind the 5V pin. The module's VCC wants the board's 5V pin — on 3.3V the display runs faint or dark. Unplug USB before you move any wire.

03 One action at a time

Build it

This is the main path — you can finish the day without opening a single field note. Tap each step as you go to keep your place.

0 / 8 done
  1. Seat the ESP32-S3 on the GPIO extension board and keep USB unplugged while you wire.

  2. Turn the LCD module over and find the four labelled pins on its backpack — GND, VCC, SDA, SCL.

  3. Slide female jumper ends onto GND and VCC, then land them on the board's GND and 5V pins.

  4. Wire SDA to GPIO 14 and SCL to GPIO 13.

  5. Compare every wire to the chart before you plug in USB.

  6. In Arduino IDE choose Sketch → Include Library → Add .ZIP Library… and pick LiquidCrystal_I2C-1.1.2.zip from the kit download's C/Libraries folder — you install it once and it stays.

  7. Open Sketch_18.1_Display_the_string_on_LCD1602.ino and upload it. (Wire.h, the I2C library, ships with the board package.)

  8. Watch row 0 greet you and row 1 start counting seconds.

The project has a face.

The screen is greeting you and counting on its own. Head to Test & debug to confirm both rows.

04 Read just enough code

Read the code

The sketch does its real work in setup — start the I2C bus, find the display's address, wake it, and print the greeting. The loop then rewrites row 1 once a second with the count. Switch to MicroPython if you'd rather see the same idea in Python — the wiring never changes.

Sketch_18.1_Display_the_string_on_LCD1602.ino
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

#define SDA 14                    //Define SDA pins
#define SCL 13                    //Define SCL pins

/*
 * note:If lcd1602 uses PCF8574T, IIC's address is 0x27,
 *      or lcd1602 uses PCF8574AT, IIC's address is 0x3F.
*/
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
  Wire.begin(SDA, SCL);           // attach the IIC pin
  if (!i2CAddrTest(0x27)) {
    lcd = LiquidCrystal_I2C(0x3F, 16, 2);
  }
  lcd.init();                     // LCD driver initialization
  lcd.backlight();                // Open the backlight
  lcd.setCursor(0,0);             // Move the cursor to row 0, column 0
  lcd.print("hello, world!");     // The print content is displayed on the LCD
}

void loop() {
  lcd.setCursor(0,1);             // Move the cursor to row 1, column 0
  lcd.print("Counter:");          // The count is displayed every second
  lcd.print(millis() / 1000);
  delay(1000);
}

bool i2CAddrTest(uint8_t addr) {
  Wire.beginTransmission(addr);
  if (Wire.endTransmission() == 0) {
    return true;
  }
  return false;
}
Wire.begin(SDA, SCL)Starts the I2C bus with GPIO 14 as the data line and GPIO 13 as the clock.
LiquidCrystal_I2C lcd(0x27,16,2)Names the display by its bus address — 16 columns, 2 rows. If nothing answers at 0x27, i2CAddrTest lets the sketch switch to 0x3F by itself.
lcd.setCursor(0,1)Parks the cursor at column 0 of row 1 so the next print lands on the bottom row.
lcd.print(millis() / 1000)Prints the seconds since the board booted — the running count you see tick.

05 Understand, don't memorise

Two wires carry the whole screen

A bare LCD1602 wants over a dozen wires. The backpack soldered to its back shrinks that to two signals, because I2C sends everything as addressed messages down a shared pair.

One bus

Two shared wires

SDA carries the data while SCL keeps the beat for both ends.

Address

0x27 or 0x3F

Every device on the bus has a number so the board can call this one by name.

Translate

The backpack chip

It turns bus messages into the many parallel signals the bare LCD needs.

Print

Cursor then text

The sketch parks the cursor at a row and column and writes characters there.

The model two wires → address → cursor position → characters

Another kind of serial

The bits travel single file down SDA the way they travel down USB to your Serial Monitor; SCL is the shared clock that tells both ends when each bit counts.

Two possible addresses

Backpacks built on the PCF8574T chip answer at 0x27 and PCF8574AT boards answer at 0x3F. The sketch tries 0x27 first and switches by itself when nothing replies.

06 Know it worked

Test & debug

Nothing prints to the Serial Monitor today — the proof is written on the glass in front of you.

What you should see
LCD
  • Row 0 shows "hello, world!" as soon as the sketch starts.
  • Row 1 shows "Counter:" followed by the seconds since the board booted.
  • The number ticks up once a second for as long as the board has power.

A glowing backlight with blank rows is normal at first — the contrast dial on the back of the module sets whether characters show, and it often ships turned too far.

If it doesn't
  • Backlight on but no characters? Turn the small contrast dial on the back of the module slowly until the text appears.
  • Nothing at all — no glow? Check the VCC and GND pair first, then SDA on GPIO 14 and SCL on GPIO 13.
  • Compile fails on LiquidCrystal_I2C.h? The library step was skipped — add the kit's ZIP via Sketch → Include Library → Add .ZIP Library…
  • Counter frozen? Re-upload the sketch, then press the board's reset button.

07 Make the idea yours

Try this: make the screen yours

Same working circuit, three edits to the two print lines. It fits inside today's 25 minutes.

Name the boat

Change lcd.print("hello, world!") to your boat's name and upload — row 0 is yours now.

Minutes and seconds

Make row 1 read like a clock — print millis() / 60000 for the minutes, print a colon, then print (millis() / 1000) % 60 for the seconds.

Overflow the row

Print a message longer than sixteen characters and watch where the extra letters go. Then trim the message until the whole line fits the glass again.

Logbook

08 Learn it with a hand on the tiller

Coach me through it

Every lesson ships with a code and a machine-readable packet, so an agent can guide you with full context.

Lesson code

TSK-DAY25-LCD

How the agent should behave: guide one physical connection at a time, wait for you to confirm, explain terms on request, and always check wiring, board, port, and USB before changing code.

Field note

Shortcut

Prompt copied