ethercat-linux/docs/scope-waveform-design.md

192 lines
9.5 KiB
Markdown
Raw Permalink Normal View History

# 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 仅在组 PREOP→SAFEOP 转换时由主站编程;
本程序跳过该转换EL6695 走裸配置),因此 EL2202 的 SM0 也手动配置:
起始 0x0F00、长度 1、ctrl 0x44、enable 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 驱动 SAFEOP→OP写 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
不是 4。EL2262 输出 SM0@0x1000ctrl 0x64, enable 0x09
EL1252 输入 SM0@0x1000。
- **EL1252 锁存时间戳直接在 ESC 寄存器里**PDO 0x1A13 的存储位置):
0x09AE=status0、0x09AF=status1、0x09B0=Latch0Pos、0x09B8=Latch0Neg、
0x09C0=Latch1Pos、0x09C8=Latch1Neg通道 1→Latch0通道 2→Latch1
无需 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µs。A+C 或 B+C 组合 = 4 帧/周期,
单圈执行 ~898µs锁相保持phase_err p50≈164µ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