ESP32 · Arduino · 8-Channel Relay H-Bridge

Relay Drone Control Hub

Live control panel plus the full setup reference — eight relays wired as four H-bridges, so every motor runs forward, reverse, or off.

Live Control
not connected
Active command
--
Motor direction
M1FRONT-L--
M2FRONT-R--
M3REAR-L--
M4REAR-R--
Your browser is blocking this page from reaching the drone. This page is served over HTTPS and the drone speaks plain HTTP, so the browser refuses the request as mixed content. Two ways forward: Also check the drone is powered, you are joined to its network, and the address above is right.
Open On-Board Dashboard → http://192.168.4.1 — always works, no browser settings needed
The panel above holds a 1-second heartbeat, exactly like the on-board page. The drone's 2-second failsafe cuts every relay if that heartbeat stops — closing this tab, losing WiFi, or walking out of range all shut the motors down on their own.

The two control modes

Same networkInternet
Pathbrowser → dronebrowser → Worker → drone
Works fromsame WiFi / hotspotanywhere with internet
Round tripa few ms~0.3–1.1 s
Needsinsecure content allowedthe device key
Drone mustbe reachable on the LANhave internet access

Internet mode works because the drone sits behind NAT and cannot accept inbound connections. Instead it calls out to a Cloudflare Worker roughly twice a second, pushing telemetry up and collecting whatever command is being held. Nothing is forwarded, nothing is exposed, and both ends speak HTTPS — so unlike the direct path, there is no mixed content to unblock.

The key is not stored in this page. It lives only in your browser's local storage after you type it in. Without it the relay answers 401 to everything, which is what keeps a public URL from being a public throttle. Treat it like a password; if it leaks, run npx wrangler secret put DRONE_KEY in worker/ and reflash with the new value.
The deadman is enforced twice over. The relay only hands the drone a real command while the browser keeps refreshing it — after 2.5 s of silence it starts answering stop. Independently, if the drone's own internet drops, no command arrives at all and its local 2 s failsafe cuts the relays. Both halves fail safe on their own, so a dead phone, a dropped Wi-Fi link, or a Cloudflare outage all end with the motors off.
Do not fly this remotely. A 0.3–1.1 s round trip, no video feed, and no line of sight means you cannot know what the aircraft is doing — and flying beyond visual line of sight is illegal in most places without specific authorisation. Internet mode is for telemetry and for bench-testing the rig when you are not next to it. Turn it off entirely from the drone's WiFi Setup page, which also cuts the motors as it detaches.

Connect

Hotspot SSID
DroneESP32
Password
87654321
Dashboard
192.168.4.1
Serial baud
115200

The drone runs its hotspot and your home network at the same time (WIFI_AP_STA), so all of these work simultaneously — the hotspot is always there as a fallback when you are out of router range.

RouteAddressRequires
On-board page, hotspothttp://192.168.4.1joined to DroneESP32
On-board page, home WiFihttp://drone.localsame network as the drone
This hosted paneladdress box aboveinsecure content allowed
Use drone.local, not the raw IP. The router hands out the drone's address by DHCP, so it can change after a reboot and any bookmarked IP goes stale. The firmware publishes an mDNS record on both interfaces, so the name follows it either way. Resolves natively on iOS, macOS, Windows 10/11 and Android 12+. On anything older, fall back to the IP shown on the drone's WiFi Setup page — or give it a DHCP reservation in your router.

H-bridge topology

Each motor takes two adjacent relays. The motor's + lead goes to the COM of the first relay, the lead to the COM of the second. On both relays, NC ties to battery − and NO ties to battery +. Energising one relay but not the other puts the two motor leads on opposite rails, and which relay is energised decides which way the current — and the prop — turns.

RELAY A (+ lead) NO COM NC RELAY B (− lead) NO COM NC M + BATTERY + (both NO) BATTERY − (both NC)
Shown at rest: both relays de-energised, both motor leads sitting on battery −. No supply current flows, and the shorted winding brakes the prop. Energise relay A alone for forward, relay B alone for reverse. SPDT contacts are break-before-make, so there is no shoot-through path.
Relay A (+ lead)Relay B (− lead)Motor leadsResult
offoffboth on BATT−OFF — braked
ONoff+ on BATT+, − on BATT−FORWARD
offON+ on BATT−, − on BATT+REVERSE
ONONboth on BATT+braked — never commanded

Pin map

