冗余 (Redundancy)
EtherCAT 冗余通过双网卡 + 环形拓扑实现链路级容错: 主网口走 primary 帧, 副网口走 secondary 帧, 任一段断线时 SDK 自动从两侧 WKC 合并完成的从站状态, 整个网络仍正常运行.
通过 master.Diagnostics 访问冗余状态; 启用冗余通过初始化时指定双网口完成。
启用方式
冗余在 初始化阶段 通过 SetNetwork(primary, redundant) 指定双网口启用, 不需要单独的开关 API。运行时无需手动控制。
相关页面
- 冗余诊断 /
RingMode/BreakPoint详见 主站诊断 - 冗余状态 - 冗余链路状态变化事件:
RedundancyModeChanged - 网口扫描自动识别冗余对:
GetNetworkInfo
冗余状态查询 API
冗余运行时状态通过 master.Diagnostics(类型 MasterDiagnosticsInfo)的公开属性查询,无需单独的冗余状态对象。常用属性:
| 属性 | 类型 | 说明 |
|---|---|---|
| RedundancyActive | bool | 冗余是否激活(存在断线但网络仍正常运行) |
| RingMode | RingMode | 环拓扑冗余运行模式(Inactive / Dual / Degraded) |
| PrimaryPortOk | bool | 主端口是否正常 |
| SecondaryPortOk | bool | 副端口是否正常(无冗余时始终 false) |
| PrimaryPortErrors | uint | 主端口最近 5 秒错误数 |
| SecondaryPortErrors | uint | 副端口最近 5 秒错误数 |
| BreakPoint | BreakPointInfo? | 断线 / CRC 故障点定位 |
完整的诊断属性表与 RingMode / BreakPointInfo 枚举/结构定义见 主站诊断 - 冗余状态。
冗余 WKC 读取 (合并 WKC)
合并 WKC 是权威值, 别拿主口单口 WKC 判故障
环形冗余下, 主帧 (primary) 从 P0 入网走 ring + branch, 副帧 (secondary) 从 P1 入网仅走 ring。某段断开时, 一侧帧只能看到断点之前的从站, 另一侧从反方向补齐 —— SDK 把两侧 WKC 合并, 得到本周期真正完成 PDO 交换的从站数。
铁律: 合并 WKC == 期望 WKC, 即网络完好; 此时主口单口 WKC 可以 < 期望, 不是故障。 切勿用 PrimaryWKC 单口值去比 ExpectedWKC 判掉站 —— 在断点被冗余补偿的场景下这必然误报。
| 类别 | 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|---|
| 合并 WKC (权威) | WKC | ushort | 只读 | 主+副两侧合并后本周期实际完成交换的从站数 |
| 期望 WKC | ExpectedWKC | ushort | 只读 | 配置期/进 OP 时确定的固定真值, 永不下调迁就劣化总线 |
| 主口单口 | PrimaryWKC | ushort | 只读 | 主口实测 WKC (冗余模式独立跟踪); 断点被补偿时可 < ExpectedWKC, 属正常 |
| 副口单口 | SecondaryWKC | ushort | 只读 | 副口实测 WKC (冗余模式独立跟踪); 单网卡模式恒为 0 |
| 主口单口 (RT) | PrimaryWkcRt | ushort | 只读 | 主口 RT 路径直读实测 WKC (内核已滤波, 延迟更低) |
| 副口单口 (RT) | SecondaryWkcRt | ushort | 只读 | 副口 RT 路径直读实测 WKC (内核已滤波, 延迟更低) |
| 主口期望 | PrimaryExpectedWKC | ushort | 只读 | 主发帧期望 WKC = ring + branch (主口拓扑完好真值); 单口/拓扑未识别时为 0 |
| 副口期望 | SecondaryExpectedWKC | ushort | 只读 | 副发帧期望 WKC = ring (副口拓扑完好真值); 单口/拓扑未识别时为 0 |
| 冗余激活 | RedundancyActive | bool | 只读 | 冗余是否激活 (双端口均有流量, 即存在被补偿的断点) |
判健康的正确写法 — 以合并 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);
}