Community project
Interactive Photo Booth Controller
This interactive photo booth controller combines an ESP32-based lighting system with a Raspberry Pi 5 compute engine to create a fully automated photo capture and display setup. The project integrates addressable RGB strips, dual-white CCT lighting, and dual camera modules to deliver professional-quality booth photography with real-time lighting control and image processing.
Builders will receive a complete wiring diagram, detailed parts list with sourcing information, step-by-step assembly instructions covering power distribution, level shifting, and LED integration, plus firmware configuration guides for both the WLED controller and custom ESP32 application. The guide walks through safety protocols, component mounting, and system calibration to get the photo booth operational.
Wiring diagram

Gather all the parts
Assemble it in 14 steps
1. Safety first — all work with mains de-energised
Before wiring anything, confirm the switched power strip is OFF and unplugged from the wall. All three supplies (ATX PSU, Pi 5 USB-C PSU, screen 12V PSU) must be disconnected from mains. Work on a non-conductive surface. The Corsair RM650e contains lethal mains voltage internally even when the rocker switch is OFF — never open its enclosure.
- Never work on wiring with any supply plugged into mains.
- RM650e internal capacitors can hold charge — if you have handled it live, wait 30 s after disconnecting before touching modular cable sockets.
2. Force-on the Corsair RM650e (PS_ON jumper)
On the RM650e's 24-pin ATX main connector: locate pin 16 (green PS_ON wire) and pins 15 or 17 (black COM wires). Bridge them with a short solid-core wire or a commercial 24-pin ATX paperclip/breakout block. This permanently latches the PSU to turn on whenever mains is applied — the PSU's own IEC rocker switch then serves as the booth DC backbone on/off. Tape or heat-shrink any unused 24-pin pins to prevent accidental shorts. Do NOT connect the 24-pin connector to a motherboard.
- Commercial '24-pin ATX jumper' blocks (available for <$5) are tidier than a loose wire and have labelled positions.
- Leave the 3.3V (orange) and 5VSB (purple, pin 9) wires capped — not used by this design.
- 5VSB on pin 9 is live whenever mains is connected, even before PS_ON pulls low. Never short it.
3. Build the 12V and 5V distribution buses
From the RM650e's SATA or Molex modular cables, tap 12V (yellow) and 5V (red) wires plus COM (black). Feed each rail into a WAGO 221 lever connector junction block as the distribution point. From each junction, run individual branches through inline blade/glass fuse holders to each load group. Suggested fuse sizing: • 12V → WS2815 strip + cap: 5A fuse • 12V → CCT strip (via MOSFETs): 3A fuse • 12V → button LEDs ×3: 1A fuse • 5V → ESP32-A + ESP32-B: 2A fuse • 5V → Pi Zero 2 WH (via bonnet): 3A fuse • 5V → HUB75 Panel 1 power: 5A fuse (18AWG wire) • 5V → HUB75 Panel 2 power: 5A fuse (18AWG wire) All COM (black) wires join at a single star-point WAGO connector — this is the system common ground.
- Use 18AWG red/black for 12V and 5V power runs, 22AWG for signal.
- Label each fused branch at the fuse holder with a permanent marker.
- Rate fuses at the load's expected current + 50%, rounded up to the next common value.
- Verify the actual amperage printed on the RM650e label for 5V and 12V rails before finalising fuse values — use the label amps, not the total wattage.
- Do not daisy-chain fuse holders in series — each branch gets its own fuse from the distribution junction.
4. Mount and power ESP32-A (WLED Controller)
Mount the WeAct ESP32-A board on M2.5 standoffs inside the enclosure. Connect: • ESP32 5V pin → 5V fused branch (ESP32 branch) • ESP32 GND pin → common ground star point Do not connect GPIO pins yet.
- Check the specific WeAct ESP32 silkscreen carefully — the 5V/VIN pin position varies between WeAct revisions. Confirm with a multimeter before powering.
5. Install 74AHCT125 level shifter
Mount the 74AHCT125 (DIP-14 or breakout) near ESP32-A. Wire: • Pin 14 (VCC) → 5V rail • Pin 7 (GND) → common ground • Pin 1 (1OE, output enable) → GND (tie permanently low = always enabled) • Pin 2 (1A, input) → ESP32-A GPIO16 (22AWG) • Channels 2/3/4: tie their OE pins (pins 4, 10, 13) HIGH (to VCC) to disable unused outputs • Pin 3 (1Y, output) → one leg of the 390Ω series resistor (instance: resistor_ws2815) • Other leg of 390Ω resistor → WS2815 strip DIN
- The AHCT125 inputs are TTL-compatible — 3.3V from ESP32 is above the 2V VIH threshold at 5V supply, so level shifting works correctly.
- Place the IC as close to the ESP32 as practical to keep the 3.3V input trace short.
6. Connect WS2815 RGB strip
At the start of the WS2815 strip: 1. Solder or connect a 1000µF ≥16V electrolytic capacitor (cap_ws2815) between V+ and GND on the strip's input pads — positive leg to V+, negative to GND. Keep leads short. 2. V+ → 12V fused branch (18AWG red, WAGO junction) 3. GND → common ground star (18AWG black) 4. DIN → 390Ω resistor output (from level shifter 1Y) Segmented runs: each segment's input JST-SM 3-pin pigtail receives V+/GND/DIN daisy-chained from the previous segment.
- Install the bulk cap before powering — without it, the first few LEDs can be damaged by inrush on power-on.
- Check strip polarity on V+. WS2815 strips are marked with an arrow indicating DIN direction.
- Electrolytic capacitors are polarised — positive leg to 12V, negative to GND. Reversed polarity will destroy the cap.
7. Install CCT ring light MOSFETs and strip
Mount MOSFET module #1 (mosfet_warm) and module #2 (mosfet_cool) on standoffs or directly into the enclosure. Wire each module: • GATE ← ESP32-A GPIO17 (warm) / GPIO18 (cool) — 22AWG • SOURCE → common ground • DRAIN → CCT strip W wire (warm) / C wire (cool) CCT strip V+ (common anode) → 12V fused branch The MOSFETs pull each strip channel's return to ground in a PWM pattern.
- Logic-level MOSFETs (IRLZ44N, AOD4184) switch fully with 3.3V gate drive — no level shifting needed here.
- No external gate resistor needed if the module has one built in. Verify the module datasheet.
8. Flash and configure WLED on ESP32-A
With ESP32-A powered via USB (before connecting it to the RM650e 5V rail), use Schematik's Deploy button to flash the firmware.cpp fallback sketch, then switch to WLED binary from install.wled.me (select ESP32). After flashing, connect via WLED's own Wi-Fi AP to configure: • LED Output 1: Type WS2815/WS281x, Data pin 16, GRB, count = your LED count • LED Output 2: Type PWM White, Data pin 17 (warm) • LED Output 3: Type PWM White, Data pin 18 (cool) • Enable CCT mode for outputs 2+3 • Wi-Fi: join booth SSID • Note the assigned IP address — this is what ADR-0027 TcpWledTransport points to.
- The bench-test firmware (firmware.cpp) sweeps the CCT channels to verify MOSFET wiring before you flash WLED.
- Verify MOSFET channels respond to the bench sweep before committing to the WLED binary.
9. Mount and power ESP32-B (Custom FW / Spare)
Mount ESP32-B identically to ESP32-A. Connect 5V → 5V fused branch, GND → common ground star. Default transport is TCP/Wi-Fi — no signal wires to Pi 5 needed in normal configuration. Flash the project custom firmware (adapters/lighting/esp32.py companion sketch from the project repo) via Schematik Deploy. If opting for UART serial transport instead, also wire: • ESP32-B TX → Pi 5 GPIO15 (physical pin 10) — 22AWG • ESP32-B RX ← Pi 5 GPIO14 (physical pin 8) — 22AWG • Add a wire from Pi 5 GND (physical pin 6 or 9) to the RM650e common ground star point (required for shared logic reference).
- Only bond Pi 5 GND to the RM650e star point if using the wired UART transport. If TCP-only, the Pi 5 operates on its separate PSU with no ground tie.
10. Assemble Pi Zero 2 WH + RGB Matrix Bonnet + HUB75 panels
1. Mount the Raspberry Pi Zero 2 WH on M2.5 standoffs. 2. Press the Adafruit RGB Matrix Bonnet onto the Pi Zero 2 WH 40-pin header — board-to-board, no loose wiring. 3. Connect the RM650e 5V branch to the bonnet's power input (screw terminal or barrel jack on the bonnet board — check the specific bonnet revision). 4. Verify whether the bonnet back-powers the Pi Zero via the GPIO 5V pin. If it does, no separate power cable to the Pi is needed. If it does NOT, attach a micro-USB pigtail from the 5V branch to the Pi's power micro-USB — but never connect both paths simultaneously. 5. Run HUB75 IDC ribbon from bonnet HUB75 OUT to Panel 1 HUB75 IN. 6. Run second HUB75 IDC ribbon from Panel 1 HUB75 OUT to Panel 2 HUB75 IN. 7. Inject 5V power to each panel's dedicated power input terminal (JST or screw terminals on the panel PCB, separate from the HUB75 IDC port) with its own 18AWG pair from the fused 5V branch. Do not rely on the HUB75 ribbon for panel power.
- Mount panels side-by-side to form the 128×32 combined canvas.
- The bonnet has onboard level shifters (3.3V→5V) for HUB75 — no extra level shifting needed.
- Never power the Pi Zero from both the GPIO 5V pin (bonnet) and the micro-USB simultaneously. Pick one, verify on bench first.
- HUB75 ribbon 5V pins are not rated for full panel current — always inject panel power directly.
11. Wire arcade buttons to Raspberry Pi 5
For each of the three illuminated arcade buttons: Switch circuit (active-low): • Button switch terminal A (SW1) → Pi 5 GPIO: Button1→GPIO5 (pin 29), Button2→GPIO6 (pin 31), Button3→GPIO13 (pin 33) — 22AWG • Button switch terminal B (SW2) → common GND (Pi 5 GND pin 30 or 34, tied to system GND) LED circuit (always-on, 12V): • LED+ spade terminal → 12V fused branch (use 4.8mm quick-connect spade) • LED- spade terminal → common GND Buttons use Pi 5's internal pull-up resistors in software (RPi.GPIO PUD_UP) — no external resistors needed on switch legs.
- Use 4.8mm quick-connect spade terminals for button tabs for tool-free replacement.
- Label each button's GPIO wire at both ends before routing inside the enclosure.
12. Connect cameras, touchscreen, and Pi 5 power
1. Cameras: insert 22-pin MIPI CSI-2 ribbons (300mm) into Pi 5's CSI0 (Camera Module 3 standard) and CSI1 (Camera Module 3 Wide) connectors. The ribbon carries power and data — no other wiring needed. 2. Touchscreen HDMI: micro-HDMI (Pi 5 HDMI0) → HDMI cable (1m) → Riverdi screen HDMI input. 3. Touchscreen USB touch: Pi 5 USB-A port → USB-A to USB-C cable → Riverdi screen USB-C touch port. 4. Touchscreen power: connect dedicated 12V PSU (screen_psu) barrel/terminal to Riverdi screen 12V IN. 5. Pi 5 power: official 27W USB-C PSU (pi5_psu) → Pi 5 USB-C power port. This PSU must NOT be substituted. 6. Plug all three mains supplies into the switched power strip.
- The Pi 5 official USB-C PSU is mandatory — a generic 5V supply without USB-PD CC resistors caps the Pi at 3A (15W) and it will brown out under combined camera + screen + USB load.
- CSI ribbon connectors are fragile — lift the latch gently, insert ribbon contacts-down, then close latch.
13. Optional — TCS34725 ambient colour/lux sensor
This sensor is Stage-future (KI-006) and can be omitted now. When adding: • VIN → Pi 5 3.3V (physical pin 1) • GND → Pi 5 GND (physical pin 6) • SDA → Pi 5 GPIO2 (physical pin 3, I2C1 SDA) • SCL → Pi 5 GPIO3 (physical pin 5, I2C1 SCL) No level shifting needed — Pi 5 I2C1 is native 3.3V and the TCS34725 breakout is 3.3V-native. I2C address: 0x29.
- After wiring, scan I2C with: sudo i2cdetect -y 1 — should show 0x29.
14. First power-on and validation sequence
Follow this order for first power-on: 1. Double-check all connections with the strip OFF — especially common ground star completeness, and that no 12V wires touch 5V branches. 2. Plug the switched power strip into mains. Turn ON the strip (booth master switch). 3. RM650e fan should spin; measure 12V and 5V at WAGO junction blocks with a multimeter before connecting any loads. 4. Connect ESP32-A only — verify WLED bench-sweep firmware dims the CCT strip smoothly and no LED on the WS2815 strip flickers without data. 5. Connect ESP32-B — verify it joins Wi-Fi and responds to TCP commands. 6. Connect Pi Zero 2 WH + bonnet + panels — verify marquee displays a test pattern (run matrix-test binary from rpi-rgb-led-matrix). 7. Connect Pi 5 — verify boot, CSI camera detection (libcamera-hello --list-cameras), touchscreen HDMI, and arcade button GPIO reads. 8. Final check: confirm 12V button LED branches are all lit.
- Measure current on each branch fuse before finalising — verify no branch is near its fuse rating at expected operating brightness.
- Keep a USB keyboard plugged into Pi 5 for the first boot in case of network/config issues.
- Never connect any load to a rail you haven't verified with a multimeter first.
- If any fuse blows on first power-on, find and fix the short before replacing the fuse.
Review all connections
1. Connections between "wall_outlet" and "ESP32"
2. Connections between "power_strip" and "ESP32"
3. Connections between "atx_psu" and "ESP32"
4. Connections between "esp32_a" and "ESP32"
5. Connections between "esp32_b" and "ESP32"
6. Connections between "level_shifter" and "ESP32"
7. Connections between "resistor_ws2815" and "ESP32"
8. Connections between "ws2815_strip" and "ESP32"
9. Connections between "cap_ws2815" and "ESP32"
10. Connections between "mosfet_warm" and "ESP32"
11. Connections between "mosfet_cool" and "ESP32"
12. Connections between "cct_strip" and "ESP32"
13. Connections between "pi5" and "ESP32"
14. Connections between "touchscreen" and "ESP32"
15. Connections between "button1" and "ESP32"
16. Connections between "button2" and "ESP32"
17. Connections between "button3" and "ESP32"
18. Connections between "tcs34725" and "ESP32"
19. Connections between "pi_zero2w" and "ESP32"
20. Connections between "matrix_bonnet" and "ESP32"
21. Connections between "hub75_panel1" and "ESP32"
22. Connections between "hub75_panel2" and "ESP32"
Deploy the firmware
// Pixelbooth — wiring reference only.
// This project is designed in KiCad; no firmware is compiled here.
void setup() {}
void loop() {}Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.



