ESP32-S3 CSI Firmware v0.2.0
Pre-built firmware binaries for the ESP32-S3 CSI sensing pipeline.
Built from main with ESP-IDF v5.2 via Docker.
What's New (since v0.1.0)
- MAC address filtering — filter CSI frames by transmitter MAC to prevent signal mixing in multi-AP environments (#101)
- TDM sensing protocol — time-division multiplexing for multistatic mesh deployments (ADR-029/031)
- Channel hopping — configurable multi-channel scanning
- NVS runtime config — configure MAC filter, TDM slots, channel list, and dwell time without reflashing
What's Included
| File | Size | Flash Address | Description |
|---|---|---|---|
bootloader.bin
| 21 KB | 0x0
| ESP32-S3 second-stage bootloader |
partition-table.bin
| 3 KB | 0x8000
| Flash partition layout |
esp32-csi-node.bin
| 789 KB | 0x10000
| CSI firmware with MAC filter + TDM |
provision.py
| — | — | NVS provisioning script (WiFi + network + MAC filter config) |
Quick Start (No Build Required)
1. Install esptool:
pip install esptool2. Flash all three binaries:
python -m esptool --chip esp32s3 --port COM7 --baud 460800 \
--before default-reset --after hard-reset \
write-flash --flash-mode dio --flash-freq 80m --flash-size 4MB \
0x0 bootloader.bin \
0x8000 partition-table.bin \
0x10000 esp32-csi-node.binReplace COM7 with your serial port (/dev/ttyUSB0 on Linux, /dev/cu.usbserial-* on macOS).
3. Provision WiFi credentials (no rebuild needed):
python provision.py --port COM7 \
--ssid "YourWiFi" --password "YourPassword" \
--target-ip 192.168.1.20 --target-port 50054. Run the aggregator:
# From the wifi-densepose repo (Rust)
cargo run -p wifi-densepose-sensing-server -- --http-port 3000 --source esp32
# Or Docker
docker run -p 3000:3000 -p 5005:5005/udp ruvnet/wifi-densepose:latest --source esp32MAC Address Filtering (New)
Filter CSI to a single AP to prevent signal mixing:
# Via provision.py (runtime, no reflash)
python provision.py --port COM7 --filter-mac "AA:BB:CC:DD:EE:FF"
# Or compile-time via Kconfig
# Set CONFIG_CSI_FILTER_MAC="AA:BB:CC:DD:EE:FF" in sdkconfig.defaultsTDM Mesh Setup (New)
For multistatic mesh with 3+ nodes:
# Node 0
python provision.py --port COM7 --ssid "WiFi" --password "pass" \
--target-ip 192.168.1.20 --tdm-slot 0 --tdm-total 3
# Node 1
python provision.py --port COM8 --tdm-slot 1 --tdm-total 3
# Node 2
python provision.py --port COM9 --tdm-slot 2 --tdm-total 3Hardware Compatibility
| Board | Status | Notes |
|---|---|---|
| ESP32-S3-DevKitC-1 | Verified | Tested with CP210x USB-UART |
| ESP32-S3-WROOM-1 | Expected | Same SoC |
| ESP32-S3-MINI-1 | Expected | Same SoC |
| ESP32 (classic) | Rebuild required | idf.py set-target esp32
|
Firmware Features
- WiFi STA + promiscuous mode for CSI capture
- ADR-018 binary serialization with 20-byte header + raw I/Q payload
- UDP streaming to configurable aggregator
- NEW: MAC address filtering (compile-time or runtime via NVS)
- NEW: TDM time-slot protocol for multistatic mesh (ADR-029/031)
- NEW: Channel hopping with configurable dwell time
- NVS runtime config — SSID, password, target IP/port, node ID, MAC filter, TDM config
- ~20 Hz CSI frame rate (LLTF + HT-LTF + STBC HT-LTF2)
- 64-128 subcarriers per frame depending on bandwidth
- Automatic WiFi reconnection (up to 10 retries)