MotorPosition+ lead relay− lead relayRotation
M1Front-leftIN1 · GPIO 18IN2 · GPIO 19CW
M2Front-rightIN3 · GPIO 32IN4 · GPIO 33CCW
M3Rear-leftIN5 · GPIO 25IN6 · GPIO 26CCW
M4Rear-rightIN7 · GPIO 14IN8 · GPIO 27CW
IN1 and IN2 moved to GPIO 18 and 19. GPIO 34 and 35 are input-only pins on the ESP32 — they have no output driver in silicon, so they can never switch a relay regardless of firmware. Move those two jumpers. Any free output-capable pin works; 16, 17, 21, 22, 23 and 13 are also fine. The pins are #defines at the top of main.cpp.
GPIO 14 twitches at power-on. It is a bootstrap/JTAG pin and the ROM bootloader toggles it for a few milliseconds before any sketch code runs — no firmware can suppress this. Power the motor pack after the ESP32 has booted, or move IN7 to another free pin.

What each command does

CommandM1 front-LM2 front-RM3 rear-LM4 rear-REffect
flyFWDFWDFWDFWDClimb
landREVREVREVREVPowered descent
frontREVREVFWDFWDNose dips forward
backFWDFWDREVREVNose lifts
leftFWDREVFWDREVRolls left
rightREVFWDREVFWDRolls right
stopOFFOFFOFFOFFHard kill

Only /stop and the failsafe de-energise the relays. Every other command reverses polarity rather than cutting power, so land is an active powered descent that keeps running until you press STOP or the heartbeat stops.

Reverse thrust is weaker. A propeller's airfoil only works in one direction. Spun backwards it still moves air, but at roughly half the thrust and with much more drag — so land and the reversed side of each turn push noticeably harder in one direction than the other.

Reverse dead-time

Flipping a spinning motor straight from forward to reverse is plugging: back-EMF adds to the supply voltage and the surge can approach twice stall current. That welds relay contacts and browns out the pack. The firmware routes every flip through OFF first and applies the new direction 60 ms later, without blocking the loop. Tune with REVERSE_DEADTIME_MS.

Rotor directions

ESP32 8x RLY FRONT M1 CW IN1/IN2 M2 CCW IN3/IN4 M3 CCW IN5/IN6 M4 CW IN7/IN8
Diagonal pairs spin the same way; neighbours spin opposite. That is what cancels yaw torque. The exact mirror also flies — the pattern is what matters. With the H-bridge you now set this in firmware order rather than by swapping motor leads, but the props still have to match: a CW prop on a CCW motor runs its airfoil backwards.

HTTP API

EndpointEffect
GET /Flight dashboard
GET /cmd?c=flyAll four forward
GET /cmd?c=landAll four reverse
GET /cmd?c=frontFront pair reverse, rear forward
GET /cmd?c=backRear pair reverse, front forward
GET /cmd?c=leftLeft pair forward, right pair reverse
GET /cmd?c=rightRight pair forward, left pair reverse
GET /stopAll relays de-energised, clears active command
GET /status{"cmd":"left","m":[1,-1,1,-1]}
GET /wifiWiFi setup page
GET /wifi/scanAsync scan; poll until scanning:false
GET /wifi/save?ssid=&pass= — save to NVS and join
GET /wifi/statusLink state, station IP, RSSI
GET /wifi/forgetErase stored credentials

In /status, each entry of m is 1 forward, −1 reverse, 0 off. Unknown c values return HTTP 400 and leave the motor state untouched. All responses carry Access-Control-Allow-Origin: * so this page can read them cross-origin.

Joining your home WiFi

  1. Join the DroneESP32 hotspot and open 192.168.4.1.
  2. Tap WiFi Setup at the bottom of the dashboard.
  3. Tap Scan Networks, pick yours, type the password, then Save & Connect.
  4. The station IP appears once the link is up. Credentials persist in NVS across power cycles and auto-rejoin on boot.
Expect a brief stutter. Scanning and joining retune the radio, and in AP_STA mode the hotspot follows the router's channel — your phone may drop off for a few seconds. The firmware de-energises all eight relays before any scan or join for exactly this reason.

Safety behaviour

Why relays still cannot hover

The H-bridge adds reverse thrust, which is a real capability gain — but this is still a ground test rig, not a flyable aircraft:
The upgrade path: replace the relays with MOSFETs (brushed) or ESCs (brushless) driven by ESP32 PWM via ledcWrite(), and add an MPU-6050 for stabilisation. A dual H-bridge driver such as the DRV8833 or TB6612FNG gives you reverse and proportional speed on the same two pins per motor. The WiFi, dashboard, provisioning, and failsafe all carry over unchanged.

Measuring where you stand

Put the assembled drone on a kitchen scale, tare it, hold it down and run FLY. The reading drops by however much thrust you are making. Weigh the craft too: you need thrust above total weight just to leave the ground, and roughly before it is controllable. If the reading goes up on FLY, forward and reverse are swapped — flip DIR_FWD/DIR_REV for that motor, or swap its two relay leads.