资讯动态

ESP-CSI 实战:用 Ping 触发路由器数据包采集 Wi-Fi CSI(csi_recv_router 示例深度解析)

发布时间:2026/9/18 22:39:49 来源:尧图企业网站定制
ESP-CSI 实战用 Ping 触发路由器数据包采集 Wi-Fi CSIcsi_recv_router 示例深度解析【免费下载链接】esp-csiApplications based on Wi-Fi CSI (Channel state information), such as indoor positioning, human detection项目地址: https://gitcode.com/GitHub_Trending/es/esp-csi本篇技术指南聚焦 ESP-CSI 项目基于 Wi-Fi CSI 的室内定位、人体检测等应用中最常见的联网场景让 ESP 设备作为普通 Wi-Fi Station 连接路由器通过 Ping 命令周期性触发路由器回包从而在不改造路由器的前提下采集设备与路由器之间无线信道的 CSI信道状态信息。读完本文你将掌握csi_recv_router示例的完整运行流程、串口 CSI 数据格式的含义、以及示例源码中 Ping 触发与 CSI 回调的实现原理可直接上手搭建自己的路由器 CSI 采集节点。一、示例原理为什么用 Ping 就能拿到 CSIcsi_recv_router位于 examples/get-started/csi_recv_router/README.md其核心设计思路只有一句话设备通过 Ping 命令触发路由器发送数据包从而获取设备与路由器之间的 CSI 数据。Wi-Fi CSI 是接收端在收到数据帧时由 PHY 层估算出的信道频率响应它描述了无线信号从发送端到接收端经历的多径传播特性。要拿到 CSI接收端ESP 设备必须持续收到来自某个发送端的数据包。在此示例中发送端就是日常的路由器ESP 设备以 Station 模式连接路由器获得 IP 地址并记录网关路由器的 IP设备周期性向网关发送 ICMP Ping 请求路由器收到 Ping 请求后回送 Ping Reply这些回包恰好成为承载 CSI 的免费数据帧ESP 在接收回包的同时通过esp_wifi_set_csi()使能 CSI 采集由 CSI 回调拿到每一个回包对应的信道状态信息。这种方案的优势在于无需路由器端做任何定制只要路由器支持 ICMP 协议任何普通家用/商用路由器都可以作为 CSI 信号的发射源非常适合室内定位、人体存在检测等应用的快速原型验证。二、硬件准备根据 csi_recv_router README 的说明本示例仅需单块开发板一块搭载 ESP32 / ESP32-S2 / ESP32-C3 / ESP32-S3 / ESP32-C5 / ESP32-C6 / ESP32-C61 SoC 的开发板如 ESP32-DevKitC、ESP-WROVER-KIT 等一根用于供电和程序下载的 USB 线一个可用的 Wi-Fi 路由器AP用于连接并作为 Ping 的响应方。与需要两块开发板配合的 csi_recv/csi_send 双机示例 不同本示例只需要一台 ESP 设备 一台现成路由器即可采集 CSI硬件门槛更低。三、工程结构速览在开始编译前先了解示例的工程组成examples/get-started/csi_recv_router/ ├── CMakeLists.txt # 引用 ESP-IDF 的 protocol_examples_common 组件 ├── sdkconfig.defaults # 默认配置使能 Wi-Fi CSI、提升 UART 波特率等 └── main/ ├── CMakeLists.txt ├── app_main.c # 核心逻辑连接 Wi-Fi、配置 CSI、启动 Ping └── idf_component.yml # 依赖声明idf4.4.1、esp_csi_gain_ctrl0.1.4其中顶层 CMakeLists.txt 通过EXTRA_COMPONENT_DIRS引入了 ESP-IDF 自带的protocol_examples_common组件该组件提供example_connect()函数负责根据menuconfig配置完成 Wi-Fi 或以太网连接。依赖清单 main/idf_component.yml 声明了esp_csi_gain_ctrl组件增益控制这是后续 CSI 幅值补偿的关键依赖。四、项目配置设置目标芯片与 Wi-Fi1. 设置目标芯片构建前必须先用set-target指定芯片型号idf.py set-target chip_name例如使用 ESP32-C3 开发板idf.py set-target esp32c3源码中针对不同芯片使用了条件编译配置逻辑会随目标芯片自动切换详见下文源码剖析部分因此请务必与你的硬件型号一致。2. 配置项目menuconfigidf.py menuconfig在菜单中主要完成两部分配置Wi-Fi / 以太网连接参数包括要连接的 AP 的 SSID 与密码、连接方式Station/以太网等。example_connect()会读取这些配置完成联网可参考 ESP-IDFexamples/protocols目录中关于建立 Wi-Fi 或以太网连接的说明CSI 相关开关默认配置已通过 sdkconfig.defaults 预设无需手动改动即可运行。3. 关键默认配置项说明sdkconfig.defaults 中与 CSI 采集直接相关的预设有配置项值作用CONFIG_ESP32_WIFI_CSI_ENABLEDy在 Wi-Fi 协议栈中使能 CSI 采集能力必须开启CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED空关闭关闭 TX AMPDU 聚合降低发送路径的突发负载CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM128增大动态接收缓冲区数量容纳高频 CSI 数据帧CONFIG_ESP_CONSOLE_UART_BAUDRATE921600将控制台串口波特率提升到 921600保证 CSI 大数据量输出不丢帧CONFIG_ESPTOOLPY_MONITOR_BAUD921600与上面一致idf.py monitor也使用 921600 波特率CONFIG_FREERTOS_HZ1000FreeRTOS 系统节拍 1000Hz保证 Ping 定时与回调处理的时序精度CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ240主频拉到 240MHz为 CSI 处理留足算力CONFIG_ESP_TASK_WDT_TIMEOUT_S30看门狗超时放宽到 30s避免长时间打印触发复位五、编译、烧录与运行进入示例目录并执行idf.py -p PORT flash monitor其中PORT替换为实际的串口设备名如 Linux 下的/dev/ttyUSB0、Windows 下的COM3。该命令会完成编译、烧录并打开串口监视器按Ctrl-]可退出串口监视器。若分步执行可先idf.py build再分别执行idf.py -p PORT flash与idf.py -p PORT monitor。上电后设备会依次完成NVS 初始化 → 网络初始化 → 连接 Wi-Fi 路由器 → 获取 IP → 使能 CSI → 向网关发起 Ping。完整的串口启动日志参见 csi_recv_router README 的 Example Output 一节典型的连接过程输出为I (4335) csi_recv_router: got ip:192.168.0.107, gw: 192.168.0.1 I (4346) csi_recv_router: CSI RECV 随后便开始以 CSV 行形式持续打印 CSI 数据。六、串口 CSI 输出格式详解CSI 数据以逗号分隔的文本行输出第一行是表头其后每一行是一条 CSI 记录。依据目标芯片不同输出有两种字段布局。1. ESP32 / ESP32-S2 / ESP32-C3 / ESP32-S3完整字段格式表头与 csi_recv 双机示例 相同type,id,mac,rssi,rate,sig_mode,mcs,bandwidth,smoothing,not_sounding,aggregation,stbc,fec_coding,sgi,noise_floor,ampdu_cnt,channel,secondary_channel,local_timestamp,ant,sig_len,rx_state,len,first_word,data一条示例记录CSI_DATA,0,94:d9:b3:80:8c:81,-30,11,1,6,1,0,1,0,1,0,0,-93,0,13,2,2751923,0,67,0,128,1,[67,48,4,0,0,0,0,0,0,0,5,0,20,1,20,1,...]2. ESP32-C5 / ESP32-C6 / ESP32-C61精简字段格式由于新一代芯片的wifi_pkt_rx_ctrl_t结构体字段不同表头简化为type,seq,mac,rssi,rate,noise_floor,fft_gain,agc_gain,channel,local_timestamp,sig_len,rx_state,len,first_word,data该格式额外输出fft_gainFFT 增益与agc_gainAGC 增益两个字段这两者正是增益补偿计算所需的输入。3. 字段含义与 CSI 数据体元数据字段mac为发送端路由器的 BSSIDrssi为接收信号强度rate为物理层速率sig_mode、mcs、bandwidth等描述调制与带宽信息noise_floor为噪声底channel/secondary_channel为信道信息local_timestamp为本地接收时间戳len为 CSI 数据体长度字节数first_word标记首字是否有效。CSI 数据体最后一个字段为方括号包裹的整数数组每个子载波按先虚部、后实部的顺序存放即[子载波1虚部, 子载波1实部, 子载波2虚部, 子载波2实部, ...]。该数组来自接收帧的 Long Training FieldLTF顺序为 LLTF → HT-LTF → STBC-HT-LTF依据信道与分组配置三种 LTF 不一定全部出现。注意ESP32-C5 / C61 上若开启CSI_FORCE_LLTF数据体为 16 位有符号数按大端方式每 2 字节解析为一个子载波默认配置下与其他芯片一致按单字节int8_t逐字节输出。七、源码剖析Ping 触发与 CSI 回调的实现示例的全部逻辑集中在 main/app_main.capp_main()主流程为ESP_ERROR_CHECK(nvs_flash_init()); // 1. NVS 初始化 ESP_ERROR_CHECK(esp_netif_init()); // 2. 网络接口初始化 ESP_ERROR_CHECK(esp_event_loop_create_default()); // 3. 事件循环 ESP_ERROR_CHECK(example_connect()); // 4. 连接 Wi-Fimenuconfig 配置 wifi_csi_init(); // 5. 配置并使能 CSI wifi_ping_router_start(); // 6. 启动对网关的 Ping1. CSI 使能wifi_csi_init()wifi_csi_init()按芯片平台分别构造wifi_csi_config_t关键点如下ESP32-C5 / ESP32-C61开启acquire_csi_legacy、acquire_csi_ht20、acquire_csi_ht40并将acquire_csi_force_lltf置为CSI_FORCE_LLTF源码中默认0。注释明确说明为了保证路由器的兼容性只选择 LLTF 子载波——普通路由器不一定支持 HT-LTF 或更高阶的前导码仅依赖 LLTF 是兼容性最好的选择ESP32-C6采用acquire_csi_legacyht20ht40的类似组合ESP32 系列传统芯片ESP32/ESP32-S2/S3/C3 等使用lltf_en true、htltf_en false、ltf_merge_en true、channel_filter_en true、manu_scale true、shift true的默认配置。随后通过三个调用完成注册与使能ESP_ERROR_CHECK(esp_wifi_sta_get_ap_info(s_ap_info)); // 获取当前 AP路由器信息 ESP_ERROR_CHECK(esp_wifi_set_csi_config(csi_config)); // 下发 CSI 采集配置 ESP_ERROR_CHECK(esp_wifi_set_csi_rx_cb(wifi_csi_rx_cb, s_ap_info.bssid)); // 注册回调并传入路由器 BSSID ESP_ERROR_CHECK(esp_wifi_set_csi(true)); // 使能 CSI值得注意回调注册时把当前路由器的bssid作为上下文参数传入回调内部会做 MAC 过滤只保留来自该路由器的 CSI避免其他设备的无线帧污染数据。2. Ping 触发wifi_ping_router_start()wifi_ping_router_start()使用 ESP-IDF 的ping_sock组件构造 ICMP 会话esp_ping_config_t ping_config ESP_PING_DEFAULT_CONFIG(); ping_config.count 0; // 无限次数 ping_config.interval_ms 1000 / CONFIG_SEND_FREQUENCY; // 发送周期 ping_config.task_stack_size 3072; ping_config.data_size 1; // 最小包长其中CONFIG_SEND_FREQUENCY在源码中定义为100即Ping 发送频率为 100Hz每 10ms 一包由此保证 CSI 数据帧的到达速率足以支撑连续的信道观测。目标地址取自 STA 接口的网关 IPesp_netif_get_ip_info(esp_netif_get_handle_from_ifkey(WIFI_STA_DEF), local_ip); ping_config.target_addr.u_addr.ip4.addr ip4_addr_get_u32(local_ip.gw);也就是说Ping 的目标永远是当前连接的网关路由器与 CSI 回调中的 BSSID 过滤形成同一发送端的闭环。最后通过esp_ping_new_session()与esp_ping_start()启动会话。3. CSI 回调增益补偿与数据打印回调wifi_csi_rx_cb()首先校验参数并做 MAC 过滤if (memcmp(info-mac, ctx, 6)) { return; } // 只处理来自路由器的帧对于支持增益控制的芯片ESP32-S3 / C3 / C5 / C6 / C61由CONFIG_GAIN_CONTROL开启回调会调用esp_csi_gain_ctrl组件完成增益链路处理前 100 包通过esp_csi_gain_ctrl_record_rx_gain()统计 AGC/FFT 增益基线第 100 包时取基线若CONFIG_FORCE_GAIN为 1 则用esp_csi_gain_ctrl_set_rx_force_gain()强制锁定增益每包通过esp_csi_gain_ctrl_get_gain_compensation()计算补偿系数compensate_gain并对每个子载波执行(int16_t)(compensate_gain * csi)的幅值补偿后打印。最后按芯片平台打印表头与CSI_DATA记录行s_count每包自增作为序号。整个过程直接使用ets_printf不经日志缓冲输出配合sdkconfig.defaults中 921600 的高波特率最大限度降低大数据量下的丢帧概率。八、数据后处理用配套工具可视化与分析示例输出与 csi_recv 双机示例 的数据格式完全一致因此可直接复用examples/get-started下配套的 Python 可视化工具 csi_data_read_parse.pycd examples/get-started/tools pip install -r requirements.txt # 安装 numpy/pandas/pyserial/PyQt5/pyqtgraph/scipy 等依赖 python csi_data_read_parse.py -p PORT # PORT 为采集设备的串口号该工具实时读取串口并绘制 CSI 各子载波的幅度、相位与 IQ 图同时支持-s参数将数据保存为 CSV、-l参数记录异常日志。它内部按len字段128/256/490 等自动识别子载波数量并划分 LLTF/HT-LTF 区间着色方便直观观察人体移动、位置变化引起的 CSI 波动是验证本示例采集效果最快捷的方式。注意运行工具前应先退出idf.py monitor以释放串口。九、使用建议与注意事项路由器兼容性优先示例特意只采集 LLTF 子载波以保证与普通路由器的兼容性若你的实验场景支持可在 main/app_main.c 的wifi_csi_init()中调整 HT-LTF/VHT 等采集开关获得更丰富的子载波信息。串口波特率务必匹配CSI 数据量大若 monitor 或上位机波特率低于 921600极易出现丢帧导致 Python 工具报数据不完整类错误。无线环境选择Ping 触发依赖路由器回包信道拥塞、信号过弱都会影响 CSI 帧到达率优先选择信道干净、RSSI 良好的位置。增益基线前 100 个包用于建立 AGC/FFT 增益基线此阶段数据幅值尚未完全补偿评估稳态数据时建议跳过起始段。通过本示例你可以仅凭一块 ESP 开发板和一台普通路由器就构建出稳定的 CSI 数据源为室内定位、人体检测、手势识别等上层应用提供原始信道特征输入。【免费下载链接】esp-csiApplications based on Wi-Fi CSI (Channel state information), such as indoor positioning, human detection项目地址: https://gitcode.com/GitHub_Trending/es/esp-csi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价