Skip to content

fix(esp32): make CSI callback actually fire (connected-STA CSI + self-ping)#955

Open
merajmehrabi wants to merge 1 commit into
ruvnet:mainfrom
merajmehrabi:fix/esp32-csi-callback-never-fires
Open

fix(esp32): make CSI callback actually fire (connected-STA CSI + self-ping)#955
merajmehrabi wants to merge 1 commit into
ruvnet:mainfrom
merajmehrabi:fix/esp32-csi-callback-never-fires

Conversation

@merajmehrabi
Copy link
Copy Markdown

Problem

On ESP32-S3, wifi_csi_callback never firespkt_yield=0pps, the ADR-081 adaptive controller stays in ADAPT_STATE_DEGRADED, and every rv_feature_state_t packet reads motion=0, presence=0, DEGRADED. The node streams but senses nothing. Reproduced on v0.6.5 and v0.7.0, on 3 boards, on both HT40 and HT20 APs. (Same symptom as #954 and the closed #521.)

Root cause

The ESP32 CSI engine only produces CSI for received OFDM frames (it measures the L-LTF/HT-LTF training fields). csi_collector_init() captured CSI only through a MGMT-only promiscuous filter (the #396 Core-0 DATA-sniff crash workaround), so the only CSI-eligible frames were beacons — which APs almost always transmit at non-OFDM DSSS basic rates (1–2 Mbps) that carry no training field. Net: zero CSI-eligible frames → zero callbacks.

The OFDM traffic source the comments describe ("probe request injection at 10 Hz") does not exist — csi_inject_ndp_frame() has no callers and is a TX-only null-data stub anyway (TX does not generate CSI).

The prior #521 fix — esp_wifi_set_ps(WIFI_PS_NONE) — was a wrong diagnosis (modem sleep) committed without a hardware check; it is present in current firmware and the symptom persists.

Fix

Mirror Espressif's reference (esp-csi/examples/get-started/csi_recv_router): use plain connected-STA CSI and generate received OFDM frames by pinging the gateway at 50 Hz (esp_ping). Each ICMP echo reply is a unicast OFDM data frame addressed to the station → the CSI engine fires.

Disabling promiscuous mode also removes the #396 Core-0 crash surface entirely (we no longer sniff DATA frames; we only receive our own low-rate replies).

Verification (ESP32-S3 N16R8, ESP-IDF v5.4)

csi_collector: Promiscuous DISABLED — connected-STA CSI + self-ping (fix #521/#954)
csi_collector: self-ping started -> 192.168.0.1 @50Hz
csi_collector: CSI cb #1: len=256 rssi=-65 ch=3      <- callback now fires
adaptive_ctrl: state=6 yield=32pps motion=1.00 presence=10.48   <- SENSE_ACTIVE

Host-side decode of 0xC5110006: DEGRADED 0/70, PRES_VALID|RESP_VALID|HB_VALID, breathing ≈ 9–13 bpm and heart rate ≈ 40–46 bpm computed.

Notes / follow-ups

  • motion saturates at 1.00 in early testing — likely the constant self-ping baseline; the motion threshold/normalisation may want a follow-up tune.
  • Ping rate (50 Hz) and target (gateway) could be made NVS-configurable.
  • 1 file changed (firmware/esp32-csi-node/main/csi_collector.c); builds clean for esp32s3, 47% app partition free.

Closes #954. Supersedes the unverified #521 fix.

…-ping)

The ESP32 CSI engine only produces CSI for received OFDM frames (L-LTF/
HT-LTF). csi_collector_init() captured CSI only via a MGMT-only promiscuous
filter (the ruvnet#396 Core-0 DATA-sniff crash workaround), so the only
CSI-eligible frames were beacons -- which APs transmit at non-OFDM DSSS
rates carrying no training field. Result: wifi_csi_callback never fired,
pkt_yield=0pps, adaptive controller stuck in DEGRADED, motion/presence=0
(ruvnet#521, ruvnet#954). The probe/NDP "injection" in the comments is an uncalled
TX-only stub, and the prior ruvnet#521 fix (esp_wifi_set_ps(WIFI_PS_NONE)) was
committed without hardware verification and does not resolve it.

Fix: mirror Espressif's esp-csi csi_recv_router reference -- disable
promiscuous mode and ping the gateway at 50 Hz so received OFDM replies
drive the CSI engine. Running without promiscuous also sidesteps the ruvnet#396
Core-0 DATA-sniff crash entirely.

Verified on ESP32-S3 (N16R8), ESP-IDF v5.4: CSI cb fires, yield ~30 pps,
adaptive state -> SENSE_ACTIVE, DEGRADED cleared, breathing + heart rate
computed with PRES/RESP/HB_VALID flags set.

Closes ruvnet#954. Supersedes the unverified ruvnet#521 fix.

Co-Authored-By: claude-flow <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant