A gifted ESP32 “IPS nixie” tube clock with broken stock firmware, reverse-engineered and rebuilt: custom firmware that drives the displays + an HTTP REST API, a local WYSIWYG web console for pushing arbitrary content and animations, and full standalone button control. Documented end-to-end for a Quarto write-up (diligentservices.io).
populated_mask 0x3E). Display index i and glow-LED index i are the same glass.1 — The web console (rich): open tools/helper.html in a browser on
the same WiFi (type the clock’s IP, hit Connect). Per-tube widgets — Text · Colour · Picture ·
Weather · Clock (time, Date / mini-calendar, or single value; plain or Nixie glow) ·
Ticker (crypto / stocks / weather / JSON) · Custom — a spanning canvas (all tubes as one
wide display), an animation studio (marquee, big clock/countdown, month calendar, progress,
sparkline, ticker, news, LED waves, matrix, starfield, plasma, slot-roll, alerts), a scene
manager with save / load / edit + cycling, and JSON backup/restore. The UI is
glyph-labelled throughout (kid- and non-English-friendly). All client-side over REST — no flashing.
2 — The physical buttons (standalone):
Modes clock · rainbow · breathe · comet · off · manual; NTP positional clock; per-tube
text, image (/raw565, memory-safe), and WS2812 glow; persisted brightness/tz/layout;
/status reports each tube’s live content + LED; ArduinoOTA + POST /ota (WiFi updates, so USB is
rarely needed). REST reference and the full API are in docs/GUIDE.md and
docs/UI-SPEC.md.
| Path | What |
|---|---|
firmware/custom-fw/ |
firmware source (PlatformIO; builds to local disk, not iCloud) |
tools/ |
helper.html (web console), esptube (REST CLI), flash.sh, monitor.sh |
hardware/pinmap.md |
the confirmed SI HAI pin map |
docs/ |
GUIDE · UI-SPEC · LEARNINGS · the identification/connection/spec journey |
samples/ |
demo images |
images/ |
photos + manifest.md for the blog |
blog/ |
Quarto post (to write) |
Rebuild/flash: tools/flash.sh (USB) or OTA. Watch serial: tools/monitor.sh. Drive from a shell:
tools/esptube status (see docs/GUIDE.md).
This is an EleksTube-IPS-family clock (the SI HAI variant), so parts from the wider EleksTube IPS ecosystem fit. There are three levels of replacement — cheapest/easiest first:
| Part | What it is | What to buy | Rough cost |
|---|---|---|---|
| Glass tube (cosmetic dome) | The clear cover that slips over a screen. This is the cracked one on pos-4. No electronics. | “EleksTube IPS glass tube(s)” — usually sold in 3-packs | ~$10–15 / 3-pack |
| Display module (“the screen”) | A 1.14″ IPS LCD, ST7789 driver, 135×240, on a small carrier board with an FPC ribbon into a ZIF socket (see the teardown photos in images/). This is the dead panel on pos-5. |
“1.14 inch IPS LCD screen display module replacement — EleksTube / NovelLife tube clock” | ~$15–20 each |
| Whole clock / assembly | A complete replacement unit. | Easiest drop-in: another SI HAI IPS clock (same 74HC595 wiring, so this firmware + the web flasher just work). Other IPS clones (original EleksTube, NovelLife) also work but may need a different pin profile — see note below. | ~$40–90 |
Where to buy
Swapping a screen (no soldering): power off → open the top cap → release the FPC from the ZIF
socket (flip the little latch) → seat the new module’s ribbon → close. Then open
tools/helper.html → 🔦 Working tubes, tick the slot, and 💾 Save layout.
The firmware degrades gracefully — missing or dead tubes simply stay dark, so the clock keeps
working while you wait for parts. Buying one extra screen also fills the empty slot 0 for a full 6.
Compatibility note: this firmware is wired for the SI HAI board (74HC595 shift-register chip-select — see
hardware/pinmap.md). A same-model SI HAI replacement is plug-and-play. A different IPS clone may use other pins/CS — flash EleksTubeHAX with its matching hardware profile, or adjust the pins infirmware/custom-fw/src/config.h.
manual occasionally instead of clock — press MODE, or hit Clock in the helper
(one-line firmware fix, deferred to avoid a flash)./image can OOM on full frames — the helper uses /raw565 instead (memory-safe).Backed up in iCloud + git (git log in this folder).