跳到主要内容

DC 配置

什么是 DC?

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

DC 对设备的好处
  • 多轴同步运动 — 所有伺服驱动器在同一时刻更新位置指令,消除轴间抖动,轨迹插补更平滑
  • IO 同步采样 — 所有输入输出在同一时刻,主站读取时数据一致,适合高速控制和测量
  • 精确 I/O 时间戳 — 输入数据带有硬件时间戳,主站可精确知道采样发生的物理时刻
  • 确定性输出 — 输出在固定时刻生效,不受 EtherCAT 帧到达时间的抖动影响,降低系统延迟和不确定性

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

相关页面

属性

类别属性类型访问说明
DC 状态HasDCbool只读网络中是否有支持 DC 的从站

方法

ConfigureDC(uint sync0CycleNs, uint sync1CycleNs = 0, int? shiftNs = null)

public void ConfigureDC(uint sync0CycleNs, uint sync1CycleNs = 0, int? shiftNs = null)

为所有 DC 从站配置 DC 同步。所有参数单位:纳秒(ns)。自动完成传播延迟测量、偏移计算和 DC 参数写入。

参数:

  • sync0CycleNs (uint) — SYNC0 周期(纳秒),0 表示禁用 DC
  • sync1CycleNs (uint) — SYNC1 增量时间(纳秒),0 表示仅 SYNC0
  • shiftNs (int?) — 相位偏移(纳秒):null=自动计算(默认),0=不设置偏移,其他值=手动偏移(所有从站使用相同值)

示例:

master.ConfigureDC(1_000_000);              // SYNC0 = 1ms
master.ConfigureDC(1_000_000, shiftNs: 0); // SYNC0 = 1ms, 不设置偏移
master.ConfigureDC(1_000_000, 500_000); // SYNC0 = 1ms, SYNC1 = 500µs
推荐配置

125μs 高性能配置(WDK 驱动推荐):

master.Config.LoopCycle = 125_000;    // PDO 交换周期 125μs
master.ConfigureDC(125_000); // SYNC0 = 125μs,自动计算偏移

1ms 常规配置(通用场景):

master.Config.LoopCycle = 1_000_000;  // PDO 交换周期 1ms
master.ConfigureDC(1_000_000); // SYNC0 = 1ms,自动计算偏移
  • SYNC0 与 LoopCycle — 应保持一致或为其整数倍,数据未到达的同步没有意义
  • 自动偏移(推荐) — shiftNs 不传 / null,主站自动测量传播延迟并计算
  • 手动偏移 — 也可设置一个较高的固定值,如 0.8 × sync0CycleNs
  • 过采样例外 — Oversampling 设备中 SYNC0 < LoopCycle,需设备硬件和 PDO 映射专门支持
关于 SYNC1

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

与从站级配置的区别
  • master.ConfigureDC() — 一次性配置所有 DC 从站
  • slave.ConfigureDC() — 配置单个从站

两者都默认自动计算偏移。仅在需要对个别从站设置不同参数时使用从站级方法。

Master.ConfigureDC(DcSyncMode mode, uint sync0CycleNs = 0, uint sync1CycleNs = 0, int? shiftNs = null)

public void ConfigureDC(DcSyncMode mode, uint sync0CycleNs = 0, uint sync1CycleNs = 0, int? shiftNs = null)

主站级重载: 根据同步模式为所有 DC 从站配置 DC(ETG.1020)。自动配置各从站的同步类型。从站级单独配置使用 slave.ConfigureDC

参数:

  • mode (DcSyncMode) — DC 同步模式
  • sync0CycleNs (uint) — SYNC0 周期(纳秒),仅 DcSynchron 模式使用
  • sync1CycleNs (uint) — SYNC1 周期(纳秒),仅 DcSynchron 模式使用
  • shiftNs (int?) — 相位偏移(纳秒),仅 DcSynchron 模式使用

示例:

master.ConfigureDC(DcSyncMode.DcSynchron, 1_000_000);  // 所有 DC 从站 SYNC0 = 1ms
master.ConfigureDC(DcSyncMode.SmSynchron); // 所有 DC 从站 SM 同步模式
master.ConfigureDC(DcSyncMode.FreeRun); // 禁用所有 DC 从站的 DC 同步

