Motion Light Controller

An ESP32, a PIR sensor, and a servo that physically flips your wall light switch. No mains wiring.

This build lets a motion sensor control an existing wall switch. The servo moves the toggle itself, so the device never touches 120V. The light stays on for five minutes after the last detected motion, and a dark web panel gives manual control from anywhere over MQTT.

2026 Embedded / Home Automation MQTT over TLS
Demo
Walk through
Hardware

What is in the build

The whole controller is a small stack of parts sitting on or near a standard wall switch. The servo does the mechanical work, and everything else is low voltage and easy to move around.

ESP32 dev board

Runs the Arduino firmware, handles the servo, reads the PIR, and keeps the MQTT connection alive.

AM312 PIR motion sensor

Small, low-power sensor that detects movement in the room and refreshes the shutoff timer.

MG90S metal-gear servo

Flips the physical wall switch. Enough torque to move a standard toggle without touching the wiring.

Custom servo mount bracket

3D-printed bracket that holds the servo in the right spot above the switch plate.

Status LEDs

Green when the light is on, red blinking when the system is idle and waiting for motion.

USB-C power supply

Powers the whole unit from a normal phone charger or wall adapter.

Safety

Why a servo instead of a relay

A relay would have to splice into the wall wiring and switch 120V. That means mains voltage, code mistakes, and the risk of leaving the switch in a weird state. A servo physically moves the existing toggle instead. Nothing in the build touches high voltage. If the device is unplugged or the code crashes, the switch still works exactly like it did before.

Build progress
Wiring the ESP32, PIR, and servo into the printed enclosure on the bench.
Wiring the ESP32, PIR, and servo into the printed enclosure on the bench.
Test fitting the servo arm against the switch plate to find the right throw.
Test fitting the servo arm against the switch plate to find the right throw.
Closing up the case and checking the status LED before mounting it on the wall.
Closing up the case and checking the status LED before mounting it on the wall.
Firmware

Retriggering timer

Every time the PIR sees motion, the shutoff deadline resets. The light only turns off after five minutes of sustained stillness, not on a fixed countdown that could cut out while someone is barely moving.

Slow servo sweeps

The servo moves the switch in 2-degree increments instead of snapping instantly. That limits the current spike at the start of each move and avoids browning out the board when the servo starts under load.

Remote control

From local WiFi to MQTT over TLS

The first version ran a small web server on the ESP32 itself, so you could control the light while connected to the same network. That worked fine inside the house, but it broke the moment you left WiFi range. The current version uses a HiveMQ Cloud broker and connects over TLS. The ESP32 dials out and keeps the connection open, so it works through NAT without port forwarding or a VPN.

Retained messages

The UI loads with the current switch state already there, even if the device just connected.

Last Will and Testament

If the controller loses power or drops offline, the panel marks it offline immediately.

No port forwarding

Because the ESP32 opens the outbound connection, your home router does not need any inbound rules.

Control panel

Dark web UI

The frontend is a single dark control panel hosted on GitHub Pages. A live animated SVG of the switch plate flips in sync with the real servo, and the plate glows amber whenever the light is on.

Manual on/offDisable motion1 min delay5 min delay10 min delay30 min delay

The countdown ticks locally and resyncs from the device whenever a new MQTT message arrives, so the timer does not drift if you leave the page open.

Open source

Build it or borrow from it.

The full Arduino firmware, 3D servo mount files, and the dark web panel are all in the GitHub repo. Stack is C++ / Arduino, MQTT over TLS, HiveMQ Cloud, HTML/CSS/JS, MQTT.js, and GitHub Pages.