Repository navigation
Field notes: keeping a 9-node ESP32-C6 CSI fleet from filling its own WiFi channel #2082
clonea1
started this conversation in
ESP32 / Hardware
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
We run 9 ESP32-C6 nodes on one AP (2.4 GHz, channel 11, IDF v5.4) and spent a few weeks working out why the fleet's frame rate decayed with uptime and why the channel sat at 80%+ busy. Most of it turned out to be the nodes' own airtime. These are the notes we wish we'd had; the firmware fix is in #2081. Numbers are measured from the AP's per-client stats and AP-side captures unless marked as a model.
1. If frame rate decays with uptime, look at the AP's per-client rate first
The cause was nodes falling back to 1-2 Mbps 802.11b on their uplink and staying there for hours. The symptom looked like a firmware leak (frame rate sliding, free heap dipping deeper over time,
send_failbursts). It wasn't one: the TX queue backs up behind a slow link (CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=128lets a lot pile up), and the minimum-heap watermark only ever goes down, so it reads like a leak.The quickest check is the AP's receive rate for each node (UniFi shows it per client). One node at 1 Mbps costs roughly 10% of the channel by itself (model, calibrated on our captures), and it drags every other node's frame rate down with it.
Blocking 11b on the nodes (#2081) took our channel from 80-85% busy to ~44% and fleet frame rate up ~26%.
2. An AP "minimum data rate" may not stop 802.11b
Our UniFi WLANs had a 12 Mbps minimum rate enabled, but with
minrate_ng_advertising_rates: falsethe 802.11b rates were still advertised, and clients still used them. Check both settings, not just the minimum.Also: any other BSS on the same radio that still allows 802.11b (a hidden or legacy SSID) can keep 11b protection on for the whole channel.
3. On the C6, firmware cannot remove 802.11b completely
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AX)(no 11B) returnsESP_ERR_INVALID_ARGon the C6 on IDF 5.4.0, 5.4.4 and 5.5.5: the driver insists on 11B in any 2.4 GHz protocol set.esp_wifi_config_11b_rate(WIFI_IF_STA, true)is the lever that works, and it is partial: captures still show RTS at 2 Mbps and some retries at 5.5 Mbps.ESP-NOW defaults to 1 Mbps 11b. With 11b off you need
esp_now_set_peer_rate_config()(we use 11g 6 Mbps). Trade-off: 6 Mbps OFDM needs more SNR, so the weakest, longest node-to-node links got worse while most improved.4. What the ping illuminator costs
With the self-ping illuminator at 50 Hz, each round trip is ~9 frames on the air, not 4 (RTS/CTS-protected data both ways plus BlockAck/BAR). That is a floor of ~1.8% of the channel per node, ~16.5% for 9 nodes (frame counts measured, airtime per frame modelled, contention not counted).
Ping replies are only ~9% of the CSI candidates each node sees (423-710 frames/s per node in our fleet, of which our frame gating keeps 26-33/s). So a lower ping rate may cost little frame rate. That part is a model; we are measuring 25 Hz vs 50 Hz now.
Side effect worth knowing:
esp_pingsends the next request only after the previous reply or timeout, so a degraded link lowers the ping rate by itself. The achieved ping rate and RTT make a cheap link-health signal on the node.5. Placement beats everything else for a weak node
Move nodes toward the AP on both axes before anything else. A node inside a cabinet gained ~11 dB just by coming out of it. For our two persistently weak nodes the answer was placement: changing RTS behaviour or frame gating did not fix them. And don't split nodes across APs or channels to help a weak one; every cross-node CSI comparison assumes one shared radio environment.
6. Slides still happen, but now recover
Legacy IoT clients dropping and rejoining the AP still knock a node's rate down at times. With 11b blocked, those dips recover on their own in under an hour instead of sticking. We are testing a node-side watchdog (reassociate, then reboot, driven by the illuminator's RTT) to cut that further, and will post results if it earns its keep.
All reactions