Crown Display Thing is an ESP32-C3 driven LED crown display with a built-in web UI, rotary encoder control, scoreboard mode, scrolling marquee mode, and a geared 28BYJ-48 motor output.
This repository is the current firmware source for the project. The firmware already supports:
WS2812BLED control with multiple display modes- a browser-based control panel over Wi-Fi
- AP + STA networking at the same time
- live UI updates over WebSocket
- rotary encoder control
- persistent settings in NVS
- OTA firmware updates using a
.binfile
Current firmware version: v0.3.0
Included firmware file in this repository:
- Crown_Display_Thing_v_0_3_0.bin
- SHA-256:
8120d427afe6a09cabe014b14a5fc73175a4386ebd728b4241a0536113006fed
- LED modes:
Classic RainbowWorld RainbowFull RainbowSolid ColorMarqueeScoreboard
7default display sections, each with:- adjustable start position
- single/double-row layout
- per-section hue correction
- per-section scoreboard trim
7editable solid-color presets7scoreboard players with:- custom names
- enable/disable toggle
- point tracking
- winner detection
- adjustable points-to-win
- marquee text editor with LED exclusion controls
- motor speed control with signed output RPM
- OTA update page in the web interface
The firmware is currently configured for:
- controller:
ESP32-C3 Super Mini - LEDs:
WS2812B - default LED count:
200 - rotary encoder:
KY-040style encoder with push button - motor:
28BYJ-48 - motor driver:
ULN2003 - default section count:
7
| Function | GPIO |
|---|---|
| WS2812B data | GPIO3 |
| Encoder CLK | GPIO0 |
| Encoder DT | GPIO1 |
| Encoder switch | GPIO20 |
| ULN2003 IN1 | GPIO5 |
| ULN2003 IN2 | GPIO6 |
| ULN2003 IN3 | GPIO7 |
| ULN2003 IN4 | GPIO4 |
- Connect
ESP32 GND,LED GND, andULN2003 GNDtogether. - Feed the
WS2812Bstrip from a proper5Vsupply. Do not power a full strip through the ESP32 board. - Power the
28BYJ-48motor from theULN2003board as intended, normally from5V. - The encoder uses
INPUT_PULLUP, so wire it as a normal KY-040 module with common ground. - A level shifter on the LED data line is optional but recommended for long wires or noisy power layouts.
The exact mechanical parts depend on your printed model, but the electronics BOM for the current firmware is:
| Qty | Part | Notes |
|---|---|---|
| 1 | ESP32-C3 Super Mini |
Main controller |
| 1 | WS2812B LED strip |
Default firmware assumes 200 LEDs total |
| 1 | 28BYJ-48 stepper motor |
Geared stepper used for crown motion |
| 1 | ULN2003 driver board |
Driver for the 28BYJ-48 |
| 1 | KY-040 rotary encoder module |
With push button |
| 1 | 5V power supply |
Size this for your LED count and motor load |
| 1 | Main power switch | Optional but recommended |
| 1 | USB cable for first flash | ESP32-C3 programming |
| 1 | Hookup wire set | For power and signals |
| 1 | JST, screw terminals, or similar connectors | Optional, but useful for serviceability |
| 1 | Large capacitor across LED power | Recommended for WS2812B stability |
| 1 | Series resistor on LED data line | Recommended, typically 330-470 ohm |
If you publish on Makerworld, add your printed parts, fasteners, brackets, diffusers, gears, and enclosure hardware to the Makerworld BOM beside this electronics list.
The code is currently tuned for:
- motor type:
28BYJ-48 - drive sequence:
4-state wave/full-step - motor steps per motor revolution:
2048 - external gear ratio in code:
- pinion:
15 - driven gear:
90
- pinion:
The web UI shows motor speed as output RPM after that external gear reduction.
If your printed gearing is different, update these constants in 00_Config.ino:
MOTOR_PINION_TEETHMOTOR_DRIVEN_TEETH
This firmware is meant to be calibrated to the physical build from the web UI.
Expect to set:
- the real LED count if you are not using
200LEDs - the
7section start points - which sections are single-row led's or double-row
- per-section hue offsets (optional)
- scoreboard trim values
- marquee excluded LEDs if some pixels should stay dark
Default section starts are evenly spread across the total LED count on first boot. For a finished build, you will almost certainly want to fine-tune them.
The device hosts a control page with these main areas:
LEDMotorScoreboardMarqueeAdvanced OptionsSystem Settings
The advanced panel includes:
- LED count save + reboot
- section start editing
- single/double layout toggles
- hue adjustment
- scoreboard trim adjustment
- section preview
- marquee LED exclusion tools
The system panel includes:
- Wi-Fi SSID and password
- hostname
- OTA firmware update
The encoder cycles between 4 control modes:
RainbowScoreboardMarqueeMotor Control
Current behavior:
- rotate:
- rainbow or marquee: change LED speed
- solid color mode: cycle color presets
- scoreboard: select enabled player
- motor: change motor speed
- single click:
- rainbow: cycle LED style
- scoreboard: add
1point
- double click:
- rainbow: toggle LED axis
- scoreboard: subtract
1point
- triple click:
- scoreboard: reset scores when there is a winner
- long press:
- cycle encoder target mode
The device always starts its own Wi-Fi access point:
- SSID:
Crown Display Thing - password:
thingsfromthom
If you store local Wi-Fi credentials, it also connects in AP+STA mode so both remain available.
Default hostname:
crown-display-thing
Web services:
- HTTP UI:
http://<device-ip>/ - WebSocket state sync:
ws://<device-ip>:81
You need:
Arduino IDEorarduino-cliesp32board package- libraries used by the sketch:
FastLEDWebSocketsServerfromarduinoWebSockets
Core libraries such as WiFi, WebServer, Preferences, ESPmDNS, and Update come from the ESP32 board package.
Build for:
- FQBN:
esp32:esp32:esp32c3
With arduino-cli:
arduino-cli compile --fqbn esp32:esp32:esp32c3 .
arduino-cli upload --fqbn esp32:esp32:esp32c3 --port <your-port> .If you use Arduino IDE, open Crown_Thing.ino, select the ESP32-C3 board target, then upload normally.
After flashing:
- Power the build.
- Join the
Crown Display ThingWi-Fi network. - Open
http://192.168.4.1/if your device stays in AP-only mode. - If STA credentials were already configured and it joined your local network, use the shown IP address or the hostname.
From the web UI:
- Set the correct LED count and reboot.
- Adjust the section boundaries to match the physical crown layout.
- Toggle single/double sections where needed.
- Tune hue offsets and scoreboard trim.
- Set player names, marquee text, and Wi-Fi credentials.
- Save settings.
Once the device is online, future updates can be done from the browser:
- Build a new
.bin. - Open the device web UI.
- Go to
System Settings. - Select the firmware file.
- Start
Update & Reboot.
For easy sharing, this repository already includes:
This file was freshly built from the current source in this repository for:
- board target:
esp32:esp32:esp32c3 - firmware version:
v0.3.0 - SHA-256:
8120d427afe6a09cabe014b14a5fc73175a4386ebd728b4241a0536113006fed
You can upload that file directly from the firmware update page on the device.
If you make further firmware changes, rebuild the .bin before publishing so the shared binary matches the checked-in source.
To export a binary for OTA upload:
arduino-cli compile --fqbn esp32:esp32:esp32c3 --build-path /tmp/crown_build --export-binaries .Main output:
/tmp/crown_build/Crown_Thing.ino.bin
Example versioned copy:
cp /tmp/crown_build/Crown_Thing.ino.bin ./Crown_Display_Thing_v_0_3_0.bin- 00_Config.ino: constants, pins, defaults, firmware version
- 10_State.ino: runtime state
- 20_MotorLed.ino: motor control and LED rendering
- 22_Scoreboard.ino: scoreboard helpers
- 25_Encoder.ino: rotary encoder behavior
- 30_Sections.ino: section mapping and tuning
- 35_PixelMap.ino: pixel map helpers
- 36_MarqueeExclude.ino: marquee exclusion helpers
- 40_Storage.ino: persistent settings
- 50_Web.ino: web UI, HTTP endpoints, WebSocket
- 60_Network.ino: AP, STA, and mDNS setup
- 90_Main.ino: setup and loop
- Crown_Thing.ino: includes and sketch entry anchor