跳到主要内容

冗余 (Redundancy)

EtherCAT 冗余通过双网卡 + 环形拓扑实现链路级容错: 主网口走 primary 帧, 副网口走 secondary 帧, 任一段断线时 SDK 自动从两侧 WKC 合并完成的从站状态, 整个网络仍正常运行.

通过 master.Diagnostics 访问冗余状态; 启用冗余通过初始化时指定双网口完成。

启用方式

冗余在 初始化阶段 通过 SetNetwork(primary, redundant) 指定双网口启用, 不需要单独的开关 API。运行时无需手动控制。

相关页面

冗余状态查询 API

冗余运行时状态通过 master.Diagnostics(类型 MasterDiagnosticsInfo)的公开属性查询,无需单独的冗余状态对象。常用属性:

属性类型说明
RedundancyActivebool冗余是否激活(存在断线但网络仍正常运行)
RingModeRingMode环拓扑冗余运行模式(Inactive / Dual / Degraded)
PrimaryPortOkbool主端口是否正常
SecondaryPortOkbool副端口是否正常(无冗余时始终 false
PrimaryPortErrorsuint主端口最近 5 秒错误数
SecondaryPortErrorsuint副端口最近 5 秒错误数
BreakPointBreakPointInfo?断线 / CRC 故障点定位

完整的诊断属性表与 RingMode / BreakPointInfo 枚举/结构定义见 主站诊断 - 冗余状态

冗余 WKC 读取 (合并 WKC)

合并 WKC 是权威值, 别拿主口单口 WKC 判故障

环形冗余下, 主帧 (primary) 从 P0 入网走 ring + branch, 副帧 (secondary) 从 P1 入网仅走 ring。某段断开时, 一侧帧只能看到断点之前的从站, 另一侧从反方向补齐 —— SDK 把两侧 WKC 合并, 得到本周期真正完成 PDO 交换的从站数。

铁律: 合并 WKC == 期望 WKC, 即网络完好; 此时主口单口 WKC 可以 < 期望, 不是故障。 切勿用 PrimaryWKC 单口值去比 ExpectedWKC 判掉站 —— 在断点被冗余补偿的场景下这必然误报。

类别属性类型读写说明
合并 WKC (权威)WKCushort只读主+副两侧合并后本周期实际完成交换的从站数
期望 WKCExpectedWKCushort只读配置期/进 OP 时确定的固定真值, 永不下调迁就劣化总线
主口单口PrimaryWKCushort只读主口实测 WKC (冗余模式独立跟踪); 断点被补偿时可 < ExpectedWKC, 属正常
副口单口SecondaryWKCushort只读副口实测 WKC (冗余模式独立跟踪); 单网卡模式恒为 0
主口单口 (RT)PrimaryWkcRtushort只读主口 RT 路径直读实测 WKC (内核已滤波, 延迟更低)
副口单口 (RT)SecondaryWkcRtushort只读副口 RT 路径直读实测 WKC (内核已滤波, 延迟更低)
主口期望PrimaryExpectedWKCushort只读主发帧期望 WKC = ring + branch (主口拓扑完好真值); 单口/拓扑未识别时为 0
副口期望SecondaryExpectedWKCushort只读副发帧期望 WKC = ring (副口拓扑完好真值); 单口/拓扑未识别时为 0
冗余激活RedundancyActivebool只读冗余是否激活 (双端口均有流量, 即存在被补偿的断点)

判健康的正确写法 — 以合并 WKC 为准:

var diag = master.Diagnostics;

// ✅ 正确: 合并 WKC == 期望 WKC, 网络完好 (即使有断点被冗余补偿)
bool linkHealthy = diag.WKC == diag.ExpectedWKC;

if (linkHealthy && diag.RedundancyActive)
Console.WriteLine("有断点, 但冗余已补齐, 网络仍完整 (合并 WKC 达期望)");
else if (!linkHealthy)
Console.WriteLine($"真有从站掉了: 合并 WKC={diag.WKC} < 期望={diag.ExpectedWKC}");

// 诊断断点位置时再看主/副单口 (不要拿单口去判整体健康)
Console.WriteLine($"主口单口 WKC={diag.PrimaryWKC} (期望主路={diag.PrimaryExpectedWKC}), " +
$"副口单口 WKC={diag.SecondaryWKC} (期望副路={diag.SecondaryExpectedWKC})");

完整示例

启用冗余 + 健康监控

// 通过双网口启用冗余 (推荐通过 GetNetworkInfo 自动识别冗余对)
var adapters = DarraEtherCAT.GetNetworkInfo();
var pair = adapters.Where(a => a.RedundantSlaveNum > 0).Take(2).ToList();
if (pair.Count < 2) return;

var master = new DarraEtherCAT()
.SetNetwork(pair[0], pair[1])
.SetENI(@"C:\config.xml")
.Build();
if (master == null) return;

// 订阅冗余模式变化 (回调签名: ushort masterIndex, int oldMode, int newMode)
master.Events.RedundancyModeChanged += (masterIndex, oldMode, newMode) =>
{
Console.WriteLine($"冗余模式: {oldMode} -> {newMode}");
};

master.SetState(EcState.OP);

// 周期性健康检查 — 通过诊断模块查看冗余状态
var diag = master.Diagnostics;
while (true)
{
Console.WriteLine($"冗余: ring_mode={diag.RingMode}, " +
$"active={diag.RedundancyActive}, " +
$"primary_ok={diag.PrimaryPortOk}, secondary_ok={diag.SecondaryPortOk}");
if (diag.BreakPoint != null)
Console.WriteLine($"故障点: {diag.BreakPoint}");
Thread.Sleep(1000);
}