安全联锁是压铸机、涂装线、真空炉这类设备上位机里最不能含糊的部分。C# 里实现联锁逻辑,先要分清两个角色:联锁是"设备能不能动"的守卫,操作是"让设备怎么动"的指令——联锁必须优先、必须兜底、绝不能和操作挤在同一个 if 里。这篇按开发顺序讲:安全等级怎么分级、联锁矩阵怎么建、实时判定线程和事件驱动怎么取舍、上位机与 PLC 互锁的边界在哪、关键变量为什么要写死。

先分级:不是所有联锁都得上同一个强度

把联锁对象按"失效后果"分成三级,不同级用不同实现强度,成本和可靠性的账才划算:

Level 3人身/设备损毁急停、门联锁、光栅、超温、超压。必须 PLC 硬线回路,上位机只读状态,绝不参与控制
Level 2质量/工艺损失镀层前必须到位、压铸模温不达标禁止合模。上位机联锁可参与,但需与 PLC 双写互锁
Level 1效率/操作保护未选配方禁止启动、料位不足警告。上位机负责即可,告警不阻断安全敏感动作

一句话记住边界:能伤人伤机的,绝不上位机;只会伤产品的,才轮到上位机管。这条边界理清楚,整个架构就不会跑偏。

联锁矩阵:把"谁禁了谁"画成一张表

联锁逻辑最怕写成一坨散落的 if,后来人根本看不出来"为什么这台设备现在不许动"。规范做法是把联锁关系集中成一张联锁矩阵——行是动作(允许启动/允许合模/允许开阀),列是前置条件(急停未复位/门未关/模温未达标),表里填允许与否。这张表既是需求文档,后来也直接驱动代码,能让安全和工艺两个部门指着一格吵架,而不是各看各的代码。

动作 / 前置条件急停已复位门联锁闭合模温达标真空到位配方已选
允许合模··
允许开高压···
允许开启镀膜靶··
允许启动自动流程···

图例说明:● = 硬性联锁(不满足绝对禁止,交给 PLC 硬回路或上位机硬判);▲ = 半联锁(不满足给出强告警并阻断,但允许工程师强行解锁);"·" = 本动作不依赖此条件。矩阵定稿后,代码里只出现这张表的映射,绝不出现表格之外的裸 if。

实时判定线程 vs 事件驱动:选错了会两种崩法

联锁判定在 C# 里有两条路,我们这次对比着用才懂各自的坑。

实时轮询线程(推荐做兜底)
  • 固定周期(如 50ms)全量表刷新后逐条判定
  • 缺点:占用一点 CPU
  • 优点:通信断线、数据抖动时状态仍稳定可按
  • 最大价值:作为"最后防线"独立线程,即使事件漏了也兜住
事件驱动(回调/订阅)
  • 只在点位变化时触发判定,响应快、省资源
  • 缺点:一旦事件丢失(通信瞬时抖动漏帧),状态不同步
  • 缺点:多线程同时回调需加锁,否则竞态
  • 适合做快速响应,但别只依赖它管安全

结论是我们常踩出来的:安全联锁用轮询做主、事件做辅。轮询线程兜底保证"状态不漂移",事件用于界面快速刷新。轮询线程里跑联锁判定的骨架:

void InterlockLoop() { while (_running) { var snap = _plc.ReadSnapshot(); // 全量状态,50ms 一次 lock (_lock) { _em.Merge(snap); // 事件版本与轮询快照对齐 foreach (var rule in _interlockMatrix.Rules) rule.Evaluate(snap); // 逐条判定,含超时变量 } Thread.Sleep(50); } } // 联锁结果统一喂给"允许动作"门: bool CanStart = _allow.Actions[Action.LetRun].Value;

▲ 轮询联锁线程:快照对齐 + 逐条判定 + 统一动作门,UI 只读 CanXxx 结果

联锁与操作分离,是这次不返工的根子

实战里最容易出事的写法是 if(起步条件) 就启动 这种"边判定边执行"。一但中间插了什么别的东西,联锁强度就被稀释了。我们强制分两层:判定层只产"允许动作"布尔,执行层读这个布尔。操作员点【启动】,执行层先问判定层"CanStart 当前是不是 true",不是就弹"联锁未满足"并列出哪一条不满足。判定和操作之间隔着一道门,测试也好写——把矩阵每个格子造出来断言 CanXxx 对不对,能自动化回归。

上位机联锁和PLC互锁,边界到底怎么切?

铁律:凡涉及人身安全的急停、安全门、光栅,信号必须直连 PLC 安全回路或硬线,上位机只能读、不能写。上位机负责的是"工艺级联锁"——比如 Phase A 没走完不许进入 Phase B,这属于 Level 2 非安全关键。真正的边界只有一个:上位机写的任何东西,都要假设自己下一秒会失联。所以上位机下发的工艺参数,PLC 侧要有独立超时和硬限位接收校验,上位机挂了 PLC 自己也能顶住——这叫"降级不失位"。

举个例子:上位机写"镀膜靶电流 32A",PLC 不要无脑接收,要在 PLC 里做 限幅 + 超时:超过安全工作范围(比如 0~35A)直接拒绝并报警;上位机关联字长时间没心跳,PLC 自动把工艺参数回退到安全默认值。这段互锁逻辑写在 PLC 里,上位机负责生成合理目标值并监控过程,两边各守各的边界,事故概率最低。

关键变量为什么要"写死"一个上限?

联锁程序里的安全阈值(比如超压 0.8MPa、超温 260℃),C# 里很多人用配置项方便调,这没错——但要留一手:程序里编译定死一个不可修改的硬上限,配制的阈值只能比它更严,不能更松。这样哪怕现场工程师把配方参数改到天上去,编译层的硬上限也能兜住。这个"双阈值"设计,安全审计时是加分项,真出事故时是保命符。

这套联锁程序,验收时怎么证明它可靠?

行动建议:联锁写完别急着上线,先把矩阵每一个格子做成自动化测试——把急停未复位、门开着、模温不到底、真空没到位这些状态逐一造出来,断言对应的 CanXxx 必须是 false,行程覆盖率点名表。这一步能跑通,再谈交付。安全联锁不是"有逻辑就行",是"每条可能死人的路径都验证过死了"。测试做得越满,上线睡越香。