跳到主要内容

冗余热备 (双 PLC 热切换)

Darra 冗余热备方案 — 双 Runtime 热切换, 切换时间 <50ms, 和西门子 S7-1500 R/H 同档。


1. 冗余热备概述

1.1 什么是冗余热备

冗余热备 (Redundancy / High Availability) 指现场部署两台功能等同的 PLC 工控机, 同一时刻只有其中一台真正驱动现场设备 (称"主", Primary), 另一台以"影子"方式跟随运行 (称"备", Secondary), 实时接收主机同步过来的变量、状态、工艺对象。当主机发生故障 (掉电 / 网卡失联 / 系统崩溃 / 硬件损坏) 时, 备机能在毫秒级时间内接管 EtherCAT 主站角色, 继续驱动现场设备, 让产线不停机。

与"冷备"(故障后人工切换)、"温备"(备机启动但不同步状态) 不同, 热备的关键指标是:

  • 同步周期: 变量/状态在主备之间每毫秒同步一次
  • 切换时间: 故障发生到备机接管的延迟, 目标 <50ms
  • 切换透明: 现场从站设备无感知, EtherCAT 链路不中断
  • 数据一致: 切换瞬间工艺对象、定时器、计数器、PID 积分项不丢

1.2 应用场景

以下场景对 PLC 停机敏感, 必须使用冗余方案:

行业典型场景停机损失
半导体晶圆光刻/刻蚀/CVD 设备¥50 万 / 小时起, 晶圆报废
汽车总装焊装线 / 涂装线整车厂 ¥200 万 / 小时
医药发酵生物反应釜 / 无菌灌装批次报废, 数千万损失
石化连续生产炼油 / 乙烯装置安全事故风险 + 巨额损失
电力/能源变电站 / 核电辅机电网事故
关键物流机场行李 / 快递分拣大面积延误
数据中心空调精密空调冷水主机服务器宕机连锁反应

一般的工厂自动化 (非连续生产, 可排停机窗口) 不需要冗余, 基础版 Darra PLC 即可满足。


2. Darra 冗余方案总览

2.1 架构总览

图示说明:

  • 工控机 A / B: 独立硬件, 独立 UPS, 各自运行 Darra Runtime
  • 万兆同步链路: 两机各装一块万兆网卡, 专线直连, 不经过交换机, 独立 VLAN
  • EtherCAT 主链路: 主机通过网卡 A1 驱动现场从站环网
  • EtherCAT 备链路: 备机网卡 B1 接入环网另一端 (HSR 冗余端口), 平时静默
  • 心跳: 独立 UDP 包, 100ms 周期, 走同步链路或独立 1G 口

2.2 和 S7-1500 R/H 对比

对比项Darra 冗余S7-1500 RS7-1500 H
同步介质万兆以太网 (10 GbE)标准以太网 (1 GbE)光纤专用同步模块
同步周期1 ms典型 4~8 ms典型 1 ms
切换时间<50 ms<300 ms<50 ms
主站冗余方式MAC 克隆 + AL 状态继承系统级 IP 接管同步模块主备
EtherCAT 支持原生支持 + HSR通过 PN 代理通过 PN 代理
硬件成本 (一对)¥3~5 万¥20 万起¥50 万起
软件授权 (一对/年)¥12,000 起约 ¥8 万约 ¥15 万
IO 冗余支持 (HSR 从站)支持 (PROFINET S2)支持 (PN S2)
开发难度和单机几乎一致需理解系统冗余变量同 R
维护难度可热插拔 / 在线升级可热插拔可热插拔

3. 硬件要求

3.1 工控机

项目推荐规格备注
型号研华 IPC-610L / 研祥 IPC-820商用工控机即可
CPUIntel i7-12700 及以上核数 ≥8, 支持 TSC 不变频
内存DDR4 16 GB 及以上影子运行同样吃内存
系统盘SSD 256 GBNVMe 优先
操作系统Windows 10 IoT LTSC / Windows 11 Pro两机必须同版本
网卡 1板载千兆 (管理)上位机连接
网卡 2Intel i210 / i350 (EtherCAT)独立物理网卡
网卡 3Intel X710-DA2 万兆同步专用, 必须独立
电源工业级冗余电源双路输入

两台工控机型号建议一致 (便于备件), 但非强制 — A/B 机型号不同 (如 A 为 IPC-610, B 为 IPC-820) 只要 CPU 代际相近, 同样可运行冗余, 见 FAQ。

3.2 同步链路

项目规格
线缆屏蔽六类 / 七类万兆双绞线 (CAT6A / CAT7)
长度≤5 m (两机建议并排机柜放置)
模式点对点直连, 不经任何交换机
IP 规划独立网段 (如 192.168.200.0/30), 独立 VLAN
介质铜缆 SFP+ (短距) 或 光模块 (长距 ≤100m)

3.3 UPS

  • 每台工控机 独立 UPS, 两个 UPS 接不同市电回路
  • 单 UPS 容量: 支持 15 分钟以上满载 (给运维人员切换时间)
  • 建议: 施耐德 APC SRT 系列 / 山特 C3KS

3.4 EtherCAT 从站

实现 EtherCAT 主站冗余, 要求从站支持下列任一方式:

  • HSR 冗余端口: 从站具备 IN + OUT + REDUNDANCY 三端口, 环网接线
  • 双接口模型: 从站带两个 EtherCAT 口, 可插入独立冗余环

推荐从站型号:

