release_bins/ ships firmware that yields ~1 pps on ESP32-S3 display boards, blocking calibration
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 94.4k
- Forks
- 12.5k
- Avg merge
- 21h 27m
- Merged PRs (30d)
- 43
Description
firmware/esp32-csi-node/release_bins/ ships firmware that yields 1 pps on ESP32-S3 display boards
Summary
The pre-built binaries committed under firmware/esp32-csi-node/release_bins/ are several
releases behind the published GitHub releases. Flashing them onto an ESP32-S3 board that has
an AMOLED panel produces a CSI yield of ~1 pps, which is below
CALIBRATION_GRID_MIN_RATE_HZ = 2.0 — so room calibration can never start, and
/api/v1/vital-signs abstains forever. The node looks alive in every other respect, which
makes this very hard to diagnose.
Upgrading the same board to the published v0.8.8 release fixes it completely
(1 pps → 34 pps). No hardware change.
Environment
| Board | Waveshare ESP32-S3 AMOLED 1.8" (SH8601 368x448), 16 MB flash, 8 MB PSRAM, chip rev v0.2 |
| Repo commit | b370d4f (2026-09-10) |
| Server | ruvnet/wifi-densepose:latest, CSI_SOURCE=esp32 |
| AP | 2.4 GHz, channel 1, beacon interval 102400 µs (~9.8 Hz) |
Reproduce
- Flash
release_bins/{bootloader,partition-table,ota_data_initial,esp32-csi-node}.bin
to an ESP32-S3 with a display panel. - Provision and point it at a host running the sensing server.
- Watch the serial log and
POST /api/v1/calibration/start.
Observed
Serial log, release_bins/esp32-csi-node.bin:
main: ESP32-S3 CSI Node (ADR-018 / ADR-110) — v0.7.0 — Node ID: 1
csi_collector: Promiscuous mode enabled (MGMT-only, RuView#396)
adaptive_ctrl: medium tick: state=8 yield=0pps motion=0.00 presence=0.00 rssi=-53
adaptive_ctrl: medium tick: state=8 yield=1pps motion=0.00 presence=0.00 rssi=-52
Independent measurement by binding UDP :5005 directly and counting 0xC5110001 frames
(25 s window): 1.32 Hz, matching the firmware's own yield=1pps.
Calibration is therefore unreachable:
POST /api/v1/calibration/start
→ {"success": false, "error_code": "calibration_source_required",
"error": "Choose exactly one eligible ESP32 source for room calibration.",
"eligible_sources": []}
GET /api/v1/vital-signs
→ {"authority": "abstained",
"abstention_reason": "fresh explicit calibration with exactly one occupant and qualified evidence required"}
Generating heavy WiFi traffic (two concurrent ping -i 0.05 floods) does not change the
rate, ruling out a quiet-network explanation.
Root cause
main/main.c:657 picks the promiscuous filter from a compile-time flag plus a runtime panel probe:
#ifdef CONFIG_DISPLAY_ENABLE
bool has_display = display_is_active(); /* runtime panel probe result */
#else
bool has_display = false;
#endif
if (!has_display) {
csi_collector_enable_data_capture();
}
A board with a panel keeps the MGMT-only filter (the RuView#396 crash workaround). The
comment in main/csi_collector.c:639 says that is fine because probe injection compensates:
/* MGMT-only gives ~10 Hz (beacons). Probe request injection at 10 Hz
* adds ~10 Hz probe responses from APs → ~20 Hz total, matching the
* edge processing designed sample rate of 20 Hz. */
But in the release_bins vintage that compensation does not exist:
csi_inject_ndp_frame() (main/csi_collector.c:889) is an explicit TODO stub, and
grep -rn csi_inject_ndp_frame main/ finds no call site — only a comment in
main/rv_radio_ops_esp32.c:87. So the MGMT-only path runs with nothing making up the
difference, and yield collapses.
The published v0.7.1 release ("CSI self-ping + heart-rate fix") and later address this.
release_bins/ predates it.
Fix verification
Flashing esp32-csi-node-v0.8.8-s3-8mb-flash-bundle.zip from the v0.8.8-esp32 release onto
the same board, same AP, same room:
adaptive_ctrl: medium tick: state=5 yield=33pps dsp=15.6Hz ...
adaptive_ctrl: medium tick: state=6 yield=36pps dsp=19.6Hz motion=1.00 presence=8.95 rssi=-47
csi_collector: CSI cb #900: len=256 rssi=-51 ch=1
| release_bins (v0.7.0) | v0.8.8 | |
|---|---|---|
| CSI yield | 1 pps | 34 pps |
| DSP rate | — | 19.8 Hz |
| CSI payload | 128 B (64 subcarriers) | 404 B (192 subcarriers) |
| motion / presence | 0.00 / 0.00 | 1.00 / 2–20 |
calibration/start |
eligible_sources: [] |
succeeds, rate_hz: 15.08 |
Display still initialises on v0.8.8, so this is not a display-vs-CSI trade-off.
Secondary problems in the same directory
version.txtdoes not match the binaries. It says0.6.7, but every S3/C6 binary
reports0.7.0at boot — excepts3-fair-adr110/, which is0.6.6.s3-fair-adr110/is older than the others and predates RuView#893 entirely
(stringsfinds noMGMT+DATA/data-capture symbols in it, while the v0.7.0 binaries have them).
Anyone following the README's display-less guidance to fix low yield will flash a build that
cannot capture DATA frames and see no improvement — the exact wrong turn this issue's
reporter took before finding v0.8.8.s3-fair-adr110/has noota_data_initial.bin, so its four-offset install is incomplete.
Suggested resolution
- Refresh
release_bins/from the current release, or delete it and point the README at the
GitHub releases page as the single source of truth. - Make
version.txtgenerated rather than hand-maintained. - If
release_bins/stays, add a boot-time or docs-level warning that a display-equipped S3
on a pre-0.7.1 build will starve at ~1 pps.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with firmware/esp32-csi-node/release_bins/, version.txt, and the README, then compare the bundled artifacts with the published v0.8.8 release. Inspect main/main.c:657, main/csi_collector.c:639 and :889, and main/rv_radio_ops_esp32.c:87 to understand the reported display-board path. Done means the chosen release-bin or documentation resolution is consistent and a display-equipped board no longer remains below the calibration threshold.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- documentation, embedded-iot, release
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100