ESP32-S3 能做 CSI 吗?能——以及什么时候你需要 5GHz 的芯片

作者 Wu Jun · 更新于 2026-10-29 · ESP32-S3, Wi-Fi CSI, esp-csi, 2.4GHz, ESP32-C5 · 约 6 分钟

当原来的 ESP32 不够用时,大多数人会看向 ESP32-S3:内存更大、算力更强、带 USB,而且比树莓派便宜。 问题永远是同一个——它能不能做 CSI,够不够用?

直接给结论

1. 官方文档实际怎么写的

ESP-IDF 的 ESP32-S3 指南把 CSI 描述为 "the channel frequency responses of sub-carriers … estimated when packets are received from the transmitter"。每个子载波存成两个有符号字节——先虚部,再实部—— 最多可能有三段训练字段:LLTF、HT-LTF、STBC-HT-LTF [2]。

最后这点比看起来重要:每包的载荷大小并不固定,取决于包类型、信道宽度与是否用 STBC。 S3 的表格从 128 字节(20MHz non-HT,64 个复数值) 一直到更大的 HT-LTF 情况。 请记录实际上报的长度,而不是硬编码子载波数——这条规则和路由器 CSI 完全一样。

ESP32-S3 还有一个官方记录的硬件特性:当 first_word_invalid 为真时,CSI 缓冲区的前四个字节无效, 必须丢掉 [2]。忘了这一步,你会在每次测量开头看到一个固定的凹口。

2. 让 S3 吐出 CSI(四步调用)

ESP-IDF 的流程很短 [2]:

  1. 在 menuconfig 里打开 Wi-Fi CSI(Components config → Wi-Fi → Wi-Fi CSI);
  2. 用 esp_wifi_set_csi_rx_cb() 注册接收回调;
  3. 用 esp_wifi_set_csi_config() 配置;
  4. 用 esp_wifi_set_csi() 打开。

同一页里还有两条实践提醒:

应用侧,espressif/esp-csi 自带收发示例和 csi_data_read_parse.py 解析器; ESP32-CSI-Tool 是面向数据集的 CSV 路线;ESPectre 把整套东西封装成 ESPHome 存在传感器 [1] [4] [5]。

3. 一块 ESP32-S3 加一台路由器

第一次做台架验证时,最简单且变量最少的拓扑是:ESP32-S3 连接 2.4GHz AP,持续向网关发 Ping, 再从返回包读取 CSI。它不需要第二块 ESP32,就能跑通接收回调、CSI 配置、串口输出和解析器。 当前官方对应示例是 examples/get-started/csi_recv_router [1]。

下面的命令按 2026-10-29 检查到的示例仓库编写。这里使用的是 C 级厂商文档与源码证据,不是本站 E 级实测:我们还没有把 ESP32-S3 接到已发布的路由器实验里。

git clone https://github.com/espressif/esp-csi.git
cd esp-csi/examples/get-started/csi_recv_router

# 先激活你准备使用的 ESP-IDF,并在编译前确认版本。
. "$IDF_PATH/export.sh"
idf.py --version

idf.py set-target esp32s3
idf.py menuconfig
idf.py -p /dev/ttyUSB0 -b 921600 flash monitor

在 menuconfig 里打开 Example Connection Configuration,填写 2.4GHz SSID 和密码。 示例的 sdkconfig.defaults 已打开 Wi-Fi CSI,并把 monitor 设为 921600 baud。Component Manager 还会下载 esp_csi_gain_ctrl,因此即使 ESP-IDF 已安装,第一次构建仍需要网络。

当前路由器示例刻意只申请 LLTF:

wifi_csi_config_t csi_config = {
    .lltf_en           = true,
    .htltf_en          = false,
    .stbc_htltf2_en    = false,
    .ltf_merge_en      = true,
    .channel_filter_en = true,
    .manu_scale        = true,
    .shift             = true,
};

这是兼容性选择,不代表最大载荷。如果打开 HT-LTF 或 STBC-HT-LTF,必须重新检查 len、包类型和带宽, 不能继续假设数组形状没变;也不要把 LTF 标志不同的行混进同一个 CSI 矩阵或模型。

示例把 Ping 间隔设为 1000 / CONFIG_SEND_FREQUENCY,当前 CONFIG_SEND_FREQUENCY=100。 这是请求速率,不是保证到手的 CSI 速率:AP 要回应、空口要抢到发送机会、回调队列要跟得上, 串口还要能承受文本输出。921600 baud 下,较长 CSI 行加上日志可能已经吃满 monitor。 在把数据当成 100Hz 之前,必须先统计实际收到的 CSI_DATA 行数和队列丢弃数。

4. 按字节解析,不要自己发明单位

官方示例每个回调输出一行 CSI_DATA。对 S3 格式,关键字段包括 len、first_word、rssi、rate、 sig_mode、mcs、bandwidth、stbc、channel、local_timestamp 和 data [2] [1]。最小解析器应保留这些字段:

