// the display: clock, weather, stocks, Spotify now-playing, Todoist tasks
I wanted a summer project that pushed beyond what I'd learned in embedded systems while giving me something useful for my apartment. Instead of buying a desk display, I decided to design and build one from scratch.

// the AI concept render I started from: the target I was building toward
A Wi-Fi-connected 128×32 RGB LED dashboard that displays the information I'd otherwise reach for my phone to check:
The core engineering challenge: HUB75 panels have no memory. The MCU must continuously scan pixel data to the panels, so the render loop can never be blocked by a slow network call. The design splits work across the ESP32's two cores:
Each API gets its own FreeRTOS task pinned to core 0. Shared state uses two mutexes: one for data, one for HTTP, because the TLS client can't handle concurrent requests. Rendering is dirty-region based: each zone repaints only when its data changes, minimizing SPI traffic and eliminating flicker.
A desk gadget that needs daily reboots is a failed desk gadget. To make the system resilient, I added a self-healing watchdog stack: Wi-Fi auto-reconnect, stale TLS connection reset, and a full ESP.restart() if no network call has succeeded in 15 minutes.
Wired the ESP32 to one HUB75 panel on jumpers, got the DMA driver scanning, drew the first pixels. Then chained the second panel into a single 128×32 canvas.

// first light on panel one

// the hand-wired ESP32 harness: every one of these jumpers later became a PCB trace
Network stack up, NTP clock synced, then Open-Meteo weather as the first live data on glass.
More APIs meant blocking calls stalling the render loop: restructured into one FreeRTOS task per API on core 0, mutex-guarded shared state, render loop alone on core 1.
OAuth refresh-token flow, scrolling track text, live progress bar. Built the aurora + starfield idle animation for when nothing's playing.
A desk gadget that needs reboots is a failed desk gadget: layered in Wi-Fi reconnect, stale-TLS reset, and a 15-minute dead-man restart.
Power and signal problems (below) pushed the project off jumper wires: designed the PCB in KiCad and sent it to fab.
Bright full-white frames browned out the panels, the supply couldn't hold 5V under peak current draw. Diagnosed the sag, learned to budget for worst-case (not typical) panel current, and resized the power path.
The stock barrel connector quietly cooked itself carrying sustained panel current. Lesson learned about connector current ratings; replaced with screw terminals sized for the job, a decision carried into the PCB design.
Random glitched pixels traced back to the rat's nest of jumpers carrying fast HUB75 clock and data lines. Shortening and re-routing helped; the real fix was designing a proper board.

// the prototype wiring that motivated the PCB. every embedded engineer has this photo.
Designed in KiCad and fabricated by JLCPCB, the custom PCB integrates ESP32 socket headers, a HUB75 output header, screw-terminal power input with bulk decoupling, a optional barrel-jack, and 17 labeled test points to simplify bring-up and debugging.



// layout, 3D render, and schematic. board is in transit from the fab, assembly photos coming.