跳到主要内容

DC 配置

什么是 DC?​

DC(分布式时钟)是 EtherCAT 的硬件级时间同步机制。它让网络中所有从站共享同一个时间基准,使各从站能在完全相同的时刻执行动作。

DC 对设备的好处
  • 多轴同步运动 -- 所有伺服驱动器在同一时刻更新位置指令,消除轴间抖动
  • IO 同步采样 -- 所有输入输出在同一时刻,主站读取时数据一致
  • 精确 I/O 时间戳 -- 输入数据带有硬件时间戳,主站可精确知道采样发生的物理时刻
  • 确定性输出 -- 输出在固定时刻生效,不受 EtherCAT 帧到达时间的抖动影响

主站级 DC 配置。通过 master 直接调用。

相关页面

方法​

类别方法类型读写说明
DC 配置configureDCAll(int sync0Ns, int sync1Ns)int只写为所有 DC 从站配置 SYNC0/SYNC1,0=成功
setMasterDCCycleTime(int timeNs)void只写设置主站 DC 循环时间(纳秒)
autoCalculateDCShift()int只写自动计算各从站相位偏移
漂移补偿enableDriftCompensation(boolean, int, int)void只写启停漂移补偿(阈值 + 增益)
enableContinuousMeasurement(boolean, int)void只写启停持续传播延迟测量(ETG.1500 5.13.2)
setDCAutoShiftEnabled(boolean) / getDCAutoShiftEnabled()void / boolean读写自动偏移开关
同步窗口MaxSyncDifference()int只读最大时间偏差(纳秒),失败 -1
isAllSlavesInSync()boolean只读所有 SYNC0 DC 从站是否在同步窗口内
resetAllSyncWindowStats()void只写重置同步窗口统计
MaxPropagationDelay()int只读最大传播延迟(纳秒)
时间查询getMasterDCTime()long只读最近一次 PDO 周期取回的 DC 时间(纳秒)
getReferenceClockSlaveIndex()int只读参考时钟从站索引(1-based,0=无)

configureDCAll​

public int configureDCAll(int sync0Ns, int sync1Ns)

为所有 DC 从站配置 DC 同步。所有参数单位:纳秒(ns)。默认自动完成:

  1. 传播延迟测量 -- 读取各端口接收时间并计算延迟
  2. 偏移计算 -- 基于传播延迟自动计算每个从站的相位偏移
  3. DC 应用 -- 写入 SYNC0/SYNC1 周期和起始时间到各从站

参数:

  • sync0Ns (int) -- SYNC0 周期(纳秒),0 表示禁用 DC
  • sync1Ns (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

SYNC1 是相对于 SYNC0 的增量时间。例如 SYNC0=1,000,000ns, SYNC1=500,000ns 表示 SYNC1 在每个 SYNC0 后 500us 触发。

备注

DC 同步模式由用户显式配置。恢复快照后需要 DC 的站应确认已进入 DcSynchron / DcSynchron01。

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()

检查所有已启用 SYNC0 DC 的从站是否都在同步窗口内(偏差 <= SyncWindowThreshold)。全站 FreeRun 不是「DC 已同步」。

返回值:

  • boolean -- 所有 SYNC0 DC 从站在窗口内返回 true;FreeRun 不得解读为已同步

示例:

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 能力从站");
}

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();