feat(ecat): 启动后把 ecat_native 提到 RealTime;跳拍优化实验脚本与报告

- esp32_server: Popen 后外部 SetPriorityClass(RT/High),native 自设会被钳成 High
- 入库 skip_* 标定/实验脚本与 REPORT_ecat_skip_opt_20260917
- 前端 WIP:layout/app/polling/boot_ecat/index
- 不含 lab/skip_meter 原始采样与 preview 截图
This commit is contained in:
cbb
2026-09-17 02:32:20 +08:00
parent b3a3a365bb
commit e91d53e0fc
22 changed files with 1956 additions and 61 deletions
+107
View File
@@ -0,0 +1,107 @@
# 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,已修。