EnableContinuousMeasurement(bool enable, uint intervalSec = 0)

public void EnableContinuousMeasurement(bool enable, uint intervalSec = 0)

启用或禁用持续传播延迟测量(ETG.1500 5.13.2)。启用后主站定期重新测量传播延迟,适用于温度漂移等导致延迟变化的场景。

参数:

  • enable (bool) — true 启用,false 禁用
  • intervalSec (uint) — 测量间隔(秒),0 表示使用默认间隔

示例:

master.EnableContinuousMeasurement(true, 60);  // 每 60 秒重新测量
master.EnableContinuousMeasurement(false); // 禁用
备注

默认情况下 DC 偏移在 ConfigureDC() 时一次性计算。仅在长时间运行且环境温度变化较大时启用此功能。

同步窗口监控

主站每秒自动检查各 DC 从站的时间偏差。当从站偏差超出 SyncWindowThreshold 阈值时触发 DCSyncLost 事件。

// 阈值:默认 1000ns,可调整
master.Diagnostics.SyncWindowThreshold = 500; // 设为 500ns

// 事件:从站从"同步"变为"失同步"时触发一次(不重复触发)
master.Events.DCSyncLost += (masterIdx, slaveIdx, diffNs) =>
Console.WriteLine($"从站 {slaveIdx} DC 同步丢失: 偏差 {diffNs}ns");

GetMaxSyncDifference()

public int GetMaxSyncDifference()

获取所有 DC 从站中的最大时间偏差(纳秒)。

返回值:

  • int — 最大时间偏差(纳秒),失败返回 -1

示例:

int maxDiff = master.GetMaxSyncDifference();
Console.WriteLine($"最大同步偏差: {maxDiff}ns");

IsAllSlavesInSync()

public bool IsAllSlavesInSync()

检查所有 DC 从站是否都在同步窗口内(偏差 ≤ SyncWindowThreshold)。

返回值:

  • bool — 所有从站同步返回 true

示例:

if (!master.IsAllSlavesInSync())
Console.WriteLine("存在从站同步偏差过大");

ResetAllSyncWindowStats()

public void ResetAllSyncWindowStats()

重置所有从站的同步窗口统计(最大/最小时间差、超出同步次数等)。

示例:

master.ResetAllSyncWindowStats();
单个从站

单个从站的同步窗口详细状态请使用 slave.GetSyncWindowStatus(),包含 DiffNs、MaxDiffNs、MinDiffNs、InSync、OutOfSyncCount。

完整示例

125μs 高性能(WDK 驱动)

var master = new DarraEtherCAT()
.SetENI(@"C:\config.xml");

var (success, message) = master.Build();
if (!success) return;

// 1. 配置周期 — 125μs(WDK 驱动推荐值)
master.Config.LoopCycle = 125_000;

// 2. 切换到 SafeOp
master.SetState(EcState.SafeOp);

// 3. 配置 DC(自动偏移)— SYNC0 与 LoopCycle 保持一致
if (master.HasDC)
{
master.ConfigureDC(125_000);
}

Thread.Sleep(1000);

// 4. 切换到 Op
master.SetState(EcState.OP);

// 监听 DC 同步丢失事件
master.Events.DCSyncLost += (masterIdx, slaveIdx, diffNs) =>
Console.WriteLine($"从站 {slaveIdx} DC 同步丢失: 偏差 {diffNs}ns");

持续测量与同步监控

// 长时间运行:启用持续传播延迟测量(温度漂移补偿)
master.EnableContinuousMeasurement(true, 60);

// 同步窗口监控
if (!master.IsAllSlavesInSync())
{
int maxDiff = master.GetMaxSyncDifference();
Console.WriteLine($"同步偏差过大: {maxDiff}ns");
}

// 重置统计
master.ResetAllSyncWindowStats();
SM 同步类型配置

SM 同步类型通过从站级 slave.ConfigureDC(DcSyncMode mode, ...) 方法自动配置,无需手动调用。详见 从站 DC 同步

DC 漂移补偿

