Wireless RGB Lighting Control System
Jul. 2025 - Sept. 2025
Designed and implemented a BLE-based wireless RGB lighting control system during an internship at NZXT, coordinating two RGB peripherals from a single central controller while investigating EMI/RFI performance inside a PC enclosure.
Project Overview
During a summer internship at NZXT, I designed and implemented a proof-of-concept wireless RGB lighting control system using Bluetooth Low Energy (BLE). The system uses a central Arduino Nano 33 BLE to coordinate two independent RGB peripherals (an SK9822 LED strip and a set of NZXT F420 RGB fans) entirely wirelessly, enclosed inside a PC case. In addition to building the prototype, I performed RF measurements to characterize the electromagnetic environment inside the chassis and authored a report recommending next steps for NZXT to evolve the prototype into a manufacturable product.
The Problem
- Current NZXT RGB peripherals require wired data connections to the motherboard, occupying headers and adding internal cable clutter
- A wireless approach offers increased flexibility and cleaner builds, but PC enclosures are a challenging RF environment
- The metallic case creates a Faraday-cage effect, trapping internal noise from GPUs, PSUs, and other switching components
System Architecture
- Central Controller
- Arduino Nano 33 BLE (nRF52840) that manages BLE connections, generates RGB frames and cycles lighting modes via a button interrupt
- Peripheral 1 — LED Strip Controller
- Arduino Nano 33 BLE that receives RGB data and commands over BLE and drives a 100-LED SK9822 strip via SPI with a 3.3V→5V level shifter
- Peripheral 2 — UART Bridge
- Arduino Nano 33 BLE that receives BLE data and forwards it over UART to a Raspberry Pi Pico, which generates the WS2812B timing-critical signal for RGB fans
- Lighting Modes
- RGB Live (continuous 19 Hz frame streaming) and four command-based presets (Rainbow, Theater Chase, Color Wipe) which can be toggled by a button on the central
Key Technical Decisions
- Chose SK9822 (SPI-compatible) over WS2812B for the LED strip because reliable WS2812B bit-banging on the Nano 33 BLE is blocked by SoftDevice interrupt preemption, and Arduino doesn't expose the nRF52840 hardware peripherals (PWM+DMA, I2S) that would generate the waveform independently of the CPU
- Added a Raspberry Pi Pico as a timing coprocessor for the RGB fans; the Pico generates the WS2812B waveform deterministically while the Nano handles BLE
- Used a star BLE topology over mesh — mesh adds overhead and broadcast complexity that is unnecessary for a PC-scale deployment of 2–3 nodes
- Implemented two operational modes — high-bandwidth Live RGB streaming and low-bandwidth command-triggered presets — to trade off flexibility vs. channel occupancy and RFI
RF Measurement Results
- Outside case: avg −91.7 dBm
- 3 inches above GPU: avg −85.9 dBm (~6 dB noisier than outside)
- Directly on GPU: avg −83.9 dBm (GPU switching circuitry results in more noise)
- Above GPU with BLE system active: avg −76.1 dBm (~10 dB increase over idle inside-case measurement)
- Conclusion: the case interior is measurably noisier, and the BLE system itself raises the noise floor. Kind of obvious!
Performance Results & Limitations
- Achieved ~19 Hz RGB frame delivery to two simultaneous BLE peripherals (vs. ~40 Hz with a single peripheral)
- Connection cap: attempts to add a third peripheral consistently failed. Nordic's SoftDevice firmware supports more concurrent connections, but ArduinoBLE doesn't expose the configuration to raise the limit
What I Did
- Designed the full hardware architecture: central controller, two BLE peripherals, level shifters, shared power and ground
- Wrote all firmware: central BLE manager, LED strip peripheral, and UART bridge peripheral
- Developed the WS2812B coprocessor flow on the Raspberry Pi Pico in CircuitPython, bridged from the UART peripheral
- Performed RF/EMI measurements using the nRF52840 dongle and RSSI Viewer across four test conditions and analyzed results
- Authored a full technical report covering theoretical analysis and research, proof of concept, measurement findings, and future recommendations for NZXT
Recommendations Delivered to NZXT
- Short-term: bypass ArduinoBLE and develop directly on the Nordic nRF Connect SDK for full control of connection interval, MTU, PHY, and TX power
- Medium-term: evaluate Bluetooth Mesh only if scaling beyond a single case; prefer command-triggered presets over streaming to minimize RFI
- Long-term: migrate to Nordic DKs or ESP32-class SoCs, integrate antenna placement into case design from the start, and schedule pre-compliance EMC testing (CISPR 32 / EN 55032) early
Some Lessons and Regrets
Ultimately, I am proud of the work that I did this project. However, there are a few decisions I wish I made differently, and a few aspects I wish I prioritized more.
Sticking with Arduino's core was the biggest constraint I'd revisit. Arduino's Mbed OS layer and the ArduinoBLE library hid the parts of the chip I needed most. ArduinoBLE / Mbed Cordio capped me at 3 simultaneous connections and didn't expose TX power, connection interval, or other BLE settings. The Nordic SoftDevice layer exposes all of those, which matters for both scaling to more peripherals and for adjusting the RF environment inside the case. Additionally, this would have given me more experience working with lower level software and more opportunities to learn.
To be clear on why I stuck with Arduino: the goal of this project was to prove the concept was feasible, not to ship a full product. Arduino got me to a working prototype much faster than programming with Nordic's SDK would have. Moving to the SDK is the correct next step for anyone taking this toward a product.
I also wish I had looked into synchronization techniques like packaging an animation start time with the data. One change that would've certainly helped with synchronization would have been to use BLE's connectionless mode. This is where the central stops connecting and instead stuffs the RGB/command bytes into its advertising packets. The LED devices become passive observers (scanners) that read the payload off the air without ever connecting.