基于ESP32无线通信链路延迟测试结果
English | 中文
By RichJ233
测试过的方案包括:
- ESP32-S3 UART ↔ Wi-Fi UDP
- ESP32-S3 ↔ ESP32-C3 ESP-NOW
- ESP32-S3 native USB 本地回环
- 双 ESP32-S3 ESP-NOW
- 一对类nRF24无线串口透传模块
硬件
| 设备 | 用途 | 备注 |
|---|---|---|
| ESP32-S3 开发板 | Wi-Fi UDP、ESP-NOW、native USB、双S3测试 | 淘宝商品 669443108979 |
| ESP32-C3 开发板 | 早期S3↔C3 ESP-NOW测试 | 天猫商品 730121383834 |
| 成对无线串口透传模块 | 115200 8N1串口透传测试 | 淘宝商品 618869877874 |
| 测试11 无线串口透传模块 | 115200 8N1串口透传测试 | 淘宝商品 563716927856 |
| Windows PC | 运行Python测试程序 | 主机侧使用time.perf_counter_ns计时 |
实验
| 名称 | 计时范围 |
|---|---|
| One-way host-visible latency | PC从一端写入数据,到PC从另一端收到完整数据 |
| Radio RTT | MCU内部测量的无线A→B→A往返,不包含PC、Python和USB |
| Host RTT | Python发出请求,到Python收到对应返回数据 |
| Complete closed-loop latency | 状态上行、PC计算和指令下行的总时间 |
| Delivery rate | 最终成功收到数据的比例 |
| Deadline hit rate | 数据是否在目标周期内到达 |
1. ESP32-S3 UART ↔ Wi-Fi (UDP) ↔ PC
测试路径
串口设备/PC
→ UART
→ ESP32-S3
→ Wi-Fi UDP
→ PC
配置:
- UART RX:GPIO18
- UART TX:GPIO17
- UART Baudrate: 115200
- UDP port:2333
- PC Wi-Fi IP:192.168.0.233
- ESP32 IP:192.168.0.2
- PC串口:COM4
- Wi-Fi Router: TP-Link 5626
- Data sent: 32 bytes
结果
双向透传稳定工作,延迟约29ms。 反方向的UDP→ESP32-S3→UART测试结果近似。
2. ESP32-S3 ↔ ESP32-C3 ESP-NOW单向测试
测试方法
程序交替测试两个方向:
S3 → C3
C3 → S3
- ESP-NOW channel:6
- 关闭Wi-Fi power saving
- 非两个方向同时连续发送。
结果
- S3→C3:典型约3.3–3.5 ms
- C3→S3:典型约3.1–7 ms
- 测试中出现过TIMEOUT
S3↔C3 ESP-NOW stop-and-wait RTT:
| Metric | Result |
|---|---|
| Valid | 1000/1000 |
| Median | 4.374 ms |
| P95 | 10.910 ms |
| Maximum | 25.573 ms |
3. ESP32-S3 ↔ ESP32-C3 双向通信测试
测试路径
→ C3 UART
→ ESP-NOW
→ S3 native USB
→ PC
→ S3 native USB
→ ESP-NOW
→ C3 UART
后续测试均使用固定32-byte二进制帧,带frame type、sequence和CRC16。
100 Hz结果
目标周期为10 ms,共1000个正式样本。
| 指标 | 状态上行 | 指令下行 | 完整往返 |
|---|---|---|---|
| Valid | 996/1000 | 961/1000 | 961/1000 |
| Mean | 8.989 ms | 43.291 ms | 51.985 ms |
| Median | 5.937 ms | 29.801 ms | 38.834 ms |
| P90 | 22.034 ms | 100.828 ms | 108.076 ms |
| P95 | 25.079 ms | 132.754 ms | 137.270 ms |
| P99 | 33.683 ms | 174.612 ms | 179.279 ms |
| Maximum | 57.814 ms | 190.135 ms | 200.578 ms |
| ≤10 ms / planned | 69.80% | 22.30% | 7.70% |
50、75和100 Hz结果对比
| 目标频率 | 周期 | Complete median | Complete mean | Complete P95 | Deadline hit |
|---|---|---|---|---|---|
| 50 Hz | 20 ms | 26.140 ms | 32.040 ms | 74.988 ms | 39.30% |
| 75 Hz | 13.333 ms | 148.256 ms | 314.213 ms | 1125.351 ms | 2.30% |
| 100 Hz | 10 ms | 38.834 ms | 51.985 ms | 137.270 ms | 7.70% |
75 Hz测试中出现了大量ESP_ERR_ESPNOW_NO_MEM、pending overwrite和retry,测试结果可能会受到ESP-NOW队列和发送状态的影响。
Active + latest测试
有更新的数据时,旧的waiting packet会被替换,避免旧数据不断排队。
一个已经提交的active packet
+
一个等待发送的latest packet
100 Hz、2000个样本的结果:
| 指标 | 状态上行 | 指令下行 | 完整往返 |
|---|---|---|---|
| Valid | 1891/2000 | 1436/2000 | 1436/2000 |
| Median | 6.400 ms | 5.414 ms | 14.635 ms |
| Mean | 9.839 ms | 9.654 ms | 17.722 ms |
| P95 | 26.359 ms | 29.141 ms | 43.264 ms |
| ≤10 ms / planned | — | — | 24.10% |
板端submit计数与对端radio receive计数相等。
4. ESP32-S3 native USB本地回环延迟测试
测试路径
→ PC
→ S3 native USB
→ 原样返回
→ S3 native USB
→ PC
结果
| Metric | Result |
|---|---|
| Valid | 1000/1000 |
| Mean | 0.529 ms |
| Median | 0.501 ms |
| P95 | 0.660 ms |
| P99 | 0.934 ms |
| Maximum | 1.397 ms |
5. 双ESP32-S3 ESP-NOW RTT 测试
测试路径
→ S3-A firmware
→ ESP-NOW PING
→ S3-B firmware
→ ESP-NOW PONG
→ S3-A firmware
时间使用板端esp_timer_get_time测量,不包含Windows、Python和USB。
结果
| Metric | Result |
|---|---|
| Valid | 2000/2000 |
| Minimum | 2.973 ms |
| Median | 3.602 ms |
| Mean | 4.442 ms |
| P90 | 6.936 ms |
| P95 | 8.476 ms |
| P99 | 12.363 ms |
| Maximum | 23.785 ms |
| ≤10 ms / planned | 97.30% |
板端统计:
- A:2100次发送,0 timeout,0 send error
- B:2100次接收,2100次回复,0 send error
6. 双S3 host-triggered RTT 测试
测试路径
→ Python
→ USB
→ S3-A
→ ESP-NOW
→ S3-B
→ ESP-NOW
→ S3-A
→ USB
→ Python
结果
| Metric | Internal radio RTT | Complete host RTT |
|---|---|---|
| Valid | 1714/2000 | 1714/2000 |
| Median | 3.606 ms | 4.774 ms |
| Mean | 4.927 ms | 6.029 ms |
| P95 | 11.925 ms | 13.028 ms |
| P99 | 18.070 ms | 19.223 ms |
| Maximum | 41.194 ms | 42.363 ms |
7. 双S3 single-USB stop-and-wait 测试
测试路径
→ Python
→ USB A
→ S3-A
→ ESP-NOW
→ S3-B
→ ESP-NOW
→ S3-A
→ USB A
→ Python
S3-B的USB不在计时路径中。
测试一次只允许一个transaction in flight,同时记录完整主机RTT、内部ESP-NOW RTT和host+USB overhead。
结果
| Metric | Run 1 | Run 2 |
|---|---|---|
| Valid / planned | 2436/3000 | 2470/3000 |
| Complete median | 4.515 ms | 4.342 ms |
| Complete mean | 5.866 ms | 5.697 ms |
| Complete P95 | 13.070 ms | 12.728 ms |
| Complete P99 | 18.406 ms | 16.814 ms |
| Complete maximum | 30.694 ms | 43.885 ms |
| Radio median | 3.743 ms | 3.541 ms |
| Radio mean | 5.099 ms | 4.941 ms |
| Host+USB median | 0.709 ms | 0.712 ms |
| Host+USB P95 | 1.018 ms | 1.041 ms |
两次测试的板端统计都记录了3100次完整无线往返:
- A提交3100次,B收到3100次
- B回复3100次,A收到3100次
- 无radio queue drop
- 无NO_MEM
- 无callback failure
- 无loop timeout
- Python端记录了589和547次host timeout。
8. 双S3异步双向通信测试
测试方法
- 状态按100 Hz持续发送,不等待上一条指令返回
- Python使用两个独立reader thread持续读取两个USB端口
- 收到状态后立即计算并发送指令
- 控制器只处理一批数据中最新的状态
结果
| 指标 | 状态上行 | 指令下行 | 完整往返 |
|---|---|---|---|
| Valid / planned | 2996/3000 | 2482/3000 | 2482/3000 |
| Minimum | 1.948 ms | 1.955 ms | 4.047 ms |
| Median | 3.671 ms | 3.426 ms | 11.894 ms |
| Mean | 8.346 ms | 8.838 ms | 14.328 ms |
| P90 | 21.906 ms | 25.891 ms | 29.685 ms |
| P95 | 22.700 ms | 32.874 ms | 36.668 ms |
| P99 | 28.675 ms | 42.358 ms | 47.351 ms |
| Maximum | 51.027 ms | 62.686 ms | 64.884 ms |
| ≤10 ms / planned | 63.77% | 58.47% | 38.70% |
9. 类nRF24无线串口透传模块:12-byte顺序往返
串口和帧格式
- 115200 baud
- 8 data bits
- no parity
- 1 stop bit
- 12-byte frame
A5 5A | uint32 sequence | PING | CRC16-CCITT
测试路径和计时
同一台PC连接两个USB串口:
t0:PC写入serial A
→ 模块A
→ 无线
→ 模块B
t1:PC从serial B收到完整帧
t2:PC校验后写回serial B
→ 模块B
→ 无线
→ 模块A
t3:PC从serial A收到返回帧
计算:
- A→B visible latency = t1 - t0
- PC forwarding = t2 - t1
- B→A visible latency = t3 - t2
- Full RTT = t3 - t0
结果
| Metric | A→B | PC forwarding | B→A | Full RTT |
|---|---|---|---|---|
| Mean | 8.465 ms | 0.014 ms | 8.585 ms | 17.063 ms |
| Median | 8.326 ms | 0.010 ms | 8.581 ms | 16.920 ms |
| P90 | 8.933 ms | 0.021 ms | 8.651 ms | 17.524 ms |
| P95 | 8.988 ms | 0.028 ms | 8.722 ms | 17.589 ms |
| P99 | 9.260 ms | 0.058 ms | 9.034 ms | 18.054 ms |
| Minimum | 7.910 ms | 0.005 ms | 7.980 ms | 16.494 ms |
| Maximum | 27.299 ms | 0.814 ms | 11.332 ms | 35.873 ms |
| Std | 0.510 ms | 0.025 ms | 0.127 ms | 0.529 ms |
样本统计:
- Planned:3000
- Valid:2973
- Failed:27
- Success rate:99.100%
12-byte数据在115200 8N1下,四段UART传输的理论总时间约4.167 ms。
10. 类nRF24无线串口透传模块:同时双向发送
测试方法
两个Python worker通过threading.Barrier尽量同时开始:
serial A发送A帧,同时serial B发送B帧
两边分别等待对端数据
帧为12 bytes,包含header、source、sequence、payload和CRC。
结果
出现大量通信失败,没有形成稳定、可引用的延迟统计或准确失败率。
这个结果不能单独证明商品规格意义上的half-duplex,也可能由同时发射碰撞、竞争或radio不能同时Tx/Rx造成。但该链路不适合依赖两个方向同时传输。
11. 类nRF24无线串口透传模块:10-byte Python echo RTT
配置
- 主端口:COM9
- 回显端口:COM10
- 115200 8N1
- 10-byte packet
- Warm-up:50
- Formal measurement:1000
- Send interval:20 ms
- Packet timeout:100 ms
帧格式:
AA 55 | uint32 sequence | uint16 data | CRC16-MODBUS
测试路径
Python主线程
→ COM9
→ 模块A
→ 无线
→ 模块B
→ COM10
→ Python echo thread原样写回COM10
→ 模块B
→ 无线
→ 模块A
→ COM9
→ Python主线程
结果
| Metric | Result |
|---|---|
| Warm-up valid | 49/50 |
| Formal valid | 1000/1000 |
| Mean | 21.013 ms |
| Median | 21.578 ms |
| P90 | 22.024 ms |
| P95 | 22.124 ms |
| P99 | 22.391 ms |
| Minimum | 19.121 ms |
| Maximum | 24.892 ms |
| Std | 0.998 ms |
测试的实际频率约24.2 Hz。
结果对照
| 方案 | 测量范围 | 主要结果 | 样本/有效率 |
|---|---|---|---|
| Wi-Fi UART↔UDP | 双向透传 | 已确认连通,约 29 ms | — |
| S3↔C3 ESP-NOW | 单向host-visible | 典型约3–7 ms,有TIMEOUT | — |
| S3+C3 100 Hz通信 | 状态→PC→指令返回 | mean 51.985 ms,P95 137.270 ms,≤10 ms 7.70% | 961/1000 |
| 双S3 ESP-NOW | 板端radio RTT | mean 4.442 ms,median 3.602 ms,P99 12.363 ms | 2000/2000 |
| 双S3 single-USB Run | PC→A→B→A→PC | mean 5.697 ms,median 4.342 ms,P99 16.814 ms | 2470/3000 |
| 双S3异步完整通信 | 状态→PC→指令返回 | median 11.894 ms,P99 47.351 ms,≤10 ms 38.70% | 2482/3000 |
| 透传模块顺序往返 | A→B→PC转发→A | mean 17.063 ms,P99 18.054 ms | 2973/3000 |
| 透传模块同时双向 | 两端同时发送 | 大量失败,无稳定统计 | — |
| 测试11 透传模块echo | COM9→COM10 Python echo→COM9 | mean 21.013 ms,P99 22.391 ms | 1000/1000 |