EnableDriftCompensation(bool enable, int thresholdNs = 1000, int gain = 512)

public void EnableDriftCompensation(bool enable, int thresholdNs = 1000, int gain = 512)

启用或禁用 DC 漂移补偿。漂移补偿在主站侧持续修正系统时钟与 DC 参考时钟之间的偏差,防止长时间运行后同步精度下降。

参数:

  • enable (bool) — true 启用,false 禁用
  • thresholdNs (int) — 触发补偿的偏差阈值(纳秒),偏差低于此值时不做修正,默认 1000ns
  • gain (int) — 补偿增益,控制修正速率(值越大修正越快但可能引入振荡),默认 512

示例:

// 使用默认参数启用漂移补偿
master.EnableDriftCompensation(true);

// 自定义参数:500ns 阈值,较低增益(更平滑的修正)
master.EnableDriftCompensation(true, thresholdNs: 500, gain: 256);

// 禁用漂移补偿
master.EnableDriftCompensation(false);
推荐

对于长时间运行的系统(>24小时),建议启用漂移补偿。默认参数适合大多数场景,仅在需要更精细控制时调整阈值和增益。

CurrentDcSyncMode

CurrentDcSyncMode 是从站级属性,通过 slave.CurrentDcSyncMode 访问。详见 从站 DC 同步

主站当前 DC 时间查询

主站每个 PDO 周期会通过 FRMW (Feed-Read-Multiple-Write) 从参考时钟从站取回 64 位 DC 系统时间。SDK 将该时间戳暴露给应用层, 用于:

  • 日志时间对齐 — 应用层日志可用 DC 时间打戳, 与从站侧事件 (EMCY / Diagnosis History) 时间轴严格对齐
  • 跨站事件关联 — 多从站同时上报事件时, 基于 DC 时间可判断绝对先后
  • 漂移诊断 — 与本机墙上时钟或外部 NTP 做差值, 观察时钟漂移趋势
  • 周期起始对齐 — 需要在特定 DC 时刻触发应用层动作时, 作为基准计算等待时长
DC 时间基准

DC 时间单位为纳秒, 起算点为 2000-01-01 00:00:00 UTC (ETG 规范定义)。与 UNIX 时间戳有 30 年偏移, 换算时注意。

MasterDCTimeNs

public long MasterDCTimeNs { get; }

主站最近一次 PDO 周期从参考时钟从站 FRMW 取回的 64 位 DC 系统时间 (纳秒, 2000-01-01 纪元)。

返回值:

  • long — DC 时间戳 (纳秒); 无 DC 从站或主站未运行时返回 0

ReferenceClockSlaveIndex

public ushort ReferenceClockSlaveIndex { get; }

当前参考时钟从站的索引 (1-based)。由 DLL 在 DC 配置阶段自动选为链路上第一个支持 DC 的从站, 应用无需配置。

返回值:

  • ushort — 从站索引 (1-based); 0 表示网络中无 DC 从站

示例

// 打印当前 DC 时间与参考时钟从站
long dcNs = master.MasterDCTimeNs;
ushort refIdx = master.ReferenceClockSlaveIndex;

if (dcNs == 0 || refIdx == 0)
{
Console.WriteLine("网络中无 DC 从站");
}
else
{
// 转换为可读 UTC 时间 (DC 纪元 2000-01-01)
var dcEpoch = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var utc = dcEpoch.AddTicks(dcNs / 100);
Console.WriteLine(
$"当前主站 DC 时间 = {dcNs} ns ({utc:yyyy-MM-dd HH:mm:ss.fffffff} UTC), " +
$"参考从站 = #{refIdx}");
}

日志时间戳场景:

master.Events.DCSyncLost += (masterIdx, slaveIdx, diffNs) =>
{
long now = master.MasterDCTimeNs;
Console.WriteLine(
$"[DC={now}ns] 从站 {slaveIdx} 同步丢失: 偏差 {diffNs}ns");
};
备注

MasterDCTimeNs 由主站周期线程更新, 应用层读取是近似值, 与当前 CPU 真实时刻可能相差一个 PDO 周期以内。高精度场景可结合 Diagnostics.CycleJitter 评估抖动上限。