ethercat-linux/docs/scope-waveform-design.md
Tony Cao 21b2d3bf99 J1900 <-> TwinCAT 1 kHz verification over EL6695 bridge
Re-implementation of rustbootd's ecat_el6695_* examples as a single binary
with fixes found in review and on hardware:

- DC-follow PLL hardened against period-2 hunting: slew-limited anchor
  (+/-50us/cycle), bistable-trap snap re-anchor, re-prime on stale deadline
- drift-free absolute-grid ticker mode; probe mode for timestamp forensics
- bounded-memory online stats (histograms), graceful SIGINT/SIGTERM shutdown
  with full report, error-streak abort
- timestamp plausibility filter comparing against the previous raw sample
  (avoids the deadlock after a startup outlier)
- XFC scope waveform options: --el2202 (with --el2202-dual), --el2262,
  --el1252 latch timestamp readback with per-channel edge statistics
- register access unified in regs.rs: named bit constants everywhere,
  read-modify-write for enable/activation bytes
- vendored patched ethercrab 0.7.1 (sdo_write_complete, send_raw_coe)

Verified on J1900 (PREEMPT_RT 6.6.135): 600k cycles/600s exact 1 kHz,
tx/rx zero errors, phase_err p50=164us std=5us; EL2202<->EL1252 loopback
edge interval mean 2000.24us std=24.65us.
2026-07-22 08:55:41 +08:00

