Controllable LED Harness
Two custom 3D-printed harnesses for Darklands: one wrapped in RGB light rings, one with a scrolling matrix panel, both controllable from my phone and my website.
The idea
I wanted a piece of gear for Darklands that actually reacted to the night instead of just sitting there looking cool. So I designed and printed two harnesses, each with its own personality. The first is wrapped in individually addressable RGB light rings for slow color washes and reactive effects. The second carries an LED matrix panel that scrolls text and animations. And because leaving things simple is apparently not an option for me, both are controllable three ways: from the physical controllers, over Bluetooth from my phone, and remotely through my website, so a friend could change my lights from across the room (or the country).
Note: this writeup keeps growing. CAD files and a lot more build photos are on the way, and the whole control setup has its own deeper page.
Bill of materials
Step 1: Designing it in CAD
I modelled both harnesses in Fusion 360, aiming for something that reads as comfortable and futuristic rather than cosplay bulky. The key constraints were fitting the LED rings and the matrix panel cleanly into the body, keeping the whole thing light enough to wear all night, and making the electronics modular so I can pop a controller or battery out without rebuilding the piece. I went through a few rounds of test prints, tweaking strap angles and the depth of the channels that hide the wiring until it actually sat right on the shoulders.
Step 2: Printing in PETG
Everything printed in PETG, which handles body heat and flex far better than PLA and does not go soft in a warm, sweaty room. I printed the body in sections so each piece fit the plate and could be swapped if I bumped a design, then joined them with hidden fasteners. Diffuser pieces over the LEDs were printed thin and in white so the light spreads into a soft glow instead of a row of hard dots.
Step 3: The RGB light rings
The first harness runs WS2812B rings. Every LED is individually addressable, so I get full control over brightness, color, and animated effects instead of one flat color. They are wired to an SP801E controller, which pairs over Bluetooth for quick changes on the spot. From there I mapped a handful of go-to presets (slow warm breathing, a cooler pulse, a fast reactive mode) so I am not fighting an app in the middle of a dark room.
Step 4: The matrix panel
The second harness carries an LED matrix panel driven by an SP107E controller. This is the fun one: it scrolls custom text and little animations, and the controller can react to music, so it visually bounces along with whatever is playing. Great for writing something cheeky across your chest and letting it pulse with the beat.
Step 5: Power
Addressable LEDs are hungrier than they look. Turn everything to white at full brightness and the current draw climbs fast, so I run a LiPo cell through a step-up regulator to hold a steady 5V, and I cap the brightness in firmware so an all-night session does not die in an hour. Fat power wires and a shared ground back to the controllers keep the far LEDs from browning out and shifting color.
Step 6: Web and phone control
Both controllers pair to my phone over Bluetooth for direct, offline control. On top of that, an ESP32 on the harness listens over WiFi and takes commands from a small server, which is how the website reaches it. That means someone can open a page, pick a color or type some text, and it lands on my chest a moment later. The full command path (website, queue, home server, radios) is written up on its own project page.
A peek at the firmware
The ESP32 side is basically a little switch statement that turns a JSON command into an effect.
// ESP32 ยท harness listens over WiFi and drives the matrix / rings
void handleCommand(const JsonDocument& doc) {
const char* mode = doc["mode"]; // color | rainbow | text | pulse | fire
if (!strcmp(mode, "color")) fillSolid(doc["r"], doc["g"], doc["b"]);
else if (!strcmp(mode, "rainbow")) rainbowWave(doc["speed"] | 6);
else if (!strcmp(mode, "text")) scrollText(doc["text"], doc["r"], doc["g"], doc["b"]);
else if (!strcmp(mode, "pulse")) breathe(doc["r"], doc["g"], doc["b"]);
else if (!strcmp(mode, "fire")) fireEffect();
FastLED.setBrightness(doc["brightness"] | 120); // capped so the battery survives the night
FastLED.show();
} What fought back
- Power was the real battle: current spikes, voltage sag, and color shift on the far LEDs
- Routing wiring inside a printed body without it looking like a mess
- Keeping Bluetooth and WiFi both stable in a crowded venue full of interference
- Balancing brightness against battery life so it lasts the whole night
Where it is going
- Cleaning up the wiring loom and publishing the CAD
- Tying effects to the phone accelerometer so lights react to how I move
- More presets and a nicer control page
- A proper build gallery once I photograph it all