跳到主要内容

冗余 (Redundancy)

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

通过 master 直接调用启用 / 强制故障转移, 通过 master.diagnostics 查看冗余诊断。

启用方式

冗余在初始化阶段通过 set_network(adapter, redundant_adapter) 指定副网卡, 再调用 enable_redundancy(True) 启用 (必须在 start() 之前)。运行时无需手动控制。

相关页面

RedundancyState

from enum import IntEnum

class RedundancyState(IntEnum):
NONE = 0 # 无冗余
PRIMARY = 1 # 仅使用主网络
SECONDARY = 2 # 仅使用备用网络
BOTH = 3 # 使用双网络 (活动冗余)

RedundancyStatusInfo

冗余运行时状态详细信息。

@dataclass
class RedundancyStatusInfo:
state: RedundancyState # 冗余总体状态
primary_link_up: bool # 主链路是否在线
secondary_link_up: bool # 副链路是否在线
primary_tx_frames: int # 主网口发送帧数
primary_rx_frames: int # 主网口接收帧数
secondary_tx_frames: int # 副网口发送帧数
secondary_rx_frames: int # 副网口接收帧数
failover_count: int # 故障切换次数
last_failover_time: float # 上次切换时间 (Unix 时间戳)

主站层暴露的冗余 API: enable_redundancy(bool) / force_failover() / check_redundancy_health() / set_redundancy_mode(mode), 以及只读属性 ring_mode / secondary_link_ok / redundancy_mode / redundancy_statusRedundancyManager(master._dll, master.master_index) 类对上述接口做便捷封装, 通过 mgr.get_status() -> RedundancyStatus (别名 RedundancyStatusInfo) 一次性获取冗余快照。

冗余 WKC 读取 (合并 WKC)

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

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

铁律: 合并 WKC == 期望 WKC, 即网络完好; 此时单口 WKC 可以 < 期望, 不是故障。

Python SDK 通过 master.diagnostics_info (类型 MasterDiagnosticsInfo) 的只读属性读取合并后的 WKC, 这些镜像由内核每周期维护, 薄读零帧:

类别属性类型读写说明
合并 WKC (权威)diag.wkc_actual_mirrorint只读主+副合并后本周期真正完成交换的从站数
期望 WKCdiag.wkc_expected_mirrorint只读拓扑固定真值, 永不下调迁就劣化总线
缺额diag.wc_deficitint只读期望 - 合并实测, >0 才表示真有从站掉了
冗余激活diag.redundancy_activebool只读双端口均有流量 (即存在被补偿的断点)

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

diag = master.diagnostics_info

# ✅ 正确: 合并 WKC == 期望 WKC, 网络完好 (即使有断点被冗余补偿)
link_healthy = diag.wkc_actual_mirror == diag.wkc_expected_mirror

if link_healthy and diag.redundancy_active:
print(f"有断点, 但冗余已补齐, 网络仍完整 (合并 WKC={diag.wkc_actual_mirror})")
elif not link_healthy:
print(f"真有从站掉了: 合并 WKC={diag.wkc_actual_mirror} "
f"< 期望={diag.wkc_expected_mirror} (缺额={diag.wc_deficit})")

完整示例

启用冗余 + 健康监控

import time
from darra_ethercat import EtherCATMaster, EcState

with EtherCATMaster() as master:
# 同时指定主/副网卡 (推荐通过 get_network_info() 自动识别冗余对)
master.set_network(
r"\Device\NPF_{primary-guid}",
r"\Device\NPF_{secondary-guid}",
)

# 启用冗余 (start 前调用)
master.enable_redundancy(True)

master.set_state(EcState.OP)
master.start()

# 订阅冗余模式变化
master.on_redundancy_mode_changed(
lambda mi, old, new: print(f"冗余模式: {old} -> {new}")
)

# 周期性健康检查 — 通过诊断模块查看冗余状态
diag = master.diagnostics_info
while True:
print(f"冗余: ring_mode={master.ring_mode}, "
f"active={diag.redundancy_active}, "
f"primary_ok={diag.primary_port_ok}, "
f"secondary_ok={diag.secondary_port_ok}")
if diag.break_point is not None:
print(f"故障点: {diag.break_point}")
time.sleep(1)
参考

ETG.1500 §5.7 Cable Redundancy