冗余 (Redundancy)
EtherCAT 冗余通过双网卡 + 环形拓扑实现链路级容错: 主网口走 primary 帧, 副网口走 secondary 帧, 任一段断线时 SDK 自动从两侧 WKC 合并完成的从站状态, 整个网络仍正常运行.
通过 master.GetDiagnostics() 访问冗余状态; 启用冗余通过初始化时指定双网口完成。
启用方式
冗余在 初始化阶段 通过 SetNetwork(primary, redundant) 指定双网口启用, 不需要单独的开关 API。运行时无需手动控制。冗余管理函数位于 darra::ethercat::master_redundancy 命名空间, 提供 EnableRedundancy / DisableRedundancy / GetRedundancyStatus / IsRedundancyActive / ForceFailover / CheckRedundancyHealth / GetBreakPoints。
相关页面
- 冗余诊断 /
RingMode/BreakPoint详见 主站诊断 - 冗余状态 - 冗余链路状态变化事件:
RedundancyModeChanged - 网口扫描自动识别冗余对:
darra::ethercat::statics::get_network_info()
RedundancyState
enum class RedundancyState : int {
None = 0, // 无冗余
Primary = 1, // 仅使用主网络
Secondary = 2, // 仅使用备用网络
Both = 3 // 使用双网络 (活动冗余)
};
RedundancyStatus
冗余运行时状态详细信息。
struct RedundancyStatus {
RedundancyState state; // 冗余总体状态
bool primaryLinkUp; // 主链路是否在线
bool secondaryLinkUp; // 副链路是否在线
uint32_t primaryTxFrames; // 主网口发送帧数
uint32_t primaryRxFrames; // 主网口接收帧数
uint32_t secondaryTxFrames; // 副网口发送帧数
uint32_t secondaryRxFrames; // 副网口接收帧数
uint32_t failoverCount; // 故障切换次数
uint32_t lastFailoverTime; // 上次切换时间 (Unix 时间戳)
};
struct RedundancyBreakPoint {
uint16_t slaveIndex; // 断点所在从站索引
uint8_t port; // 断点端口号 (0-3)
};
完整示例
启用冗余 + 健康监控
#include "ethercat.hpp"
#include <chrono>
#include <thread>
using namespace darra::ethercat;
int main() {
// 推荐通过 statics::get_network_info() 自动识别冗余对
auto adapters = statics::get_network_info();
NetworkInfo primary, redundant;
int found = 0;
for (auto& a : adapters) {
if (a.RedundantSlaveNum > 0) {
(found++ == 0 ? primary : redundant) = a;
if (found >= 2) break;
}
}
if (found < 2) return -1;
EtherCATMaster master(dll);
master.SetNetwork(primary, redundant)
.SetEni("C:/config.deni");
// 启用冗余 (Build 前调用)
master_redundancy::EnableRedundancy(master);
master.Build();
// 订阅冗余模式变化
master.Events().RedundancyModeChanged = [](uint16_t mi, int oldM, int newM) {
printf("冗余模式: %d -> %d\n", oldM, newM);
};
master.SetState(EcState::OP);
master.Start();
// 周期性健康检查
auto& diag = master.GetDiagnostics();
while (true) {
auto status = master_redundancy::GetRedundancyStatus(master);
if (status) {
printf("冗余: ring_mode=%d active=%d primary=%d secondary=%d failover=%u\n",
static_cast<int>(diag.RingMode()),
master_redundancy::IsRedundancyActive(master),
status->primaryLinkUp, status->secondaryLinkUp,
status->failoverCount);
}
auto bps = master_redundancy::GetBreakPoints(master);
for (auto& bp : bps) {
printf("故障点: 从站[%u] 端口=%u\n", bp.slaveIndex, bp.port);
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
参考
- ETG.1500 §5.7 Cable Redundancy
- 其他语言 SDK 对齐: C#
EnableRedundancy/ JavaenableRedundancy/ Pythonenable_redundancy/ Rustenable_redundancy