80 MHz vs 40 MHz for Wi-Fi CSI: resolution, subcarriers, and a real-world trap

2026-10-11 · 2 min read

The single most consequential decision in a Wi-Fi CSI setup is channel bandwidth. It sets how much frequency information you get per measurement — and, as we discovered the hard way, it can also break a client entirely.

1. What bandwidth actually buys you

Bandwidth Subcarriers reported (this hardware) Range bin (c/2B) Notes
20 MHz 64 (HE20) / 30-64 on ESP32 ~7.5 m coarse, but robust
40 MHz about half of the 80 MHz count ~3.75 m good compromise
80 MHz 256 (measured) ~1.875 m best resolution, needs clean spectrum

Subcarrier counts vary by chip and firmware; always log data_num from your own capture instead of assuming.

Two things bandwidth does not change:

2. The trade-off nobody mentions: legacy clients

Our Mac (a 2013-era Broadcom NIC) negotiates 40 MHz only. Put it in an 80 MHz BSS and the AP's transmit rate for that client periodically collapses to VHT-MCS0 1SS — 13.5 Mbps PHY, ~7-10 Mbps of actual downlink — while upload stays fine.

Measured, same client, same room, only the radio width changed (6 x 6 s LAN bursts after 60 s idle) — grade E evidence, raw capture and scripts published [1] [2]:

Radio setting Downlink bursts
HE80 (80 MHz BSS, client on 40 MHz) 7.4 / 7.3 / 9.3 / 9.5 / 9.6 / 9.6 Mbps
HE40 (40 MHz BSS, client native) 384 / 375 / 328 / 416 / 411 / 419 Mbps

So the "narrow-band client inside a wide BSS" case is a real firmware/rate-control failure mode — not a signal problem (RSSI was -40 dBm and the client's own receiver handled 400 Mbps in the fast state).

3. How to get both (resolution and usable clients)

Goal What to do
Maximum CSI resolution run the radio at 80 MHz; keep legacy 40 MHz clients off that radio
Legacy clients must work run 40 MHz, accept ~half the subcarriers
Both, different times script the switch (wifi-htmode HE80 to HE40, ~30 s, no reboot)
Both, simultaneously two radios / two APs — one 80 MHz for sensing, one 40 MHz (or 2.4 GHz) for legacy clients

4. Measuring it yourself

# is the client stuck?
iw dev <ap> station dump | grep -E "Station|tx bitrate|rx bitrate"
#   tx bitrate = AP -> client (the one that collapses)
#   rx bitrate = client -> AP (usually fine)

# test with LAN traffic, not a public download
# (a public mirror adds a second variable you cannot control)

Report both the PHY rate and the achieved throughput: during our collapse, 12 s of transfer moved 12.4 MB while the AP sent 12.87 MB — i.e. almost no retransmission waste, just a very low rate and an idle channel.

Related: the MCS0 rate-control deep dive · OpenWrt Wi-Fi slow after idle · reproduction guide

References and data sources

Every external claim carries a source and an evidence grade (grading scheme). Grade E marks first-party, reproducible measurements from this project.

  1. Grade E · first-party measurement This project's 10-minute raw capture (57,293 records / 600.0 s, SHA-256 00373f83…95e2)
    Router CSI Lab · 2026
    csi.okwujun.pw/zh/datasets/ · verified: Reassembled chunks verified byte-identical (2026-10-11)
  2. Grade E · first-party measurement Router CSI Toolkit — capture/analysis/watchdog scripts (MIT)
    Router CSI Lab · 2026
    csi.okwujun.pw/zh/tools/ · verified: Repository bundle has a SHA-256; scripts run on real hardware