← SHEET 02 · ASSEMBLIES EL-011
Round-Display Desk Pet
| PART NO | EL-011 |
|---|---|
| MATL / SYSTEM | ESP32 · GC9A01 240×240 ROUND TFT |
| TOOLS | PlatformIO · Wokwi · C++ |
Working at a desk for hours on demanding projects and coursework breeds fatigue and isolation: it’s easy to lose track of time, skip water breaks, forget to stretch, and feel a creeping boredom in long solo sessions. This is the companion for that—a small animated face on an ESP32-driven round display, its blinking eyes and rotating messages (“HYDRATE”, “STRETCH!”, “YOU GOT THIS”, “NICE WORK”) offering a lightweight, friendly nudge to notice time passing and break up the monotony without another app to manage.
OVERVIEW & MOTIVATION
The goal was a single-purpose ambient companion for long work sessions: not a sensor platform or data logger, just a rotating face meant to sit quietly next to the monitor and cycle through encouraging nudges (“HYDRATE”, “STRETCH!”, “YOU GOT THIS”, “NICE WORK”) without competing for attention. That constraint keeps the firmware small and lets the round GC9A01 panel do the visual work—a circular display is filled perfectly by a circular face with no letterboxing or masked corners, which a rectangular OLED cannot do. Everything is drawn procedurally with Adafruit_GFX primitives (filled circles, lines) rather than sprite sheets or bitmap fonts, so the whole personality lives in drawBuddy() and drawEye() as plain shape math.
COMPONENTS & BOM
| REF | COMPONENT | SPEC | ROLE |
|---|---|---|---|
| U1 | ESP32 DevKit V1 | dual-core, WiFi/BT, 3.3 V logic | runs the SPI display + animation loop |
| U2 | GC9A01 round TFT module | 240×240, round, SPI, integrated backlight pin | face / message display |
| — | Backlight control | driven from a GPIO, no PWM (digitalWrite HIGH) | panel backlight enable |
| — | Wiring | SPI (SCK/MOSI) + 4 control lines (CS/DC/RST) + power | ESP32 ↔ display interconnect |
WIRING
| ESP32 PIN | NET | DISPLAY PIN |
|---|---|---|
| GPIO18 | SPI_SCK | CLK |
| GPIO23 | SPI_MOSI | DIN |
| GPIO27 | TFT_CS | CS |
| GPIO25 | TFT_DC | DC |
| GPIO26 | TFT_RST | RST |
| GPIO4 | TFT_BL | BL (backlight, driven HIGH in setup()) |
| 3V3 | 3V3 RAIL | VCC |
| GND | GND RAIL | GND |
FIRMWARE
src/main.cpp initializes SPI on explicit pins (SPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS) — no MISO, the display is write-only) and drives an
Adafruit_GC9A01A instance in setRotation(0). loop() is a single
millis()-timed scheduler with three independent intervals: eyes close for
140 ms every 2200 ms (blink), the message under the face advances every
5000 ms through a 5-entry array, and the whole face is redrawn every 40 ms
(a 25 fps frame tick) if any state changed:
if (!blinking && now - lastBlink >= 2200) {
blinking = true;
blinkStart = now;
}
if (blinking && now - blinkStart >= 140) {
blinking = false;
lastBlink = now;
}
if (now - lastMessage >= 5000) {
messageIndex = (messageIndex + 1) % MESSAGE_COUNT;
lastMessage = now;
}
if (now - lastFrame >= 40) {
lastFrame = now;
drawBuddy();
}
The face itself (drawBuddy()) is plain Adafruit_GFX shape drawing: two
concentric filled circles for the outlined head, drawEye() swapping between
a filled circle-with-highlight (open) and two short lines (closed/blinking)
per eye, two cheek circles, and a 7-segment polyline mouth. The message text
("HELLO!", "YOU GOT THIS", "STRETCH!", "HYDRATE", "NICE WORK") is
centered under the face each frame via getTextBounds().
SIMULATION
Wokwi’s stock part library has no GC9A01 part, so diagram.json pulls in the
community custom chip chip-gc9a01 (github:v0lkc/wokwi-chip-GC9A01@1.0.0)
under dependencies, wired to a wokwi-esp32-devkit-v1 on the same pins as
the table above (BL is not wired in the sim — the custom chip has no
backlight-enable pin, it renders unconditionally). wokwi.toml points the
simulator straight at the PlatformIO build output
(.pio/build/esp32dev/firmware.bin / .elf), so there’s no separate sim
build step. To run it: pio run to compile, then either open the folder in
VS Code with the Wokwi extension and press play, or drag diagram.json +
the built firmware into wokwi.com.
STATUS
Firmware is written and compiles clean against esp32dev (PlatformIO,
Arduino framework, Adafruit_GC9A01A/Adafruit_GFX/Adafruit_BusIO from
platformio.ini), and has been run and eyeballed in the Wokwi simulator —
blink timing, message rotation, and the frame tick all behave as coded.
Not done: no physical GC9A01 panel or ESP32 board has been wired up yet;
nothing here has been checked against real SPI timing, real backlight
brightness, or a real 3.3 V rail. This is a simulator-verified design, not a
bench-tested one.
USE CASES & APPLICATIONS
Small ambient desk companions and always-on character animations for study or work sessions; the same shape-based face-on-a-round-panel approach applies to round-display status widgets (clock faces, simple gauges, notification icons) on any constrained MCU where a full sprite/animation library is overkill. Related concept design: EL-001 is an earlier OLED+sensor desk-buddy exploring presence/environment sensing; EL-011 is the firmware-complete build on a round display, sensors dropped in favor of getting the panel and animation right.
FILES
sources/electronics/desk-pet/src/main.cpp— full ESP32 Arduino firmware: SPI init, blink/message/frame scheduler, procedural face drawing.sources/electronics/desk-pet/diagram.json— Wokwi wiring diagram against thechip-gc9a01custom part, pinout matches the firmware exactly.sources/electronics/desk-pet/platformio.ini— PlatformIO environment (esp32dev, Arduino framework, Adafruit GC9A01A/GFX/BusIO deps).sources/electronics/desk-pet/wokwi.toml— points the Wokwi simulator at the PlatformIO-built firmware binary/ELF.