Remote Firework Detonator

Two ESP32 boards that arm and fire fireworks over LoRa, using a custom MAC layer and a protobuf command set.

2026

Built with C++, FreeRTOS, ESP32-S3, LoRa (SX1262), RadioLib, nanopb, PlatformIO, Podman

A shot going up, fired over LoRa from a few hundred metres away.
A shot going up, fired over LoRa from a few hundred metres away.

A remote firing system for fireworks, built on two Heltec ESP32-S3 LoRa boards. I wrote the firmware for both boards and the LoRa link layer they communicate over. A handheld detonator controller arms and fires numbered slots on a detonator board, which switches nichrome igniters through MOSFETs. The firmware is written in C++ on FreeRTOS, using RadioLib and nanopb for communication. I have fired real shots with it from a few hundred metres away, using it to create a fireworks show for my family.

The radio link

LoRa offers long range and low bandwidth, but no delivery guarantee. I wrote LoRa MAC Link (LML), a reliable point-to-point link layer on top of RadioLib. LML frames and numbers every packet, checks it with CRC16, and retries it until the receiver acknowledges it. It also splits messages of up to 512 bytes into fragments and reassembles them on the far side. The library owns the protocol, and the caller owns the radio and the FreeRTOS tasks.

An LML exchange. RTS and CTS, then one acknowledged DATA packet per fragment.

The firing protocol

The two boards exchange Protocol Buffers messages encoded with nanopb. Every command names a slot, a device, and an action ID. The detonator controller sends Arm and fires only after a matching Armed comes back.

The controller arms a slot, waits for Armed, then fires and waits for Fired.

The detonator board

The detonator board runs a separate state machine for each of its four slots. A fired slot stays spent until the controller resets it. A dedicated high-priority task times each firing pulse on the microsecond timer, so the scheduler tick cannot stretch it. Each slot drives a logic-level MOSFET that switches current through nichrome wire. The firmware holds every firing line low from boot.

Slot states. Idle, Armed, and Fired, with the reply sent on each transition.

Status

I have fired real shots from a few hundred metres away, including parallel shots. The link layer does not yet avoid collisions. When both boards transmit at once, both time out and retry.

My role

Sole author.

Media

Firing from the road at night. The detonator controller glows in the foreground.
The detonator controller shows the device and slot on its OLED as shots go out.
The bench prototype on a breadboard beside the wiring notes, then the finished detonator board on its 12V battery with the igniter terminals wired out.
Range testing from a balcony. The detonator board and its leads sit out on the railing.
Shots going off downrange.
Another from the same night.
Another from the same night.