冗余 (Redundancy)
EtherCAT 冗余通过双网卡 + 环形拓扑实现链路级容错: 主网口走 primary 帧, 副网口走 secondary 帧, 任一段断线时 SDK 自动从两侧 WKC 合并完成的从站状态, 整个网络仍正常运行.
通过 master 直接调用启用 / 强制故障转移, 通过 master.Diagnostics() 查看冗余诊断.
相关页面
- 冗余诊断 /
RingMode/BreakPoint详见 主站诊断 - 冗余状态 - 冗余链路状态变化事件:
addRedundancyModeChangedListener
启用与状态
| 方法 | 返回类型 | 说明 |
|---|---|---|
| enableRedundancy(boolean) | boolean | 启用 / 禁用冗余 (需在 Start() 之前调用) |
| forceRedundancyFailover() | boolean | 强制冗余故障切换 (调试 / 维护用) |
| checkRedundancyHealth() | boolean | 检查冗余健康状态 |
| RingMode() | int | 环拓扑冗余运行模式原始值 (0=Inactive, 1=Dual, 2=Degraded),可用 EtherCATTypes.RingMode.fromValue(...) 转为枚举 |
| SecondaryLinkStatus() | boolean | 副网口链路是否正常 |
| setRedProcessdata(int mode) | void | 设置冗余处理模式 |
| RedProcessdata() | int | 获取当前冗余处理模式 |
enableRedundancy(boolean)
public boolean enableRedundancy(boolean enable)
启用 / 禁用冗余. 必须在 Start() 之前调用, 且构造主站时已经通过
SetNetwork(primary, secondary) 指定副网卡.
forceRedundancyFailover()
public boolean forceRedundancyFailover()
强制把当前发送路径切到副网口, 调试或预防性维护时使用.
checkRedundancyHealth()
public boolean checkRedundancyHealth()
检查冗余健康状态.
RingMode()
public int RingMode()
获取环拓扑冗余运行模式原始值。返回 int(0 / 1 / 2),可用 EtherCATTypes.RingMode 枚举转换为强类型:
int raw = master.RingMode();
EtherCATTypes.RingMode mode = EtherCATTypes.RingMode.fromValue(raw); // INACTIVE / DUAL / DEGRADED
EtherCATTypes.RingMode 枚举:
public enum RingMode {
INACTIVE(0), // 未激活: 冗余监控未初始化
DUAL(1), // 双向冗余: 两端发送 LRW
DEGRADED(2); // 降级模式: 仅 primary 工作
}
SecondaryLinkStatus()
public boolean SecondaryLinkStatus()
副网口链路是否正常.
setRedProcessdata(int mode) / RedProcessdata()
public void setRedProcessdata(int mode)
public int RedProcessdata()
设置 / 获取冗余处理模式.
冗余 WKC 读取 (合并 WKC)
合并 WKC 是权威值, 别拿主口单口 WKC 判故障
环形冗余下, 主帧 (primary) 从 P0 入网走 ring + branch, 副帧 (secondary) 从 P1 入网仅走 ring。某段断开时一侧帧只能看到断点之前的从站, 另一侧从反方向补齐 —— SDK 把两侧 WKC 合并, 得到本周期真正完成 PDO 交换的从站数。
铁律: 合并 WKC == 期望 WKC, 即网络完好; 此时单口 WKC 可以 < 期望, 不是故障。
Java SDK 暴露的是合并后的 WKC —— master.WKC() 已是主+副合并的权威实测值, 直接用它对比 master.ExpectedWKC() 即可判整体健康, 无需 (也无单独的高级方法) 去读主/副单口 WKC。
| 类别 | 方法 | 返回类型 | 读写 | 说明 |
|---|---|---|---|---|
| 合并 WKC (权威) | WKC() | short | 只读 | 主+副合并后本周期真正完成交换的从站数 |
| 期望 WKC | ExpectedWKC() | short | 只读 | 拓扑固定真值, 永不下调迁就劣化总线 |
| 冗余激活 | Diagnostics().isRedundancyActive() | boolean | 只读 | 双端口均有流量 (即存在被补偿的断点) |
判健康的正确写法 — 以合并 WKC 为准:
// ✅ 正确: 合并 WKC == 期望 WKC, 网络完好 (即使有断点被冗余补偿)
boolean linkHealthy = master.WKC() == master.ExpectedWKC();
if (linkHealthy && master.Diagnostics().isRedundancyActive()) {
System.out.println("有断点, 但冗余已补齐, 网络仍完整 (合并 WKC=" + master.WKC() + ")");
} else if (!linkHealthy) {
System.out.printf("真有从站掉了: 合并 WKC=%d < 期望=%d%n",
master.WKC(), master.ExpectedWKC());
}
完整示例
启用冗余 + 健康监控
try (EtherCATMaster master = EtherCATMaster.create()) {
master.SetNetwork("\\Device\\NPF_{primary-guid}", "\\Device\\NPF_{secondary-guid}");
// 启用冗余 (Start 前调用)
master.enableRedundancy(true);
// 订阅冗余模式变化
master.Events().addRedundancyModeChangedListener((mi, oldMode, newMode) -> {
System.out.printf("冗余模式: %s -> %s%n", oldMode, newMode);
});
master.setState(EcState.OP);
master.Start();
// 周期性健康检查
while (true) {
boolean healthy = master.checkRedundancyHealth();
int mode = master.RingMode();
boolean secOk = master.SecondaryLinkStatus();
System.out.printf("冗余: healthy=%b ring_mode=%d secondary_link=%b%n",
healthy, mode, secOk);
Thread.sleep(1000);
}
}
故障转移演练
// 模拟主网口故障, 强制切到副网口
master.forceRedundancyFailover();
Thread.sleep(500);
// 检查副链路是否承载主路
assert master.SecondaryLinkStatus();
assert master.State() == EcState.OP;
参考
- ETG.1500 §5.7 Cable Redundancy
- 其他语言 SDK 对齐: C#
EnableRedundancy/ Pythonenable_redundancy/ C++EnableRedundancy/ Rustenable_redundancy