ESP32-C3 & ESP-NOW

Wireless Kinetic Light Baton

Swing it, and the lights follow. The baton tracks your motion, drives its own LED strip, and beams that energy over ESP-NOW so any powered follower in range can join in. Fast enough that it feels instant.

Live ESP-NOW & Delta Math Simulator

Shake or swipe your mouse/touch quickly inside the Kinetic Charge Pad to build up energy. You'll see the charge state (0.0 to 1.0) broadcast from the baton and picked up by the follower in real time. Both sides smooth the motion with delta time interpolation instead of snapping around.

SWIPE RAPIDLY HERE TO CHARGE

Handle (Sender)

0%
Haptic Motor: OFF
ESP-NOW (30ms rate)

Follower (Receiver)

Target Charge: 0.00
Current Charge: 0.00

Project Overview

The Wireless Kinetic Light Baton is the brains and the showpiece. It reads your swing from an onboard IMU, drives haptic feedback and a WS2812B strip built into the handle, and constantly broadcasts a compact motion packet over ESP-NOW. Power up a separate follower ESP32 somewhere else in the room, wire it to another LED strip, and it listens to the same motion data without any pairing hassle.

Why ESP-NOW?

ESP-NOW is a connectionless protocol from Espressif that skips all the usual Wi-Fi handshake nonsense. The baton fires off a 4-byte energy update every 30 milliseconds on the open broadcast channel, and it arrives in under 1.5 milliseconds. Fast enough that you'd never notice any delay. Down the road, MAC-address handshakes could let baton 1 talk to follower 1 specifically instead of every follower in range, but for now it's one open channel and it just works.

The Delta Math Easing

When you swing fast, the baton might jump from 0.0 to 0.7 in one shot. If the LEDs just snapped to that directly, it'd look choppy. Both the baton and every follower use the same dt-based exponential easing function to slide toward the target smoothly:

currentCharge += (targetCharge - currentCharge) * easingFactor * dt;

This keeps things looking fluid even if a packet drops or timing gets a little wobbly. There's a snap window of < 0.001 to stop it from jittering forever once it's basically there.

Parametric CAD Configurator

There's a fully parametric 3D CAD configurator built for this project so you can dial in a baton that fits your actual hardware. It runs in the browser using a WASM-compiled geometry kernel, so boolean operations on the model happen instantly.

Configurable Part Parameters

You can tweak pretty much everything about the physical design:

  • Central Rod: Outer diameter and wall thickness.
  • Housing / Sled: Length and wall thickness to fit your battery cells, ESP32-C3, haptic motor driver, switch, and IMU.
  • Ridges & Rings: Decorative profiles, flange heights, and how snug the end caps sit.
  • Fasteners: M3 hole diameters and thread depth.
  • Handle Profile: Length and where the lanyard hole goes.

The configurator also supports exploded assembly views, blueprint wireframe mode, and instant STL export when you're ready to slice.

[ OPEN PARAMETRIC 3D CONFIGURATOR ]

Hardware Pinout Configuration

Wired up on ESP32-C3-DevKitM-1 dev boards.

1. Handle Device (Sender)

Function GPIO MPU6050 MPU6500 Description
I2C SDA 2 SDA SDA/SDI I2C data line (same wiring for both sensors)
I2C SCL 3 SCL SCL/SCLK I2C clock line (same wiring for both sensors)
Soft GND 4 GND GND Pulled LOW in setup to act as a soft ground for the sensor
INT Pin 5 INT INT Motion interrupt; kicks the device awake from deep sleep
FastLED 6 n/a n/a Signal line for the local WS2812B strip
Motor PWM 7 n/a n/a PWM output to the haptic motor driver
Sensor Power 3.3V VCC VDD/VCC 3.3V rail; both IMUs run on this
Extra Pins NC AD0, XDA, XCL, FSYNC NCS, SDO, FSYNC Leave these floating; not needed in I2C mode

2. Follower Device (Receiver, Ember)

Function GPIO Description
FastLED 6 Data out to the WS2812B strip (74 LEDs)
Power 5V External 5V; LEDs pull a lot of current
GND GND Common ground

ESP32 Firmware Architecture

Two separate firmware stacks on ESP32-C3 boards: custom C++ on the baton, and Ember on the followers. The baton does motion sensing, local LEDs, and broadcasting in one place; followers are drop-in listeners you can scatter around a space on their own strips.

1. Reactive Handle (Sender)

The baton polls the IMU over I2C to figure out how hard and fast you're swinging. It uses a soft-ground trick on Pin 4 to avoid running an extra wire, and the combined motion data drives both the onboard WS2812B strip on Pin 6 and the haptic motor on Pin 7 through three different buzz modes:

  • Low Energy (< 0.3): Slow, gentle Heartbeat pulse.
  • Medium Energy (< 0.7): Faster rhythmic Gallop pattern.
  • High Energy (>= 0.7): Full-on Shimmer/Buzz.

At the same time, it broadcasts the energy level over ESP-NOW every 30ms on the open channel, and eases its own local strip with the same delta-time interpolation so the handle lights stay fluid too.

2. Reactive Follower (Receiver)

Followers run Ember, a stack-based bytecode VM built for expressive addressable LED installs. Power one up, wire a WS2812B strip to Pin 6, and it listens on the open ESP-NOW broadcast channel for the baton's motion packets. Color, brightness, and how many pixels are lit all shift with the energy level, and the same delta math easing smooths out jitter so the animation stays clean even if a packet goes missing. Later on, paired MAC addresses could narrow that to one baton and one follower instead of every device in range.

[ BROWSE FIRMWARE SOURCE CODE ]