
ESP32-S3 board
The brain that runs your uploaded sketch.
TinySkiff ESP32-S3 Lab · Day 21 of 30
Today the shift register earns its keep. You wire its eight outputs to a 7-segment display, upload a sketch that sends one pattern byte per character, and the display counts 0 through F — a readable digit from the same three wires you ran on Day 20.
TSK-DAY21-SEVENSEG
Hand this to an agent so it can pull the lesson packet and coach you step by step.
01 First, know the pieces
Six things, and two of them are old friends from Day 20. 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.

The brain that runs your uploaded sketch.

Spreads the pins into rows you can reach and label.

Day 20's chip — takes a byte in on three wires and holds it on eight outputs.

Eight lit bars arranged as a figure — together they draw one character.

One per segment, each keeping its own current gentle.

Temporary, solder-free connections.
02 Make the physical circuit
The official Freenove diagram is your chart — schematic on top, the same circuit built on a breadboard below. Click it to enlarge. The three control wires are exactly where Day 20 left them; today's work is the eight resistor paths from the chip's outputs to the display's segments.
Mind the chip and the display's orientation. Seat the 74HC595 with its notch matching the diagram, and place the display the way the breadboard photo shows — its segments only line up with the right Q pins one way round. Unplug USB before you move any wire.
03 One action at a time
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.
Seat the ESP32-S3 on the GPIO extension board and keep USB unplugged while you wire.
Straddle the 74HC595 across the breadboard's centre gap with its notch matching the diagram — the same seat as Day 20.
Place the 7-segment display nearby the way the breadboard photo shows, and find its two common pins (3 and 8).
Run the three control wires — GPIO 12 to DS, GPIO 13 to ST_CP, GPIO 14 to SH_CP.
Wire each chip output Q0 through Q7 to its segment through its own 220 Ω resistor, following the diagram one row at a time.
Wire the display's common pins (3 and 8) to the positive rail so the shared anode has power.
Compare every wire to the chart before you plug in USB.
Open Sketch_15.1_1_Digit_7-Segment_Display.ino in Arduino IDE and upload it.
Watch the display count 0 through F, one character per second.
04 Read just enough code
The sketch keeps Day 20's writeData() helper word for word. The new piece is a table of sixteen bytes — one ready-made segment pattern per character — and a loop that sends them one per second. Switch to MicroPython if you'd rather see the same idea in Python — the wiring never changes.
int dataPin = 12; // Pin connected to DS of 74HC595(Pin14)
int latchPin = 13; // Pin connected to ST_CP of 74HC595(Pin12)
int clockPin = 14; // Pin connected to SH_CP of 74HC595(Pin11)
// Define the encoding of characters 0-F for the common-anode 7-Segment Display
byte num[] = {
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e
};
void setup() {
// set pins to output
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// display 0-F on digital tube
for (int i = 0; i < 16; i++) {
writeData(num[i]);// Send data to 74HC595
delay(1000); // delay 1 second
writeData(0xff); // Clear the display content
}
}
void writeData(int value) {
// Make latchPin output low level
digitalWrite(latchPin, LOW);
// Send serial data to 74HC595
shiftOut(dataPin, clockPin, LSBFIRST, value);
// Make latchPin output high level, then 74HC595 will update the data to parallel output
digitalWrite(latchPin, HIGH);
}
byte num[]Sixteen ready-made segment patterns — one byte per character, 0 through F. shiftOut(dataPin, clockPin, LSBFIRST, value)Clocks the byte into the chip one bit at a time — the same move as Day 20. writeData(0xff)All eight bits set to 1 means every segment off — this line blanks the display.delay(1000)Holds each character on the display for one full second. Optional side path · same circuit
from my74HC595 import Chip74HC595
lists =[0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e]
chip = Chip74HC595(12,13,14)
for count in range(16):
chip.shiftOut(0,lists[count])
time.sleep_ms(500)
Chip74HC595(12,13,14)A helper class wraps the chip — same three pins in the same order as the Arduino sketch.chip.shiftOut(0,lists[count])Sends one pattern byte; the 0 picks lowest-bit-first order, matching LSBFIRST in Arduino.Same chip, same table of bytes. This version paces at 500 ms per character and skips the blanking write between them, so it counts twice as fast. Run it in Thonny if MicroPython is set up; otherwise skip it — it should never block the Arduino-first path.
05 Understand, don't memorise
The display is eight little lights arranged as a figure. Feed them the right on-off pattern and your eye reads a character — the code table is just sixteen of those patterns, stored and ready.
Segments A through G plus the decimal point line up with the eight bits of one byte.
All segments share the positive rail so a 0 bit pulls its segment low and lights it.
The table stores one ready-made pattern per character from 0 to F.
The 74HC595 from Day 20 carries the byte in on three wires and holds it on eight outputs.
character → one byte → eight segments → a shape you can read
From the top bit down the order is DP G F E D C B A. So 0xc0 is 1100 0000 — DP and G stay dark while the other six light up and draw a 0.
This display is common anode — every segment's positive side is tied to the rail, so an output has to sit LOW to let current flow and light its segment. 0xff is all HIGH, which is a blank display.
06 Know it worked
Nothing prints to the screen today — the proof is the count running on the display in front of you.
Lowercase b and d are deliberate — with all seven segments a capital B would read as 8 and a capital D as 0.
07 Make the idea yours
Same working circuit, three small moves — pick a digit, change the pace, and invent one character the table never had. It fits inside today's 30 minutes.
Add a writeData(num[7]) call at the end of setup() and empty out loop() — your favourite digit (swap the 7) now holds steady from the moment power arrives.
Change delay(1000) to 2000 and upload — each character now holds for two seconds. Find a pace you could actually read across the room.
Segments F E G B C make an H, and in bit order DP G F E D C B A that pattern is the byte 0x89. Call writeData(0x89) and check the shape that appears.
Logbook
08 Learn it with a hand on the tiller
Every lesson ships with a code and a machine-readable packet, so an agent can guide you with full context.
TSK-DAY21-SEVENSEG
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.