Pick a module. Follow the wires. Flash the firmware. Done.
👥 Migrating to terminal block shields? See the Parent's Wiring Guide
Strap an IMU to a Hot Wheels car. Measure g-forces, tilt, and acceleration as it races down the track.
Each tier measures acceleration — higher tiers add precision, fusion quality, and data rate.
| Spec | Street | Forensic | Lab Grade |
|---|---|---|---|
| MCU | XIAO MG24 Sense | XIAO ESP32-S3 | XIAO ESP32-S3 |
| IMU Sensor | LSM6DS3TR-C (built-in) | Adafruit BNO055 | WitMotion WT901 |
| Axes | 6 (accel + gyro) | 9 (accel + gyro + mag) | 9 (accel + gyro + mag) |
| Fusion | None (software DIY) | Hardware (BNO055 M0+) | Kalman filter (48MHz MCU) |
| Accel Range | ±2 / 4 / 8 / 16g | ±2 / 4 / 8 / 16g | ±2 / 4 / 8 / 16g |
| Max Data Rate | 6.66 kHz (raw) | 100 Hz (fused) | 200 Hz (fused) |
| Angle Accuracy | Depends on code | ±0.5° (static) | ±0.05° (static) |
| Radio | BLE 5.3 / Thread | WiFi / ESP-NOW | WiFi / ESP-NOW |
| Interface | On-chip SPI | I2C (4 wires) | UART TTL (4 wires) |
| IMU Weight | 0g (built-in) | ~3.5g (breakout board) | ~1g (bare module) |
| IMU Power | 0.9 mA | 12 mA | 20 mA |
| IMU Price | $0 (included) | ~$15 | ~$34 |
| Total Cost | ~$13 | ~$28 | ~$42 |
| Best For | Quick demos, weight-limited | Science fair, ESP-NOW mesh | Max precision, research |
| Wire | XIAO Pin | BNO055 Pin | Purpose |
|---|---|---|---|
| Red | 3V3 | VIN | 3.3V Power |
| Black | GND | GND | Ground |
| Blue | D4 (GPIO 5) | SDA | I2C Data |
| Yellow | D5 (GPIO 6) | SCL | I2C Clock |
All 4 connections verified. Plug the XIAO into your computer via USB-C and proceed to firmware flashing.
| Pin Label | GPIO | Function | Used By |
|---|---|---|---|
| 3V3 | — | 3.3V output | BNO055 VIN |
| GND | — | Ground | BNO055 GND |
| D0 | GPIO 1 | Digital I/O | — |
| D1 | GPIO 2 | Digital I/O | — |
| D2 | GPIO 3 | Digital I/O | — |
| D3 | GPIO 4 | Digital I/O | — |
| D4 | GPIO 5 | I2C SDA (default) | BNO055 SDA |
| D5 | GPIO 6 | I2C SCL (default) | BNO055 SCL |
| D6 | GPIO 43 | UART TX | — |
| D7 | GPIO 44 | UART RX | — |
| D8 | GPIO 7 | Digital I/O | Onboard LED |
| D9 | GPIO 8 | Digital I/O | — |
| D10 | GPIO 9 | Digital I/O | — |
Select your MCU, pick a battery (or enter custom specs), and see your runtime, weight budget, and discharge safety at a glance.
The brain of the operation. Hosts the dashboard, records race times, calculates physics, and announces results.
Both methods produce the same result. The terminal block shield is an upgrade, not a necessity.
The IR sensor has 3 wires. This is the minimum to get a working finish gate.
| Wire | ESP32-S3 Pin | IR Sensor Pin | Purpose |
|---|---|---|---|
| Red | 3.3V | VCC | Sensor power (3.3V or 5V) |
| Black | GND | GND | Ground |
| Green | GPIO 4 | OUT / SIG | Signal — goes LOW when beam is broken |
Skip this section if you want a silent build. You can always add audio later.
| Wire | ESP32-S3 Pin | MAX98357A Pin | Purpose |
|---|---|---|---|
| Red | 3.3V | VIN | Amplifier power |
| Black | GND | GND | Ground |
| Orange | GPIO 15 | BCLK | I2S Bit Clock |
| Yellow | GPIO 16 | LRC | I2S Left/Right Clock |
| Blue | GPIO 17 | DIN | I2S Data |
Core wiring complete. Flash the firmware and you have a working race timer.
pio run -t uploadScrew terminal numbers match GPIO numbers. Find your GPIO, find the terminal.
| Terminal # | GPIO | M.A.S.S. Trap Use | Wire Color |
|---|---|---|---|
| 4 | GPIO 4 | IR Sensor (Finish) | Green |
| 5 | GPIO 5 | IR Sensor 2 (Speed Trap) | Optional |
| 15 | GPIO 15 | I2S BCLK (Audio) | Orange |
| 16 | GPIO 16 | I2S LRC (Audio) | Yellow |
| 17 | GPIO 17 | I2S DIN (Audio) | Blue |
| 38 | GPIO 38 | LiDAR TX (Start Gate) | Teal |
| 39 | GPIO 39 | LiDAR RX (Start Gate) | Teal |
| 2 | GPIO 2 | Status LED | Optional |
| 3V3 | — | Sensor power | Red |
| GND | — | Ground | Black |
| 5V | — | 5V power (barrel jack) | Red |
Add a race announcer to any M.A.S.S. Trap node. Announces car names, speed records, and race results out loud. Choose your hardware below.
00001.mp3, 00002.mp3, etc. The board plays files by number over UART.4 wires: power, ground, UART command, and BUSY playback status.
| Wire | ESP32-S3 Pin | DY-SV5W Pin | Purpose |
|---|---|---|---|
| Red | 5V | +5V | Board power (5V required) |
| Black | GND | GND (bottom) | Ground (use bottom GND, not power GND) |
| Blue | GPIO 15 | RXD / I01 | UART data — ESP32 TX → DY-SV5W RX (I01, NOT I00) |
| Green | GPIO 16 (input) | BUSY | Playback status — LOW = playing, HIGH = idle |
UART baud rate: 9600 (default). The DY-SV5W uses a simple binary protocol — send a byte sequence to play track N, set volume, stop, etc.
00001.mp3 — e.g. “Track Armed”00002.mp3 — e.g. “Race Started”00003.mp3 — e.g. “New Record!”Hardware connected. Now enable it in firmware and load your audio files.
00001.mp3 through 65535.mp3. Volume: 0–30 via UART or potentiometer.A dedicated ESP32-S3 with two IR break-beam sensors at a known distance apart. Measures mid-track velocity and sends it to the finish gate via ESP-NOW.
The first sensor the car crosses. This starts the speed measurement timer.
| Wire | ESP32-S3 Pin | IR Sensor 1 Pin | Purpose |
|---|---|---|---|
| Red | 3.3V | VCC | Sensor 1 power |
| Black | GND | GND | Ground |
| Green | GPIO 4 | OUT / SIG | Entry beam — first trigger |
The second sensor the car crosses. The time difference between sensors gives you speed.
| Wire | ESP32-S3 Pin | IR Sensor 2 Pin | Purpose |
|---|---|---|---|
| Red | 3.3V (shared) | VCC | Sensor 2 power |
| Black | GND (shared) | GND | Ground |
| White | GPIO 5 | OUT / SIG | Exit beam — second trigger |
Both sensors connected. Now measure your sensor spacing, flash the firmware, and configure the device.
pio run -t uploadA separate WLED controller drives WS2812B LED strips. The finish gate sends HTTP commands to change effects based on race state — no wiring between the ESP32 and LEDs.
Visit install.wled.me in Chrome and flash directly from the browser — no tools needed.
Connect to the WLED hotspot (WLED-AP), open 4.3.2.1 in a browser, and enter your WiFi credentials under WiFi Settings.
After reboot, find the WLED controller’s IP address on your router or use ping wled-XXXX.local.
On the finish gate, go to System → Config and set the WLED Host field to the controller’s IP address (e.g., 192.168.1.159).
Save and reboot. The finish gate will now send HTTP API calls to WLED on every race state change:
| Race State | WLED Effect | Description |
|---|---|---|
| IDLE | Configurable | Ambient/standby effect |
| ARMED | Configurable | Ready — waiting for car |
| RACING | Configurable | Car on track |
| FINISHED | Configurable | Celebration / result display |
Your LED strip is now linked to the race state machine. Effects change automatically on ARM, RACE, and FINISH.
A classic drag racing countdown on the start gate — red, yellow, yellow, yellow, green. Wired directly to ESP32 GPIO pins through current-limiting resistors.
Each LED gets its own GPIO pin through a 220Ω resistor. Accent LEDs share a common ground. These GPIO assignments are preliminary — firmware support is coming.
| LED | Color | ESP32-S3 Pin | Sequence Role |
|---|---|---|---|
| Stage 1 | Red | GPIO 6 | Pre-stage — car approaching |
| Stage 2 | Red | GPIO 7 | Staged — car in position |
| Amber 1 | Yellow | GPIO 15* | Countdown 3… |
| Amber 2 | Yellow | GPIO 16* | Countdown 2… |
| Amber 3 | Yellow | GPIO 17* | Countdown 1… |
| Green 1 | Green | GPIO 18 | GO! |
| Green 2 | Green | GPIO 21 | GO! (redundancy) |
| Common | — | GND | Shared ground for all LEDs |
*GPIO 15–17 are shared with audio on the finish gate. On the start gate, these pins are free since audio is typically on the finish gate only.
Solder or crimp a 220Ω resistor to the anode (long leg) of each LED. If using traffic light modules, the resistors are already on the PCB — skip this step.
Connect each LED’s resistor lead to the corresponding GPIO pin. Connect all cathodes to a shared GND rail.
Arrange physically in drag tree order: Red → Red → Yellow → Yellow → Yellow → Green → Green, top to bottom.
Mount the LEDs vertically next to the start gate, visible to the operator at the top of the track. Options:
• 3D-printed bracket (STL file coming soon)
• Drill holes in a strip of wood or acrylic
• Hot glue to a popsicle stick tower (Ben-approved method)
After flashing firmware with drag tree support, ARM the track and watch the countdown sequence fire.
7 LEDs mounted and wired. When firmware support lands, your start gate will have a real drag strip countdown.
Measures temperature, humidity, and barometric pressure. Air density affects aerodynamic drag at scale — this sensor tells you if race conditions changed between runs.
Standard I2C: 4 wires. Multiple I2C devices can share the same SDA/SCL bus.
| Wire | ESP32-S3 Pin | BME280 Pin | Purpose |
|---|---|---|---|
| Red | 3.3V | VIN / VCC | Sensor power (3.3V safe) |
| Black | GND | GND | Ground |
| Blue | GPIO 8 | SDA | I2C data |
| Yellow | GPIO 9 | SCL | I2C clock |
Default I2C address: 0x76 (or 0x77 if SDO pin is pulled high). The diagnostics page auto-detects either address.
Connect the 4 wires per the table above. I2C is bus-based — if you already have another I2C device on GPIO 8/9, just add these wires in parallel (same pins, shared bus).
Reboot the device, then open the System page and run diagnostics. Under the I2C Bus Scan section, you should see:
0x76: BME280/BMP280 or 0x77: BME280/BMP280
If neither address appears, check your wiring — I2C is picky about loose connections.
Mount the sensor near the track but not directly on it — you want ambient air readings, not radiant heat from the track surface.
BME280 detected on the I2C bus. Temperature, humidity, and pressure data available for race condition logging.
Non-contact infrared temperature sensor. Point it at the track surface to measure temperature without touching — because track temperature affects tire grip and rolling resistance.
Same I2C bus as other sensors. Shares GPIO 8 (SDA) and GPIO 9 (SCL).
| Wire | ESP32-S3 Pin | MLX90614 Pin | Purpose |
|---|---|---|---|
| Red | 3.3V | VCC | Sensor power (3.3V) |
| Black | GND | GND | Ground |
| Blue | GPIO 8 | SDA | I2C data (shared bus) |
| Yellow | GPIO 9 | SCL | I2C clock (shared bus) |
Default I2C address: 0x5A. Coexists on the same bus as BME280 (0x76/0x77) — different addresses, no conflict.
Connect the 4 wires per the table above. If the BME280 is already wired, you’re sharing the same SDA/SCL lines — just splice into the existing bus.
Reboot the device and run diagnostics from the System page. Under the I2C Bus Scan, look for:
0x5A: MLX90614 (IR Temp)
If you have both the BME280 and MLX90614, you should see two devices on the I2C scan — one at 0x76 and one at 0x5A.
Mount the sensor so it points down at the track surface at a 30–45° angle, about 3–5cm above the track. The field of view determines the measurement area:
• GY-906 (general FOV): Wide cone, ~35°. Mount closer for a smaller spot.
• DCI (narrow FOV): Tight 5° cone. Can measure a specific section from further away.
MLX90614 detected on the I2C bus. Non-contact track surface temperature measurement is ready.