类别厂商型号说明
冗余终端倍福EL9011 / EL9012HSR 冗余端子, 必备
数字量 IO倍福EL1xxx / EL2xxx标配
伺服驱动汇川SV660N 冗余款双口
伺服驱动松下MINAS A6B支持 HSR
变频器ABBACS880 (FECA-01)支持冗余

3.5 成本估算 (参考 2026 Q2)

项目单价一对成本
工控机 (研华 IPC-610 + i7)¥12,000¥24,000
万兆网卡 Intel X710-DA2¥3,500¥7,000
EtherCAT 网卡 Intel i210¥800¥1,600
UPS (施耐德 APC 3KVA)¥4,500¥9,000
万兆 CAT7 线缆 (3m)¥200¥200
小计 (硬件)约 ¥42,000
Darra 冗余授权 (企业版)¥12,000 / 台 / 年¥24,000 / 年
首年总计约 ¥66,000

对比西门子 S7-1500 R 的一对硬件 ¥20 万起, Darra 方案成本约为其 1/4。


4. 软件配置流程

4.1 入口

在 Darra IDE 里:

  1. 打开工程, 定位项目树根节点
  2. 展开 Runtime 节点
  3. 右键 → 启用冗余热备
  4. 进入 "冗余配置向导"

4.2 向导 6 步

步骤 1: 选择角色

  ( ) 本机为主 (Primary)
( ) 本机为备 (Secondary)
(●) 自动协商 (启动时握手判定)

"自动协商"适合绝大多数场景: 两台机器同时开机, 通过同步链路握手, 根据 MAC 地址数值大小 (或配置优先级) 决定主备。一台宕机后重启, 自动以"备"身份加入。

步骤 2: 对等机 IP + 同步网口

  对等机同步 IP      [ 192.168.200.2 ]
