# EtherCAT 跳拍优化实验报告 日期:2026-09-17 台子:i7-14700K + I210「以太网 2」100Mbps + GD32E508 从站(3 电机在线) 主判据:**不跳拍率**(`late_per_s` / `skip_per_s`,来自 `/api/motor/dbg` 拍环 `k>0`) 原始数据:`lab/skip_meter/*.json` ## 一、结论(按性价比) | 措施 | 1ms late/s | 判定 | |---|---|---| | 基线(进程 Normal,原绑定) | ~10–25(漂) | 起点 | | 进程 RealTime | 均值更好(~8–12) | **有效,保留** | | 关 I210 上 VMware Bridge 等协议 | 有助(单独测过 4.1/s 一枪;混方差) | **有效,保留** | | 关中断裁决 ITR=0 | **70/s** | **有害,已还原** | | 关 EEE | **98/s** | **有害,已还原** | | ITR=50(非法)/固定低 ITR | 更差或无效 | **已还原** | | 关 IPv4/IPv6(本卡仅链路本地) | 无可测收益 | **已重新打开** | | **周期 2ms** | **0.06/s ≈ 不跳** | **主判据下的最优运行点** | | 周期 4ms | 0 | 同上,更宽裕 | **主判据一句话**: - 必须 **1ms**:当前约 **10–17 late/s**(work p50≈366µs,余量只有 ~630µs,偶发 1ms 尖峰必跳)。 - 允许 **2ms**:约 **0.06 late/s(16s 仅 1 拍)**,达成 500.00Hz,**不跳拍率优先时选这个**。 ## 二、机理回顾(本轮再确认) 跳拍 = `pdo_worker` 自旋到绝对截止点时 `next_t <= now`,补 `k` 个周期。 本轮形态: 1. **send 长尾**(`pcap_sendpacket` ≈1ms,rxc=1)— Npcap/驱动/DPC,不是从站。 2. **rx 长尾**(等回包 ≈1ms,rxc≈200+)— 主机接收路径,不是总线被占。 从站 `load_perm≈336‰`、WKC 3/3、layout=dense,**没有被别的 EtherCAT 用户抢走**。 注意:本轮中后期 `rx p50` 从早晨的 ~90µs 变成 ~330µs(进程重启/绑定调整后未回到 90)。 这压缩了 1ms 档余量,是 late 从 ~10 抬到 ~15–25 的主要原因之一;机理未完全闭合(怀疑桌面负载/DPC 形态漂移,非网卡高级属性)。 ## 三、已落地的改动(可回滚) ### 3.1 保留 1. **`ecat_native` 启动尝试 RealTime**(`tools/ecat/ecat_native.c`) - 先提 `SE_INC_BASE_PRIORITY_NAME` 再 `SetPriorityClass(RT)`。 - **实测自设仍会被钳成 High**(令牌无该特权时 API 仍可能返回成功/或被系统钳位)。 - 因此 **`esp32_server.py` 在 Popen 后从外部 `SetPriorityClass(RT)`**(能粘住,已验证)。 - 备份:`tools/ecat/build_native/ecat_native.pre-rt.exe`。 2. **I210 绑定裁剪**(仅「以太网 2」) - 已禁用:`vmware_bridge`, `ms_pacer`, `ms_lldp`, `ms_rspndr`, `ms_lltdio`, `ms_server`, `ms_msclient` - 仍启用:`INSECURE_NPCAP`(必须)、`ms_tcpip`/`ms_tcpip6`(已恢复) - 快照:`lab/skip_meter/nic_bind_*.json` 3. **I210 高级属性**:已还原为实验前原值(ITR=适应性,EEE 按系统,FlowControl Rx+Tx 等)。 ### 3.2 运行态 - 周期:**已恢复 1ms**(与实验前一致,避免破坏你当前用法) - WKC 3/3、OP、loop=1、`pcore_mask=0x50` - 进程优先级:当前为 **RealTime**(外部设置) ## 四、回滚 ```powershell # 1) 恢复 I210 协议绑定 python scripts/skip_bind_experiment.py --restore python scripts/skip_bind_noip.py --restore # 若曾关过 IP,脚本会 Enable # 2) 恢复 I210 高级属性(用任一 nic_before_*.json) python scripts/skip_nic_experiment.py --restore --snap lab/skip_meter/nic_before_1789580690.json # 3) 还原旧主站二进制 # 先停 ecat_native,再: Copy-Item tools\ecat\build_native\ecat_native.pre-rt.exe tools\ecat\build_native\ecat_native.exe -Force # 然后由 esp32_server 自动重拉,或手动跑 ecat_web.bat # 4) 进程优先级改回 High(不必还原绑定时用) Get-Process ecat_native | ForEach-Object { $_.PriorityClass = 'High' } ``` 网卡高级属性原始快照:`lab/skip_meter/nic_before_1789580690.json`(含 ITR=65535 等)。 ## 五、标定/实验脚本 | 脚本 | 用途 | |---|---| | `scripts/skip_rate_meter.py` | 标准跳拍率标定(主判据) | | `scripts/skip_host_snapshot.py` | 主机/I210/进程现场快照 | | `scripts/skip_prio_ab.py` | High vs RealTime A/B | | `scripts/skip_quiet_periods.py` | 1/2/4ms 静默对比 | | `scripts/skip_nic_experiment.py` | 网卡高级属性实验 + `--restore` | | `scripts/skip_bind_experiment.py` | 绑定裁剪 + `--restore` | | `scripts/skip_restart_native.py` | 进程热重启对照 | ## 六、建议 1. **不跳拍优先 → 生产用 2ms**(本轮实测 16s 仅 1 拍 late)。若必须 1ms,接受 ~1%/拍 late,并保证 RealTime + 无 VMware 桥。 2. **重启 `esp32_server` 后**,新代码会在拉起 `ecat_native` 时自动提 RealTime;当前若只重启 native 不重启 server,需再手动设一次。 3. 勿再关 ITR/EEE 做“低延迟”优化——本台子上是反向的。 4. `rx p50` 90→330µs 未闭合,下一轮可专查桌面 DPC(关 360/同步盘/任务管理器常刷)对照。 ## 七、我在这轮里错过又改掉的判断 1. 「关中断裁决能降 send 长尾」→ 实测 70/s,立刻还原。 2. 「关 EEE 能降功耗相关抖动」→ 实测 98/s,立刻还原。 3. 「进程自设 RealTime 会粘住」→ 日志显示成功但 `PriorityClass=High`,改为启动方外部设置。 4. 首版标定器拿 unix 时间去比 `now_s()` 拍环 → 恒 0 late,已修。