def decode_s3_csi(row):
    raw = list(row["data"])
    if len(raw) != row["len"]:
        raise ValueError(f"len says {row['len']}, data has {len(raw)} bytes")
    if row["first_word"]:
        raw = raw[4:]  # 4 个无效字节 = 2 个复数采样
    if len(raw) % 2:
        raise ValueError("CSI byte count must be even")
    return [(raw[i], raw[i + 1]) for i in range(0, len(raw), 2)]

每个返回元组是一组 (虚部, 实部)。len 是字节数,不是子载波数;只有去掉无效前缀后, len(data) / 2 才是复采样数。sig_len 描述收到的 Wi-Fi 帧,也不是 CSI 载荷长度。

建立数据集前,至少执行下列检查;任何一项失败都应隔离或丢弃该行:

检查 目的
len 非零、为偶数,并与 data 实际长度一致 发现 CSV 截断和解析错误
记录 first_word,并用同一规则处理 否则前两个复采样会带固定伪影
时间戳单调,而且全库单位一致 S3 字段是设备时间,不是墙上时钟
每行保留信道、带宽、STBC 与 LTF 标志 包类型会改变载荷形状
记录实际行/秒和丢弃数 配置的 Ping 频率不是实测 CSI 率

先做短时串口采集,查看 len、channel、bandwidth、sig_len 的分布,再决定存储格式。 超过几分钟的采集,应优先使用二进制 UDP 或带帧长度的二进制串口协议。JSON 和逗号分隔整数便于调试, 但在持续高速率下开销很大。

5. 5GHz 的问题

这是包装盒上不会写的取舍:

芯片 频段 CSI 说明
ESP32(经典)/ ESP32-S3 2.4GHz 有 最便宜的入口,20/40MHz
ESP32-C6 2.4GHz 有 Wi-Fi 6(仅 2.4GHz)
ESP32-C5 2.4 + 5GHz 有 双频 Wi-Fi 6,WIFI_BAND_MODE_AUTO [3]
路由器(MT7986 + mt76 CSI) 5GHz 有 80MHz / 256 子载波 / 8 条链

Espressif 的双频支持是真实的——C5 的 API 暴露了同时工作在 2.4GHz 与 5GHz 的 band mode [3]——但要记住:目前没有任何 Espressif 芯片给你 80MHz 的 CSI 视野。 需要那一档分辨率(呼吸、精细动作)时,路由器路线才是现实选择,也正是本站实测并公开的那条路线。

所以诚实的决策规则是:

6. 这对你意味着什么

ESP32-S3 是一个有第一方文档背书的正经 CSI 平台——「S3 做不了 CSI」是错的, 「S3 能做到 80MHz」同样是错的。先把频段和信道宽度定死,再选硬件。

相关:ESP32 CSI 入门 · ESP32 人体检测 · 路由器 CSI 复现 · 2.4GHz vs 5GHz

参考与数据来源

本文的每条外部结论都标注来源与证据等级(分级标准);标注 E 级的是本项目可复现的实测数据。

  1. C 级 · 官方资料 espressif/esp-csi — Applications based on Wi-Fi CSI
    Espressif Systems
    github.com/espressif/esp-csi · 核实: GitHub API 2026-10-29 (stars 1,723; README confirms the complete ESP32 series list and three sender/receiver routes) · 官方 README 原文:“All ESP32 series support CSI, including ESP32 / ESP32-S2 / ESP32-C3 / ESP32-S3 / ESP32-C5 / ESP32-C6 / ESP32-C61.”
  2. C 级 · 官方资料 ESP-IDF — Wi-Fi Channel State Information (ESP32-S3)
    Espressif Systems
    docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-guides/wifi-driver/wifi-vendor-features.html#wi-fi-channel-state-information · 核实: official docs fetched 2026-10-29 (ESP32-S3 CSI section: LTF/byte-count table and the first_word_invalid note)
  3. C 级 · 官方资料 ESP-IDF — esp_wifi API (ESP32-C5): band mode 2.4G + 5G
    Espressif Systems
    docs.espressif.com/projects/esp-idf/en/stable/esp32c5/api-reference/network/esp_wifi.html · 核实: official docs fetched 2026-10-11 (text includes "band mode 2.4G + 5G (WIFI_BAND_MODE_AUTO)" and 802.11anacax)
  4. C 级 · 官方资料 StevenMHernandez/ESP32-CSI-Tool — active/passive CSI extraction for ESP32
    S. M. Hernandez
    github.com/StevenMHernandez/ESP32-CSI-Tool · 核实: GitHub API 2026-10-11 (stars 571, MIT, last push 2024-07-16)
  5. C 级 · 官方资料 francescopace/espectre — Wi-Fi CSI motion sensing for ESP32 (ESPHome)
    F. Pace
    github.com/francescopace/espectre · 核实: GitHub API and official README fetched 2026-10-29 (stars 9,700; GPLv3; ESPHome source path, Direct API port 62587 and supported chips documented) · 官方项目提供 ESPHome、Native MQTT、Matter 与浏览器烧录路线;同一块 ESP32 覆盖一个区域,不识别身份或人数。