192 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# TwinCAT Scope 通讯周期/抖动波形设计
- 日期2026-07-21
- 状态:设计已确认,待实现
- 相关项目:`ethercat-linux`J1900 侧 el6695-rt、`free/TwinCATProject1/PlcSync`TwinCAT 侧 PLC
## 1. 目标
在 TwinCAT Scope View 中以波形直观展示 J1900 ↔ TwinCAT 经 EL6695 桥的
1 kHz 通讯的**周期**与**抖动**,用于实时观测和稳定性评估。
## 2. 原理
让 PLC 每个 1ms 任务周期计算若干"测量变量",用 TwinCAT Scope View 按
PLC 任务周期1 kHz 采样率)经 ADS 符号采样绘图。现有数据通路已经齐
PLC 每周期刷新 `aOut1`(序列号 + 图案 + 发送时间戳J1900 侧
el6695_rt 每周期将 SM3 载荷原样回显到 SM2 并在字节 [8..16] 写入自己的
周期号。
关键洞察:发送时间戳(`F_GetSystemTime`)经回显路径原样返回,往返测量
**全程在 TwinCAT 自己的时钟域内**,无跨时钟域误差——这是端到端抖动的
理想波形信号。
## 3. 波形通道设计
| # | Scope 通道 | 来源 | 含义 | 正常形态 |
|---|---|---|---|---|
| 1 | `nRttUs` | `nEchoTimestamp - nSendTimestamp``aIn1[256..263]` 回显时间戳 本周期发送时间戳) | 端到端往返延迟(同时钟域) | ~4000µs 水平带,带宽 = 抖动 |
| 2 | `nInSeqDelta` | `nReturnedSeq` 的周期差分 | TwinCAT 视角的输入帧间隔 | 恒为 10 = 重读旧帧2 = 丢帧 |
| 3 | `nJ1900Delta` | `nJ1900Cycle` 的周期差分 | J1900 循环节拍在 TwinCAT 侧的投影 | 恒为 1偏离即对端周期异常 |
| 4 | `nJ1900JitterNs` | J1900 写入回显帧 payload[264..268] 的自测唤醒抖动i32 LE | 对端内部定时质量 | follow 模式锁定后 <1µs |
| 5 | `nJ1900PhaseErrNs` | payload[268..272] 的相位误差i32 LE | 对端读点与 TC 网格的相位 | ~165µs 直线慢漂移可见 |
通道优先级1 > 2 > 3 > 4 > 5。
- 通道 1 把"周期抖动"直接变为 µs 量级波形,是最有价值的一条。
- 通道 2/3 把 1 kHz 周期本身可视化为恒 1 直线,任何毛刺都显眼。
- 通道 4/5 需要 J1900 侧配合(见 §4.2),用于观测对端内部状态。
## 4. 实现方案
### 4.1 PLC 侧PlcSync 工程,追加 ~20 行 ST
`GVL_Sync.TcGVL` 增加:
```iecst
nRttUs : DINT; // 端到端往返 (us),同时钟域
nInSeqDelta : DINT; // nReturnedSeq 周期差分
nJ1900Delta : DINT; // nJ1900Cycle 周期差分
nJ1900JitterNs : DINT; // J1900 自测唤醒抖动 (ns),来自 aIn1[264..267]
nJ1900PhaseErrNs: DINT; // J1900 相位误差 (ns),来自 aIn1[268..271]
nPrevRetSeq : ULINT; // 差分寄存器
nPrevJ1900 : ULINT; // 差分寄存器
```
`MAIN.TcPOU` 末尾追加:
```iecst
// Waveform channel 1: same-clock-domain round-trip time.
IF GVL_Sync.nEchoTimestamp > 0 AND GVL_Sync.nEchoTimestamp >= GVL_Sync.nSendTimestamp THEN
// F_GetSystemTime 单位为 100ns
GVL_Sync.nRttUs := ULINT_TO_DINT((GVL_Sync.nEchoTimestamp - GVL_Sync.nSendTimestamp) / 10);
ELSE
GVL_Sync.nRttUs := -1;
END_IF
// Waveform channels 2/3: per-cycle deltas of the echoed sequence numbers.
GVL_Sync.nInSeqDelta := ULINT_TO_DINT(GVL_Sync.nReturnedSeq - GVL_Sync.nPrevRetSeq);
GVL_Sync.nJ1900Delta := ULINT_TO_DINT(GVL_Sync.nJ1900Cycle - GVL_Sync.nPrevJ1900);
GVL_Sync.nPrevRetSeq := GVL_Sync.nReturnedSeq;
GVL_Sync.nPrevJ1900 := GVL_Sync.nJ1900Cycle;
// Waveform channels 4/5: J1900 self-measured diagnostics from the payload.
MEMCPY(ADR(GVL_Sync.nJ1900JitterNs), ADR(GVL_Sync.aIn1[264]), 4);
MEMCPY(ADR(GVL_Sync.nJ1900PhaseErrNs), ADR(GVL_Sync.aIn1[268]), 4);
```
布局约束(重要):图案校验覆盖字节 [16..255],发送时间戳占 [256..263]
因此 J1900 诊断字放在 **[264..271]**,不会触发 `nMismatch`
需要重新激活配置(`free/rt-activate2.ps1`TwinCAT PLC 任务会中断几秒。
### 4.2 J1900 侧el6695-rt 小改,无副作用)
在回显之后、fpwr 之前,把本周期自测值写入回显帧:
```rust
// 回显之后:
tx_buf[264..268].copy_from_slice(&(jitter_ns as i32).to_le_bytes());
// follow 模式的相位误差ticker 模式写 0
tx_buf[268..272].copy_from_slice(&(phase_err_ns as i32).to_le_bytes());
```
交叉编译部署即可,不影响现有协议与 PLC 校验逻辑。
### 4.3 Scope 工程配置
1. XAE 中 PlcSync 工程旁新建 TwinCAT Measurement / Scope 工程。
2. 新建 YT Chart数据源选 PLC 符号ADS采样率挂到 PLC 任务
1 kHz与数据更新率一致
3. 将 §3 的 5 个变量拖为通道;通道 1µs与通道 2/3计数分双 Y 轴。
4. 长时间观测ADS 记录受缓冲限制,如需小时级统计,在 PLC 中追加滑动
窗口 min/max 寄存器(例如每 1000 周期输出一次窗口极值Scope 只画
统计曲线。
## 5. 验收标准
- 跑 60s el6695_rtfollow 模式Scope 中:
- `nRttUs` 为 ~4000µs 水平带(实测均值 ~4.04.3 个 PLC 周期);
- `nInSeqDelta`、`nJ1900Delta` 恒为 1无毛刺
- `nJ1900JitterNs` < 1µs锁定后`nJ1900PhaseErrNs` 165µs 直线
- 停掉 J1900 侧程序通道 2/3 应立即偏离 1断链可见)。
## 6. 备注
- 参考实现的 follow 代码从 `data[258..266]` 读发送时间戳 PLC 实际
写入位置 `aOut1[256..263]` 错位 2 字节——通道 1 必须使用 256 偏移
- 断链时 EL6695 输出替代值 0`nEchoTimestamp` 0通道 1 输出
-1 作为无效标记
## 7. 示波器方案EL2202已实现 2026-07-21
Scope 软件波形外`--el2202` 参数让 el6695_rt 每周期翻转 EL2202
总线 [1]站地址 0x1001的一个数字输出示波器可直接观察 ~500Hz
方波的沿抖动= J1900 RT 环路发送时序抖动PREEMPT_RT + follow 锁定下
µs )。
实现要点实机验证通过
- 简单 DO 端子无邮箱SM/FMMU 仅在组 PREOPSAFEOP 转换时由主站编程
本程序跳过该转换EL6695 走裸配置因此 EL2202 SM0 也手动配置
起始 0x0F00长度 1ctrl 0x44enable 0x09 EEPROM 类别 41)。
- **EL2202 过程字节语义**EEPROM PDO 0x1600/0x1601 实证
`bit0=通道1数据, bit1=通道1三态(高阻), bit2=通道2数据, bit3=通道2三态`
单通道写 0x01/0x00双通道`--el2202-dual`必须写 **0x05/0x00**——
0x03 会把通道 1 置高阻表现为"输出 1 失效"实测踩中)。
- AL 驱动 SAFEOPOP 0x01 回读验证通过后才启用逐周期翻转
- 翻转帧使单圈执行时间 ~410µs ~650µs帧开销为主仍在 1ms 预算内
60s 回归60000 周期精确 1kHztx/rx/el2202 错误均为 0
phase_err p50=164µs、std 5.3µs与不开 EL2202 时一致)。
- 升级路径总线 [3] EL2262XFC 时间戳输出可在 DC 网格精确翻转
EL2202 沿做双通道对比获得绝对相位基准[2] EL1252XFC 时间戳输入
可回采沿时刻做数值统计
## 8. XFC 方案 B/C已实现 2026-07-21
### 8.1 关键事实(实机 EEPROM 探明)
- EL1252/EL2262 **均无 CoE/邮箱**手册 §4.5 "This device has no CoE"
EEPROM SM 类别 41 中无邮箱 SM配置只能走 EEPROM 默认值 + 裸寄存器
- EEPROM 类别在 **41**SM)、**40**FMMU 用途)、**50/51**PDO
不是 4EL2262 输出 SM0@0x1000ctrl 0x64, enable 0x09
EL1252 输入 SM0@0x1000
- **EL1252 锁存时间戳直接在 ESC 寄存器里**PDO 0x1A13 的存储位置
0x09AE=status0、0x09AF=status1、0x09B0=Latch0Pos、0x09B8=Latch0Neg、
0x09C0=Latch1Pos、0x09C8=Latch1Neg通道 1Latch0通道 2Latch1)。
无需 SM/OP 配置PREOP 下即可 fprd 读取
- 两台端子的 DC 时钟0x910出厂即在运行自由跑未总线同步)。
### 8.2 方案 B`--el2262`DC 网格基准方波)
- 配置 EL2262 DC 同步单元0x0990=启动时间(当前+100ms)、
0x09A0=0x09A4=1ms、0x0980=0x03SYNC0+SYNC1 激活手动配 SM0
0x1000/1B/0x64/0x09 AL 驱动 OP
- 数据在 SYNC 事件才应用 输出沿锁定 DC 1ms 网格与帧到达抖动无关
- 注意该端子本台硬件版本EEPROM 未提供 StartTimeNextOutput PDO
32 位版本见新固件采用 SYNC 锁定方式实现
### 8.3 方案 C`--el1252`(沿时间戳回采统计)
- 每周期 fprd 34B @0x09AE跟踪两个通道 LatchXPos 变化输出上升沿
间隔统计名义 2ms与沿在 1ms 周期内的相位统计
- **帧预算**每帧往返 ~160-245µsA+C B+C 组合 = 4 /周期
单圈执行 ~898µs锁相保持phase_err p50164µsA+B+C 五帧超预算
不要同开
### 8.4 接线与验证步骤(需要现场操作)
端子点位三种 2 通道端子布局相同已核手册 1 = 通道 1
2/6 = +24V 3/7 = 0V**点 4/8 = PE接地不是通道 2**
**点 5 = 通道 2**
1. EL2202 输出 1 1)→ EL1252 输入 1 1
`--el2202 --el1252``el1252_ch1_edge_interval` 应为 2000µs 均值
抖动 µs
2. EL2262 输出 1 1)→ EL1252 输入 2** 5**
`--el2262 --el1252``el1252_ch2_edge_interval` 同样 2000µs
`ch2_edge_phase` 应锁定在固定相位DC 网格)——与通道 1环路驱动
的相位漂移对比即为环路相位误差
3. 示波器双通道CH1=EL2262 1DC 基准)、CH2=EL2202 1环路
驱动地夹接点 3/70V勿接点 4/8 PE)。