esp32-smallhd-tally-light
esp32-smallhd-tally-light
ESP32-S3 + W5500 Tally Light Bridge for SmallHD Monitors over Ethernet
One-line summary (for the listing): A field-ready HTTP-to-GPI tally bridge that turns an ESP32-S3 + WIZnet W5500 into a reliable wired link between broadcast control software (Bitfocus Companion) and SmallHD on-camera monitors.
Overview
In live video production, a tally light tells the camera operator and on-air talent which camera is currently being broadcast. Missing or mistimed tally is a real on-air mistake, so the signal path has to be dependable.
This project, created by Kunkles / 32Thirteen Productions LLC, builds exactly that: a small bridge that receives a simple HTTP request from broadcast control software and converts it into an electrically isolated GPI (general-purpose input) contact closure that a SmallHD monitor understands.
The signal flow is straightforward:
Bitfocus Companion (Stream Deck, etc.)
└─ HTTP GET /tally/on · /tally/off
└─ ESP32-S3 (this firmware)
└─ GPIO drives an optocoupler (PC817)
└─ SmallHD monitor GPI pin → tally indicatorIt runs on the Waveshare ESP32-S3-ETH, which pairs an ESP32-S3 with a WIZnet W5500 SPI Ethernet controller, with WiFi kept only as a fallback.
Why W5500 Ethernet (and why wired comes first)
The decision to make Ethernet the primary interface is driven entirely by the operating environment:
- Reliability — Tally must never drop. A wired link removes the reconnection, roaming, and interference variables that WiFi carries.
- Deterministic latency — When several cameras switch tally at once, consistent, low-jitter response matters. Wired Ethernet via the W5500 gives that predictability.
- Hostile RF environments — Studios and live events are packed with wireless mics, IEM systems, camera links, and audience phones saturating 2.4/5 GHz. WiFi is the first link to suffer; wired survives.
- Fits existing production infrastructure — Camera control, NDI, and intercom already run over wired gigabit networks. A W5500-based bridge drops onto the same switch with managed static IPs and VLANs.
- One cable, room to grow — A wired backbone opens the door to PoE-style single-cable installs at ceiling or rig positions where mains power is awkward.
WiFi stays in the firmware purely for first-time setup convenience and as an emergency safety net if a cable is pulled.
Hardware
| Component | Detail |
|---|---|
| Board | Waveshare ESP32-S3-ETH |
| Ethernet | WIZnet W5500 (SPI) + WiFi fallback |
| Tally output | GPIO18 (GPIO15 is a confirmed substitute) |
| Isolation | NOYITO PC817 single-channel optocoupler |
| Test button | GPIO3 |
W5500 SPI pin mapping: MOSI 11 · MISO 12 · SCK 13 · CS 14 · INT 10 · RST 9.
The optocoupler galvanically isolates the ESP32 from the monitor's GPI port, which protects both sides in a real production rig.
How it works
The firmware is a single Arduino sketch built on the ESP32 Arduino core v3.x. Key design choices:
- Flash-once, configure-in-browser. All per-unit settings (hostname, IP mode, WiFi credentials, tally pin) are stored in NVS via the
Preferenceslibrary. You flash identical firmware to every unit and give each one a unique hostname through the web portal — no per-unit code edits. - Ethernet-first, WiFi fallback. Network events are handled asynchronously; the device uses whichever interface comes up, with Ethernet prioritized.
- mDNS for discovery (
tally-light.local), with the practical advice to use static IPs in production since mDNS can be unreliable on managed/VLAN networks.
HTTP API
| Endpoint | Method | Description |
|---|---|---|
/ , /config | GET / POST | Web configuration portal |
/tally/on | GET | Tally ON (GPIO HIGH) |
/tally/off | GET | Tally OFF (GPIO LOW) |
/tally/test | GET | One-second test pulse |
/status | GET | Firmware version, IP, interface, mode, tally state |
/reset | POST | Factory reset and reboot |
A built-in dark-themed web portal polls /status every few seconds to show a live tally indicator, making bench testing and field setup easy.
Field notes worth knowing
The write-up captures hard-won deployment details, for example on the SmallHD OLED 22:
- Use GPI Pin 7, not Pin 1.
- Polarity is Active High; behavior is open-circuit = ON, contact closure = OFF (verified on PageOS 6.3.1).
- Other SmallHD models can differ — bench test each model before deployment.
