DC 配置
什么是 DC?
DC(分布式时钟)是 EtherCAT 的硬件级时间同步机制。它让网络中所有从站共享同一个时间基准,使各从站能在完全相同的时刻执行动作。
- 多轴同步运动 -- 所有伺服驱动器在同一时刻更新位置指令,消除轴间抖动
- IO 同步采样 -- 所有输入输出在同一时刻,主站读取时数据一致
- 精确 I/O 时间戳 -- 输入数据带有硬件时间戳,主站可精确知道采样发生的物理时刻
- 确定性输出 -- 输出在固定时刻生效,不受 EtherCAT 帧到达时间的抖动影响
主站级 DC 配置。通过 master 直接调用。
- 单个从站的 DC 配置请参见 从站 DC 同步
- 周期属性请参考 配置 - 周期配置
- DC 同步监控请参考 主站诊断 - DC 同步
方法
configureDCAll
public int configureDCAll(int sync0Ns, int sync1Ns)
为所有 DC 从站配置 DC 同步。所有参数单位:纳秒(ns)。默认自动完成:
- 传播延迟测量 -- 读取各端口接收时间并计算延迟
- 偏移计算 -- 基于传播延迟自动计算每个从站的相位偏移
- DC 应用 -- 写入 SYNC0/SYNC1 周期和起始时间到各从站
参数:
sync0Ns(int) -- SYNC0 周期(纳秒),0 表示禁用 DCsync1Ns(int) -- SYNC1 增量时间(纳秒),0 表示仅 SYNC0
返回值:
int-- 0 表示成功
示例:
master.configureDCAll(1_000_000, 0); // SYNC0 = 1ms
master.configureDCAll(1_000_000, 500_000); // SYNC0 = 1ms, SYNC1 = 500us
125us 高性能配置(WDK 驱动推荐):
master.Config().LoopCycle(125_000); // PDO 交换周期 125us
master.configureDCAll(125_000, 0); // SYNC0 = 125us
1ms 常规配置(通用场景):
master.Config().LoopCycle(1_000_000); // PDO 交换周期 1ms
master.configureDCAll(1_000_000, 0); // SYNC0 = 1ms
- SYNC0 与 LoopCycle -- 应保持一致或为其整数倍
- 自动偏移(推荐) -- 主站自动测量传播延迟并计算
SYNC1 是相对于 SYNC0 的增量时间。例如 SYNC0=1,000,000ns, SYNC1=500,000ns 表示 SYNC1 在每个 SYNC0 后 500us 触发。
setMasterDCCycleTime
public void setMasterDCCycleTime(int timeNs)
设置主站 DC 循环时间(纳秒)。
参数:
timeNs(int) -- DC 循环时间(纳秒)
autoCalculateDCShift
public int autoCalculateDCShift()
自动计算 DC 偏移。基于传播延迟自动计算每个从站的相位偏移值。
返回值:
int-- 计算结果
enableDriftCompensation
public void enableDriftCompensation(boolean enable, int thresholdNs, int gain)
启用或禁用 DC 漂移补偿。漂移补偿在主站侧持续修正系统时钟与 DC 参考时钟之间的偏差,防止长时间运行后同步精度下降。
参数:
enable(boolean) --true启用,false禁用thresholdNs(int) -- 触发补偿的偏差阈值(纳秒),偏差低于此值时不做修正gain(int) -- 补偿增益,控制修正速率(值越大修正越快但可能引入振荡)
示例:
// 使用推荐参数启用漂移补偿
master.enableDriftCompensation(true, 1000, 512);
// 自定义参数:500ns 阈值,较低增益(更平滑的修正)
master.enableDriftCompensation(true, 500, 256);
// 禁用漂移补偿
master.enableDriftCompensation(false, 0, 0);
对于长时间运行的系统(>24小时),建议启用漂移补偿。默认参数适合大多数场景,仅在需要更精细控制时调整阈值和增益。
enableContinuousMeasurement
public void enableContinuousMeasurement(boolean enable, int intervalSec)
启用或禁用持续传播延迟测量(ETG.1500 5.13.2)。启用后主站定期重新测量传播延迟,适用于温度漂移等导致延迟变化的场景。
参数:
enable(boolean) --true启用,false禁用intervalSec(int) -- 测量间隔(秒),0 表示使用默认间隔
示例:
master.enableContinuousMeasurement(true, 60); // 每 60 秒重新测量
master.enableContinuousMeasurement(false, 0); // 禁用
默认情况下 DC 偏移在 configureDCAll() 时一次性计算。仅在长时间运行且环境温度变化较大时启用此功能。
同步窗口监控
主站每秒自动检查各 DC 从站的时间偏差。当从站偏差超出 SyncWindowThreshold 阈值时触发 DCSyncLost 事件。
// 阈值:默认 1000ns,可调整
master.Diagnostics().setSyncWindowThreshold(500); // 设为 500ns
// 事件:从站从"同步"变为"失同步"时触发一次
master.Events().addDCSyncLostListener((masterIdx, slaveIdx, diffNs) ->
System.out.println("从站 " + slaveIdx + " DC 同步丢失: 偏差 " + diffNs + "ns"));
MaxSyncDifference
public int MaxSyncDifference()
获取所有 DC 从站中的最大时间偏差(纳秒)。
返回值:
int-- 最大时间偏差(纳秒),失败返回 -1
示例:
int maxDiff = master.MaxSyncDifference();
System.out.println("最大同步偏差: " + maxDiff + "ns");
isAllSlavesInSync
public boolean isAllSlavesInSync()
检查所有 DC 从站是否都在同步窗口内(偏差 <= SyncWindowThreshold)。
返回值:
boolean-- 所有从站同步返回true
示例:
if (!master.isAllSlavesInSync()) {
System.out.println("存在从站同步偏差过大");
}
resetAllSyncWindowStats
public void resetAllSyncWindowStats()
重置所有从站的同步窗口统计(最大/最小时间差、超出同步次数等)。
单个从站的同步窗口详细状态请参见 从站 DC 同步。
MaxPropagationDelay
public int MaxPropagationDelay()
获取最大传播延迟(纳秒)。
DC 时间查询
用于读取总线当前的 DC 系统时间和参考时钟从站索引。主站每次 PDO 周期通过 FRMW 从参考时钟从站读回 DC 时间,本 API 返回最近一次的缓存值。
getMasterDCTime
public long getMasterDCTime()
获取主站最近一次 PDO 周期取回的 64 位 DC 系统时间。单位纳秒,以 2000-01-01 00:00:00 UTC 为纪元(ETG 规范定义)。
返回值:
long— DC 时间(纳秒)。0表示 DC 未激活或无 DC 从站
示例:
long dcNs = master.getMasterDCTime();
if (dcNs == 0) {
System.out.println("DC 未激活");
} else {
// 2000-01-01 到 1970-01-01 = 946_684_800 秒
long epochMs = dcNs / 1_000_000L + 946_684_800_000L;
System.out.println("DC 时间: " + new java.util.Date(epochMs));
}
getReferenceClockSlaveIndex
public int getReferenceClockSlaveIndex()
获取当前参考时钟从站索引(1-based)。参考时钟是 DC 网络中第一个支持 DC 的从站,所有其他 DC 从站的时间相对它同步。
返回值:
int— 参考时钟从站索引(1-based);0表示总线上无 DC 能力从站
示例:
int refIdx = master.getReferenceClockSlaveIndex();
if (refIdx > 0) {
System.out.printf("参考时钟从站: Slave[%d]%n", refIdx);
} else {
System.out.println("总线上没有 DC 能力从站");
}
Java 的 getMasterDCTime() / getReferenceClockSlaveIndex() 对应 C# 的 DC.MasterDCTimeNs / DC.ReferenceClockSlaveIndex 属性,语义一致,仅 Java 以 getter 方法形式暴露。
DC 自动偏移
master.setDCAutoShiftEnabled(true);
boolean enabled = master.getDCAutoShiftEnabled();
启用后,主站在 DC 配置时自动计算最优偏移值。
完整示例
125us 高性能(WDK 驱动)
try (EtherCATMaster master = EtherCATMaster.create()) {
master.SetNetwork("\\Device\\NPF_{...}");
// 1. 配置周期 -- 125us(WDK 驱动推荐值)
master.Config().LoopCycle(125_000);
// 2. 切换到 SafeOp
master.setState(EcState.SAFE_OP);
// 3. 配置 DC(自动偏移)-- SYNC0 与 LoopCycle 保持一致
master.configureDCAll(125_000, 0);
Thread.sleep(1000);
// 4. 切换到 Op
master.setState(EcState.OP);
master.Start();
// 监听 DC 同步丢失事件
master.Events().addDCSyncLostListener((masterIdx, slaveIdx, diffNs) ->
System.out.println("从站 " + slaveIdx + " DC 同步丢失: 偏差 " + diffNs + "ns"));
}
持续测量与同步监控
// 长时间运行:启用持续传播延迟测量(温度漂移补偿)
master.enableContinuousMeasurement(true, 60);
// 漂移补偿
master.enableDriftCompensation(true, 500, 256);
// 同步窗口监控
if (!master.isAllSlavesInSync()) {
int maxDiff = master.MaxSyncDifference();
System.out.println("同步偏差过大: " + maxDiff + "ns");
}
// 重置统计
master.resetAllSyncWindowStats();