本机同步 IP [ 192.168.200.1 ]
同步网口 [ Intel X710-DA2 #1 ▼ ]
心跳端口 (UDP) [ 7788 ]
状态同步端口 (TCP) [ 7789 ]

注意: 同步网口必须选独立的万兆网卡, 不能和 EtherCAT 网卡、管理网卡共用。

步骤 3: 测试心跳与延迟

  [ 测试链路 ] 按钮
────────────────────────────
往返延迟: 0.18 ms √
抖动: 0.03 ms √
丢包率: 0 / 10000 √
带宽: 9.4 Gbps √
────────────────────────────
结果: 链路合格, 可用于 1ms 同步

若往返延迟 >0.5ms 或丢包, 向导会给出建议 (检查网线 / 换网卡口 / 禁用节能)。

步骤 4: 授权激活

冗余功能需要在两台 Runtime 上都有冗余授权 (见第 9 章)。

  本机授权:   √ 有效 (2027-04-16 过期)
对等机授权: √ 有效 (2027-04-16 过期)
授权类型: 企业版 + 冗余模块

若任一台缺少授权, 向导会阻止继续, 提示联系销售购买。

步骤 5: 初始状态同步

备机第一次加入时, 主机会把全量变量表、工艺对象状态、定时器、EtherCAT AL 状态打包发送给备机, 通常耗时 1~3 秒 (千变量项目)。

  正在同步初始状态...
████████████████████ 100%
变量同步完成 (1,247 项)
工艺对象同步完成 (18 项)
EtherCAT 配置同步完成 (32 从站)

步骤 6: 启动冗余运行

  [ 立即进入冗余模式 ]
[ 保存配置, 下次启动再启用 ]

4.3 冗余状态面板

在 IDE 主界面可打开"冗余状态面板" (菜单 → 视图 → 冗余), 实时显示:

  ╔═══════════════════════════════════════════╗
║ 冗余状态监视器 ║
╠═══════════════════════════════════════════╣
║ 本机角色: [主 Primary ●] ║
║ 对等机角色: [备 Secondary ○] ║
║ 同步健康: √ 正常 (RTT 0.21ms) ║
║ 心跳: √ 10/10 ║
║ 同步周期: 1.00 ms ║
║ 同步带宽: 0.9 MB/s ║
║ 丢包 (1 分钟): 0 ║
║ 最后切换: 从未切换 ║
║ 运行时长: 12d 4h 32m ║
╚═══════════════════════════════════════════╝

5. 同步机制详解

5.1 DarraSync-HA 协议帧格式

同步使用私有协议 DarraSync-HA, 承载于 UDP (状态) + TCP (首次全量) 之上。单帧格式:

字段长度说明
Magic4 B固定 DRSH
版本1 B协议版本, 当前 0x01
类型1 B1=心跳 2=增量 3=全量 4=切换通知
Sequence4 B递增序列号
Timestamp8 B发送侧 TSC 计数 (用于延迟测量)
Length2 BPayload 长度
Payload变长差异数据 (见 5.2)
CRC324 B帧完整性校验

5.2 差异同步策略

全量同步仅在初始化和网络重连时使用, 正常运行走差异同步:

  • 变量表维护"脏位"(Dirty Bit), 每次 PLC 扫描结束后, 标记本周期被修改的变量
  • 同步线程每 1ms 收集脏位, 仅打包变化项发送
  • 典型项目 (2000 变量, 5% 变化率) 每帧 payload 约 500 字节

5.3 时钟同步

主备需要统一时间基准, 否则定时器、时间戳类功能块会跳变。Darra 使用两级时钟同步:

  1. TSC 校准: 基于高精度 TSC (Time Stamp Counter), 两机启动时握手交换 TSC 基线, 误差 <1 μs
  2. 周期性漂移补偿: 每 10 秒测量一次时钟漂移, 动态调整备机内部时钟相位

5.4 带宽估算

以下是典型项目的带宽需求:

项目规模变量总数变化率每帧大小1ms 周期带宽
小型 (单机电控柜)5002%~200 B1.6 Mb/s
中型 (整线)2,0005%~500 B4 Mb/s
大型 (整厂多线联动)10,00010%~3 KB24 Mb/s
极端 (仿真测试)50,00020%~30 KB240 Mb/s

10 GbE 同步链路有效负载接近 9.4 Gb/s, 即使极端场景也只消耗 2.5% 带宽, 裕量充足。


6. 切换流程

6.1 正常运行态

备机此时:

  • 接收 DarraSync 帧, 把状态写入影子变量表
  • 执行 PLC 逻辑 (避免输出冲突)
  • 发送 EtherCAT 帧 (网卡处于静默模式, 只收不发)
  • 100ms 回发心跳 ACK

6.2 故障检测

备机的 HeartbeatMonitor 持续检测主机心跳:

  • 每 100ms 应收到一个心跳包
  • 连续 3 次 (300ms) 未收到, 判定主机失效
  • 同时触发同步链路断线检测 (TCP keepalive)
  • 两个信号任一触发, 切换仲裁启动

6.3 切换过程

关键时间线:

阶段耗时
心跳丢失确认300 ms (3 × 100 ms)
仲裁 + MAC 克隆<5 ms
AL 状态激活 + 首帧发送<10 ms
总切换时间约 315 ms

若将心跳周期调为 20 ms (高配置场景), 总切换时间可压到 <70 ms, 但同步 CPU 占用上升。

6.4 切换后

  • 原主机如恢复上线, 自动进入"备"角色, 拉取全量状态
  • 原主机如无法恢复 (硬件损坏), 运维手动更换后, 系统自动识别并加入
  • 备机变主后, 若原主机未恢复, 系统以单机模式运行, 冗余状态显示为"降级运行 (Degraded)"

6.5 HMI 感知

所有切换事件会被记录为系统事件, HMI 可订阅显示:

  [2026-04-15 14:32:18] WARN  冗余切换: 主 A → 主 B, 原因: 心跳丢失
[2026-04-15 14:35:42] INFO 原主 A 恢复, 已加入为备

HMI 状态栏可放置一个"冗余指示灯": 绿色=正常双机, 黄色=降级单机, 红色=双机失联。


7. EtherCAT 冗余深度

7.1 三个层次的冗余

EtherCAT 冗余需要区分三个层次:

  1. 电缆冗余 (物理层) — 一根网线断了, 走另一根
  2. 主站冗余 (控制层) — 主工控机宕机, 备工控机接管
  3. 从站冗余 (设备层) — 单个从站故障, 旁路继续

Darra 在这三个层次都有方案, 下面展开。

7.2 电缆冗余 (Cable Redundancy)

Darra 已有 SecondaryAdapter 机制, 主站网卡开两个口, 从站接成环网 (HSR 拓扑):

任一段断线, 数据帧从另一个方向绕行, 从站业务无中断。这是主站单机内部的冗余, 不涉及双工控机。

7.3 主站冗余 (Master Redundancy) — 本方案核心

即本文讨论的双 PLC 热切换。核心技术点:

MAC 克隆

EtherCAT 从站只识别 EtherType + MAC (从站无 IP 概念)。备机切换时, 必须:

  1. 停用本机 EtherCAT 网卡原 MAC
  2. 编程方式把主机的 MAC 地址写入网卡寄存器
  3. 开始发送帧, 从站以为主机"还在"

这个操作在主机侧的 OUI 下由 Darra 驱动完成, 对从站完全透明。

AL 状态继承

EtherCAT 从站有 AL 状态机 (Init → PreOP → SafeOP → OP)。切换瞬间, 备机必须:

  • 知道每个从站当前的 AL 状态 (通过同步已拿到)
  • 不要重新走 Init → OP 流程 (那会中断 IO)
  • 直接从 OP 状态接续发送 PDO 帧

7.4 从站冗余

单个关键从站 (如安全 IO) 可加一台相同型号并联, 通过诊断变量判断主从站健康切换。这属于应用层编程, 不由 Darra 运行时自动管理, 需要用户在 ST 里编写切换逻辑。

7.5 不采用的方案

方案为何不采用
HSR 双主同时发帧违反 EtherCAT 单主原则, 帧冲突
外部硬件仲裁器 (同步模块)硬件成本 ¥10 万+, 违反 Darra 软 PLC 路线
系统级 IP 接管 (Windows FCI)切换 >2 秒, 无法满足实时要求

7.6 从站选型建议

推荐使用支持 HSR Redundancy Port 的从站。一个典型环网:

  • 入口: 倍福 EL9011 HSR 冗余终端 (¥1,200)
  • IO 组: EL1809 (16 点 DI) + EL2809 (16 点 DO) 各若干
  • 伺服: 汇川 SV660N 冗余款 ×4
  • 出口: 倍福 EL9012 HSR 冗余终端 (¥1,500)

总共从站 30 台左右的规模, HSR 终端成本占比 <3%。


8. 软件架构 (Runtime 层)

Runtime 内部有 6 个逻辑模块协同工作, 用户不需要直接编程, 但理解职责有助于排障:

8.1 RedundancyManager

冗余总控, 持有当前角色 (主/备), 接受所有模块的状态回调, 对外暴露"角色切换"事件。启动时读取向导保存的配置, 协调各子模块。

8.2 SyncChannel

封装同步链路的传输层:

  • 初次握手走 TCP (可靠, 全量状态)
  • 运行时走 UDP (低延迟, 丢一帧无所谓, 下周期覆盖)
  • 自动重连, 链路断 10 秒后触发降级

8.3 HeartbeatMonitor

独立线程, 每 100ms 发一个心跳并等对方 ACK。超时 3 次 (300ms) 通知 FailoverController。

8.4 StateReplicator

负责把变量表、工艺对象、定时器、PID 内部状态等"脏位"打包/解包。对上层 PLC 运行时透明。

8.5 FailoverController

切换仲裁的决策者。收到 HeartbeatMonitor 的超时信号后:

  • 确认同步链路也断 (排除仅心跳端口故障)
  • 确认本机处于"备"角色
  • 触发 EcatHandover 执行接管
  • 通知 RedundancyManager 更新角色

8.6 EcatHandover

执行 EtherCAT 层接管动作:

  • MAC 克隆
  • AL 状态表激活 (复用 StateReplicator 同步过来的状态快照)
  • 激活 PDO 发送循环

9. 授权模式

9.1 授权分级

授权版本单机运行冗余热备价格 (年费, 占位)
基础版×¥3,000 / 台 / 年
专业版可追加¥8,000 / 台 / 年
企业版 (含冗余)√ 包含¥20,000 / 台 / 年
冗余追加模块¥12,000 / 台 / 年 起

以上价格为文档占位, 实际报价以 Darra 销售给出为准。

9.2 授权绑定

  • 授权绑定单台工控机 (硬件指纹 = 主板序列号 + CPU ID + MAC)
  • 冗余需要两台都有冗余授权, 不支持"一对授权"的共享
  • 某一台工控机硬件更换 (如主板坏了), 授权需要销售协助迁移

9.3 授权校验时机

  • Runtime 启动时, 读取本地授权文件并联网校验 (离线宽限 30 天)
  • 启用冗余向导第 4 步, 本机和对等机都要通过校验
  • 运行中若授权过期, 冗余自动降级为单机 (主机继续跑, 备机退出同步)

9.4 试用期

新客户可申请 30 天冗余试用授权, 与正式授权功能一致, 便于项目验收。


10. 和 S7-1500 R/H 对比

对比项Darra 冗余S7-1500 RS7-1500 H
同步介质万兆以太网专线标准 1 GbE PROFINET光纤同步模块
同步周期1 ms4 ms 起1 ms
切换时间<50 ms (可配置) ~ 315 ms (默认)<300 ms<50 ms
IO 冗余EtherCAT HSR (S1 系统冗余)PROFINET S2PROFINET S2
硬件成本 (一对)¥4.2 万¥20 万起¥50 万起
软件年费 (一对)¥2.4 万约 ¥8 万约 ¥15 万
授权单位单台授权 × 2系统授权系统授权
开发难度和单机项目一致需理解系统冗余变量同 R, 且需配置同步模块
维护热插拔 / 在线升级热插拔热插拔, 但需原厂服务

总结: Darra 冗余方案在切换时间与 S7-1500 H 同档, 在硬件成本比 S7-1500 R 降低约 4 倍, 开发难度与单机项目一致。


11. 常见问题 (FAQ)

Q1 切换时数据会丢失吗

答: 不会丢变量状态, 但可能丢最多 1 个扫描周期的输入采样。

  • 变量表、工艺对象、PID 积分项、定时器剩余时间等, 每 1 ms 同步一次, 切换瞬间备机持有的状态最多落后 1 ms
  • 输入采样: 故障瞬间主机读到的那一帧 IO 若还未同步就崩了, 这一帧会丢 (典型 1 ms 周期 ≤1ms 数据量), 备机下一个周期重新采样
  • 对连续控制 (如液位、温度) 完全无影响; 对事件计数 (脉冲编码器) 可能少 1 个脉冲, 用 ST 的"对齐"逻辑可补回

Q2 两台 PLC 时钟偏差怎么处理

答: Darra 自动处理。

  • 启动握手阶段, 两机交换 TSC (CPU 高精度时间戳计数器) 基线, 误差 <1 μs
  • 运行中每 10 秒测量一次漂移, 动态补偿备机内部时钟相位
  • 因此 PLC 里的 SystemTime 两机始终一致, 定时器不会因切换而跳变

Q3 从站不支持 HSR 能用主站冗余吗

答: 能, 但降级为"主站冗余 + 单链路"。

  • 主站冗余 (双工控机热切换) 不依赖从站 HSR
  • 但从站若只有单口, EtherCAT 电缆只能单链, 网线断了就停线
  • 推荐: 关键项目一定选 HSR 从站; 非关键项目可退而求其次

Q4 冗余会拖慢扫描周期吗

答: 影响 <5%, 可忽略。

  • 同步工作由独立线程做, 不阻塞 PLC 扫描
  • 脏位收集是 O(变化数) 而非 O(总变量), 2000 变量 5% 变化只需几微秒
  • 万兆网卡 DMA 零拷贝, 不吃 CPU
  • 实测: 单机扫描 0.85 ms, 冗余模式扫描 0.87 ms, 开销 ~2%

Q5 网络异常导致"脑裂"(两台都以为自己是主)怎么办

答: Darra 有三重防护:

  1. 仲裁优先级: 向导配置的"本机角色"里, 若选了固定角色, 永不脑裂
  2. 同步链路 + 心跳口双通道: 两个链路都断才算失联 (概率极低)
  3. 外部仲裁 (企业版可选): 通过云端服务或第三台见证机做 quorum 决策

实际工程中, 把同步链路布在和 UPS 同一物理回路, 故障相关性极高, 脑裂概率 <百万分之一。

Q6 升级 PLC 程序时两台怎么同步

答: 滚动升级, 不停机。

  • IDE 连接主机, 下载新程序 — 此时备机仍用旧程序同步
  • 触发手动切换 (冗余面板 → "主动切换到备机") — 备机接管, 旧程序继续运行
  • IDE 连接新的备机 (原主机), 下载新程序
  • 再次手动切换, 切回原主机, 此时两机都是新程序
  • 全程现场设备不感知, 产线不停

Q7 A/B 机型号不同能用冗余吗

答: 能, 但有约束。

  • CPU 代际: 必须同代或相邻一代 (如 Intel 12 代 + 12 代, 或 12 代 + 13 代), 避免 TSC 行为差异
  • 内存: 可以不同容量, 大者向小者对齐使用
  • 网卡: 同步网卡必须同型号 (避免驱动差异影响延迟)
  • 操作系统: 两机必须同版本同补丁级 (强制)
  • 实践建议: 新建项目一定用同型号机; 老项目迁移或 A 机坏了换新, 允许短期不对称

Q8 授权绑定单台还是一对

答: 单台 × 2。

  • 每台工控机都要买一份冗余授权
  • 不能"一对 ¥15,000", 因为许可证是绑硬件指纹的
  • 好处: 一台换硬件只需迁移一份授权, 另一台不受影响

Q9 现场维护时如何计划性切换

答: 冗余面板提供"主动切换"功能。

  1. 冗余状态面板 → 右侧"维护" 按钮
  2. 选择"主动切换到备机"
  3. 确认弹窗 (显示当前状态、预计切换时间、是否允许)
  4. 系统协调: 主机完成当前扫描 → 发送"交接"帧 → 备机确认接管 → 主机降级
  5. 整个过程切换时间 <5 ms (比故障切换还快, 因为无需等心跳超时)

Q10 如何测试冗余是否真的生效

答: Darra 提供"冗余测试工具" (IDE 菜单 → 工具 → 冗余测试):

  • 心跳中断测试: 模拟主机心跳断开, 观察是否在 <350 ms 切换
  • 网线拔插测试: 物理拔主机 EtherCAT 线, 备机是否立刻接管
  • 掉电测试: 切主机电源, 观察产线是否不停机
  • 数据一致性测试: 切换前后对比所有变量值差异, 应为 0
  • 长期稳定性: 连续运行 7 天, 每日记录切换成功次数/失败次数

验收建议: 用户在 FAT (工厂验收测试) 阶段做 100 次随机切换, 要求全部成功且无数据丢失。


12. 1oo2D 和 2oo3 安全冗余架构

12.1 为什么需要 1oo2D 和 2oo3

第 1-11 章讨论的"双 PLC 热切换"本质是 1oo1D (one out of one with diagnostics) 架构 — 两个 PLC 运行时只有一台真正驱动 IO, 备机仅做影子同步。这种架构在主机故障时可恢复运行, 但它不解决"输出错误"问题: 如果主机非宕机, 而是因 CPU 或内存故障输出错误数值, 备机不会主动切换 (因为心跳还在), 错误输出可能持续数百毫秒。

1oo2D 和 2oo3 架构解决的是安全完整性等级 (SIL) 相关的冗余, 而非单纯的"高可用":

架构冗余模式容忍故障检测输出错误安全等级典型应用
1oo1D双机热备 (本文 1-11 章)单机宕机否 (仅检测心跳)SIL 2高可用产线, 容忍停机
1oo2D双机同时执行 + 诊断单机故障, 含错误输出是 (交叉比较 + 诊断)SIL 3安全关键设备
2oo3三机表决单机故障, 含错误输出是 (多数表决)SIL 3高可用 + 安全关键

12.2 架构差异概览

核心区别:

  • 1oo1D: 同一时刻只有一台 PLC 输出, 另一台接替的前提是"心跳消失"。无法检测静默错误输出。
  • 1oo2D: 两台 PLC 同时执行同一套逻辑, 每周期交叉比较输出, 不一致时由诊断覆盖 (Diagnostic Coverage) 判断哪台故障, 切断故障侧输出。
  • 2oo3: 三台 PLC 同时执行, 输出经多数表决器 (2/3 一致才输出), 任意一台故障不影响输出, 且不需要诊断就可定位故障侧。

12.3 何时选用哪种架构

因素1oo1D1oo2D2oo3
硬件成本2 台工控机2 台工控机3 台工控机
安全等级SIL 2 (需外部诊断)SIL 3SIL 3
可用性99.999%99.999%99.9999%
输出错误容忍
维护复杂度
典型场景普通产线安全 IO / 紧急停机核电 / 航空 / 关键安全

Darra 的建议: 90% 的冗余场景用 1oo1D 即可; 只有安全关键场景 (急停回路、安全门、燃烧器控制) 才需要 1oo2D 或 2oo3。三种架构可在同一项目内混用 — 安全 IO 走 1oo2D, 普通 IO 走 1oo1D。


13. RedundantPlcExecutor 实现

13.1 IPlcExecutor 接口

IPlcExecutor 是 PLC 字节码执行器的抽象接口, 定义了执行器的核心契约:

public interface IPlcExecutor : IDisposable
{
/// <summary>执行一个完整扫描周期</summary>
PlcExecutionResult ExecuteCycle();

/// <summary>清除输出到安全状态</summary>
void ClearOutputsToSafe();

/// <summary>紧急停止</summary>
void EmergencyStop();

/// <summary>当前执行器状态</summary>
ExecutorState State { get; }

/// <summary>最近一次执行结果</summary>
PlcExecutionResult LastResult { get; }

/// <summary>执行器健康检查</summary>
ExecutorHealth Health { get; }

/// <summary>执行器故障事件</summary>
event EventHandler<ExecutorFaultEventArgs> Faulted;
}

此接口将"执行一个 PLC 周期"与"执行器的具体运行方式"解耦 — 单机运行时, PlcVmExecutor 直接实现此接口; 冗余模式下, RedundantPlcExecutor 包装多个 IPlcExecutor 实例, 提供一致的执行视图。

13.2 RedundantPlcExecutor 包装模式

RedundantPlcExecutor 的核心设计是装饰器模式 (Decorator Pattern):

public class RedundantPlcExecutor : IPlcExecutor
{
private readonly IPlcExecutor _primary;
private readonly IPlcExecutor _secondary;
private readonly ICrossComparator _comparator;
private readonly IFailoverStrategy _strategy;
private readonly object _gate = new();

// 1oo2D 模式下两个执行器同时执行
// 2oo3 模式下有三个执行器

public PlcExecutionResult ExecuteCycle()
{
lock (_gate)
{
// 步骤 1: 所有执行器并行执行 (实际线程池调度)
var task1 = Task.Run(() => _primary.ExecuteCycle());
var task2 = Task.Run(() => _secondary.ExecuteCycle());
Task.WaitAll(task1, task2);

// 步骤 2: 交叉比较结果
var result1 = task1.Result;
var result2 = task2.Result;
var comparison = _comparator.Compare(result1, result2);

// 步骤 3: 根据比较结果和故障策略决定实际输出
if (comparison.IsConsistent)
return result1; // 两者一致, 任取一个

// 不一致: 进入诊断 + 故障处理流程
return HandleDiscrepancy(result1, result2, comparison);
}
}
}

关键设计决策:

  • 锁粒度: _gate 保护整个执行周期, 防止多个周期交叉执行导致输出混乱
  • 并行执行: 各执行器通过 Task.Run 并行调度, 不增加扫描周期延迟 (在 2oo3 模式下尤其重要)
  • 结果一致即返回: 交叉比较通过后, 输出无差异, 返回任一执行器的结果即可
  • 不一致触发诊断: 见第 15 章交叉比较

13.3 2oo3 三机表决

2oo3 模式在 RedundantPlcExecutor 内部维护三个 IPlcExecutor 实例:

private readonly IPlcExecutor[] _voters = new IPlcExecutor[3];

public PlcExecutionResult ExecuteCycle()
{
lock (_gate)
{
// 三路并行执行
var results = _voters.Select(v => Task.Run(() => v.ExecuteCycle())).ToArray();
Task.WaitAll(results);

// 多数表决
var groups = results.GroupBy(r => r.OutputHash);
var majority = groups.FirstOrDefault(g => g.Count() >= 2);

if (majority != null)
{
// 2/3 一致, 输出多数结果
// 不一致的那个执行器被标记为可疑
return majority.First();
}

// 3 路结果全不一致 → 严重故障, 安全降级
return HandleFullDisagreement(results);
}
}

OutputHash 是执行器输出的快速摘要 (对输出区的所有字节做哈希), 用于快速比较差异, 不比对完整输出表以减少开销。

13.4 与 1oo1D 热备的关系

RedundantPlcExecutor 与第 8 章的 RedundancyManager / FailoverController 是两个独立层次:

层次组件职责冗余类型
执行层RedundantPlcExecutor周期内多路执行 + 交叉比较1oo2D / 2oo3
管理层RedundancyManager + FailoverController心跳检测 + 角色切换 + MAC 克隆1oo1D

两者可组合使用: 1oo2D 模式下, RedundantPlcExecutor 负责周期内输出一致性, RedundancyManager 负责整机故障切换; 如果 RedundantPlcExecutor 检测到一侧执行器持续故障, 通知 RedundancyManager 触发角色切换。


14. 故障切换策略 (立即切换 vs 防抖切换)

14.1 两种切换策略

Darra 支持的两种故障切换策略, 适用于不同的冗余模式:

策略触发条件切换延迟适用场景
立即切换 (Immediate Failover)单次故障检测即触发<1 ms1oo2D / 2oo3 输出不一致
防抖切换 (Debounced Failover)N 次连续故障才触发可配置 (典型 300 ms)1oo1D 心跳丢失

14.2 立即切换 (Immediate Failover)

在 1oo2D 和 2oo3 架构中, 输出不一致需要立即处理, 不能等 300 ms 确认:

public class ImmediateFailoverStrategy : IFailoverStrategy
{
public FailoverDecision Decide(FailoverContext context)
{
// 交叉比较发现不一致 → 立即触发安全降级
if (context.DiscrepancyDetected)
{
return new FailoverDecision
{
Action = FailoverAction.SafeDegrade,
Reason = $"输出不一致: {context.DiscrepancyDescription}",
Latency = TimeSpan.FromTicks(0) // 立即
};
}

return new FailoverDecision { Action = FailoverAction.None };
}
}

用途: 急停回路、安全门、燃烧器控制等 SIL 3 相关输出, 一旦发现 A/B 两路输出不一致, 必须在当前周期内将输出切换到安全状态, 不能等心跳超时。

14.3 防抖切换 (Debounced Failover)

在 1oo1D 心跳丢失场景, 直接切换可能导致误切换 (如网络瞬断):

public class DebouncedFailoverStrategy : IFailoverStrategy
{
private readonly int _threshold; // 连续失败次数阈值
private int _consecutiveFailures;

public FailoverDecision Decide(FailoverContext context)
{
if (context.HeartbeatReceived)
{
_consecutiveFailures = 0; // 收到心跳 → 复位计数器
return new FailoverDecision { Action = FailoverAction.None };
}

_consecutiveFailures++;

if (_consecutiveFailures >= _threshold)
{
_consecutiveFailures = 0;
return new FailoverDecision
{
Action = FailoverAction.Switchover,
Reason = $"连续 {_threshold} 次心跳丢失",
Latency = TimeSpan.FromMilliseconds(_threshold * 100) // 典型 300ms
};
}

return new FailoverDecision { Action = FailoverAction.None };
}
}

稳定期守卫 (Stable-Period Guard): 在切换完成后, 防抖策略进入一个稳定期, 期间即使再次检测到故障也不会立即切换, 防止"刚切换又切回来"的振荡:

public class StablePeriodGuard
{
private readonly TimeSpan _stablePeriod; // 默认 10 秒
private DateTime _lastSwitchover = DateTime.MinValue;

public bool CanSwitchover()
{
if (DateTime.UtcNow - _lastSwitchover < _stablePeriod)
return false; // 稳定期内, 禁止再次切换

_lastSwitchover = DateTime.UtcNow;
return true;
}
}

14.4 配置示例

在 IDE 冗余配置向导中, 工程师可按优先级配置:

<FailoverPolicy>
<!-- 1oo2D 输出不一致 → 立即安全降级 -->
<Rule Name="Discrepancy" Strategy="Immediate" Action="SafeDegrade" />

<!-- 1oo1D 心跳丢失 → 防抖 300ms -->
<Rule Name="HeartbeatLoss" Strategy="Debounced" Threshold="3" Action="Switchover" />

<!-- 同步链路中断 → 防抖 1 秒 (网络抖动容忍) -->
<Rule Name="SyncLinkDown" Strategy="Debounced" Threshold="10" Action="Degrade" />

<!-- 稳定期: 切换后 10 秒内禁止再次切换 -->
<StablePeriod Seconds="10" />
</FailoverPolicy>

15. 交叉比较 (Cross-Comparison)

15.1 为什么需要交叉比较

在 1oo2D 和 2oo3 架构中, 两个 / 三个执行器同时运行同一套 PLC 逻辑, 理论上输出应完全一致。但实际中可能出现不一致:

  • 硬件故障: CPU 缓存错误、内存位翻转 (bit flip)、浮点运算单元异常
  • 软件故障: 非确定性执行 (如未初始化的变量、随机数生成器状态不同步)
  • 时序差异: 两机的时钟漂移导致定时器 / 延时器输出略有差异

交叉比较的目的是快速发现这些差异, 定位故障源, 并决定输出哪个执行器的结果

15.2 输入比较

输入比较发生在每个扫描周期的开始:

public class InputComparisonResult
{
public bool IsConsistent { get; set; }
public Dictionary<string, InputDiff> Differences { get; set; }
public DiagnosticCoverage Coverage { get; set; }
}
  • 各执行器在周期开始前, 先读取各自的 IO 输入
  • 输入值通过高速同步链路 (DarraSync-HA) 交换
  • 比较器检查各执行器的输入是否一致
  • 不一致 → 可能是输入模块故障或采样时序差异, 标记为"可疑输入通道"

输入差异容忍: 对于模拟量输入 (如温度、压力), 允许一个小的死区 (deadband, 默认 0.5% 满量程), 超出才标记为差异。数字量输入不允许差异。

15.3 输出比较

输出比较发生在每个扫描周期结束后、输出写入 IO 硬件之前:

public class CrossComparator : ICrossComparator
{
private readonly double _analogDeadband; // 模拟量死区, 默认 0.5%

public ComparisonResult Compare(PlcExecutionResult a, PlcExecutionResult b)
{
var result = new ComparisonResult();

// 数字量输出: 逐位比较
foreach (var bit in a.DigitalOutputs)
{
if (a.DigitalOutputs[bit.Key] != b.DigitalOutputs[bit.Key])
{
result.AddDiscrepancy(
DiscrepancyType.DigitalOutput,
bit.Key,
a.DigitalOutputs[bit.Key],
b.DigitalOutputs[bit.Key]);
}
}

// 模拟量输出: 带死区比较
foreach (var ch in a.AnalogOutputs)
{
var diff = Math.Abs(a.AnalogOutputs[ch.Key] - b.AnalogOutputs[ch.Key]);
if (diff > _analogDeadband)
{
result.AddDiscrepancy(
DiscrepancyType.AnalogOutput,
ch.Key,
a.AnalogOutputs[ch.Key],
b.AnalogOutputs[ch.Key]);
}
}

// 内部状态比较: 定时器、计数器、PID 积分项
CompareInternalState(a, b, result);

return result;
}
}

15.4 差异检测与诊断覆盖

当检测到差异时, 系统进入诊断流程:

诊断覆盖 (Diagnostic Coverage, DC) 是衡量系统检测故障能力的指标:

诊断方法覆盖范围典型 DC
CPU 自检 (ECC / 奇偶校验)内存错误99%
指令集测试 (自检程序)CPU 逻辑错误95%
输出回读 (Readback)输出通道故障99%
看门狗定时器任务超时 / 死锁99%
电源电压监测电源波动90%
交叉比较 (Cross-Comparison)综合差异99.9%

15.5 差异处理策略

差异类型严重度默认动作可配置?
数字量输出不一致严重安全降级, 输出切换到安全状态
模拟量输出超出死区中等标记故障, 输出故障侧前值
内部状态不一致 (定时器 / PID)中等重新同步状态, 继续运行
单次瞬态差异 (后续周期一致)轻微记录日志, 不做处理

16. 与 OPC UA HA 的关系

16.1 OPC UA Part 4 HA 模型

OPC UA Part 4 (Services) 第 6.6 节定义了 High Availability 模型, 包含三个核心概念:

  • Server Redundancy: 多个 OPC UA 服务器提供相同的数据集, 客户端可透明切换
  • RedundancySupport: 服务器枚举, 表示其冗余能力 (None / Cold / Warm / Hot / Transparent)
  • RedundancyGroup: 多个冗余服务器组成的逻辑组

Darra 的 OPC UA HA 实现在第 8 章 OpcUaHAService 中, 支持:

public enum RedundancySupport
{
None, // 不支持冗余
Cold, // 冷备 (需手动启动)
Warm, // 温备 (备机运行但不同步)
Hot, // 热备 (备机同步, 自动切换)
Transparent // 透明冗余 (客户端无须知道多服务器)
}

16.2 两种冗余的层次关系

Darra 的冗余方案分为两个层次:

L1 — PLC 冗余: 保证现场设备的物理 IO 在主备机之间无缝切换, 对 EtherCAT 从站透明。这是本文的核心内容。

L2 — OPC UA HA: 保证上位机 (SCADA / MES / ERP) 读取 Darra 的过程数据时, 不会因单台服务器宕机而中断。这是 OpcUaHAService 的职责。

16.3 互补场景

场景L1 PLC 冗余L2 OPC UA HA说明
主机宕机, IO 切换必须可选L1 保证 IO 不停; L2 保证上位机不停
主机 CPU 输出错误必须 (1oo2D)不适用L1 交叉比较检测; OPC UA 只看数据
上位机切换服务器不需要必须OPC UA 客户端透明切换服务器
单机运行不需要可选单机模式下 OPC UA HA 不启用
远程诊断不需要建议运维人员通过 OPC UA 读冗余状态

16.4 何时重叠, 何时互补

重叠 (Overlap) 的场景:

  • 当 L1 层次进行故障切换时, L2 的 OpcUaHAService 需要同步知道切换事件, 更新其 RedundancyGroup 状态
  • 切换后, 新主机的 OPC UA 服务器成为活跃服务器, 旧主机的 OPC UA 服务器变成备用

互补 (Complement) 的场景:

  • L1 冗余解决的是"PLC 执行层"的可靠性, 保证现场 IO 不中断
  • L2 冗余解决的是"数据访问层"的可靠性, 保证上位机不中断
  • 两者共存时, 上位机应通过 OPC UA HA 连接两台主机的 OPC UA 服务器, 而不是直接连接其中一台

16.5 配置建议

场景PLC 冗余OPC UA HA推荐配置
普通产线高可用1oo1D不启用两机热备 + 上位机直连主机
安全关键设备1oo2D / 2oo3启用两机执行 + 上位机走 OPC UA HA
大型 SCADA 集成1oo1D启用两机热备 + SCADA 经 OPC UA HA 透明切换
单机 + 远程监控不启用可选单机跑, OPC UA HA 可不启用

16.6 实现示例: OPC UA 冗余状态暴露

OpcUaHAService 通过 OPC UA 变量暴露冗余状态, 供上位机读取:

节点路径数据类型说明
Objects.DarraRedundancy.CurrentRoleUInt320=单机, 1=主, 2=备
Objects.DarraRedundancy.PartnerStatusUInt320=未知, 1=在线, 2=失联, 3=降级
Objects.DarraRedundancy.RedundancyTypeUInt320=1oo1D, 1=1oo2D, 2=2oo3
Objects.DarraRedundancy.LastSwitchoverTimeDateTime最近一次切换时间
Objects.DarraRedundancy.SwitchoverCountUInt32累计切换次数
Objects.DarraRedundancy.OutputDiscrepancyCountUInt32累计输出不一致次数 (1oo2D / 2oo3)

上位机通过订阅这些变量, 可在 HMI 上显示冗余状态, 实现与第 6.5 节 HMI 感知类似的效果, 但走标准 OPC UA 协议而非 Darra 私有协议。


参考资料

  • IEC 61784-2: 实时工业以太网冗余规范
  • IEC 62439-3: HSR / PRP 冗余协议
  • ETG.1510: EtherCAT 冗余方案 (Cable Redundancy)
  • Siemens S7-1500 R/H 系统手册 (对比参考)
  • 《高可用工业控制系统设计》, 机械工业出版社, 2024

本文档属于 Darra PLC 企业版用户手册。如需项目方案设计或试用授权, 请联系 Darra 销售团队。