安全联锁是压铸机、涂装线、真空炉这类设备上位机里最不能含糊的部分。C# 里实现联锁逻辑,先要分清两个角色:联锁是"设备能不能动"的守卫,操作是"让设备怎么动"的指令——联锁必须优先、必须兜底、绝不能和操作挤在同一个 if 里。这篇按开发顺序讲:安全等级怎么分级、联锁矩阵怎么建、实时判定线程和事件驱动怎么取舍、上位机与 PLC 互锁的边界在哪、关键变量为什么要写死。
先分级:不是所有联锁都得上同一个强度
把联锁对象按"失效后果"分成三级,不同级用不同实现强度,成本和可靠性的账才划算:
一句话记住边界:能伤人伤机的,绝不上位机;只会伤产品的,才轮到上位机管。这条边界理清楚,整个架构就不会跑偏。
联锁矩阵:把"谁禁了谁"画成一张表
联锁逻辑最怕写成一坨散落的 if,后来人根本看不出来"为什么这台设备现在不许动"。规范做法是把联锁关系集中成一张联锁矩阵——行是动作(允许启动/允许合模/允许开阀),列是前置条件(急停未复位/门未关/模温未达标),表里填允许与否。这张表既是需求文档,后来也直接驱动代码,能让安全和工艺两个部门指着一格吵架,而不是各看各的代码。
| 动作 / 前置条件 | 急停已复位 | 门联锁闭合 | 模温达标 | 真空到位 | 配方已选 |
|---|---|---|---|---|---|
| 允许合模 | ● | ● | ▲ | · | · |
| 允许开高压 | ● | ● | · | · | · |
| 允许开启镀膜靶 | ● | · | · | ● | ▲ |
| 允许启动自动流程 | ● | · | · | · | ● |
图例说明:● = 硬性联锁(不满足绝对禁止,交给 PLC 硬回路或上位机硬判);▲ = 半联锁(不满足给出强告警并阻断,但允许工程师强行解锁);"·" = 本动作不依赖此条件。矩阵定稿后,代码里只出现这张表的映射,绝不出现表格之外的裸 if。
实时判定线程 vs 事件驱动:选错了会两种崩法
联锁判定在 C# 里有两条路,我们这次对比着用才懂各自的坑。
- 固定周期(如 50ms)全量表刷新后逐条判定
- 缺点:占用一点 CPU
- 优点:通信断线、数据抖动时状态仍稳定可按
- 最大价值:作为"最后防线"独立线程,即使事件漏了也兜住
- 只在点位变化时触发判定,响应快、省资源
- 缺点:一旦事件丢失(通信瞬时抖动漏帧),状态不同步
- 缺点:多线程同时回调需加锁,否则竞态
- 适合做快速响应,但别只依赖它管安全
结论是我们常踩出来的:安全联锁用轮询做主、事件做辅。轮询线程兜底保证"状态不漂移",事件用于界面快速刷新。轮询线程里跑联锁判定的骨架:
▲ 轮询联锁线程:快照对齐 + 逐条判定 + 统一动作门,UI 只读 CanXxx 结果
联锁与操作分离,是这次不返工的根子
实战里最容易出事的写法是 if(起步条件) 就启动 这种"边判定边执行"。一但中间插了什么别的东西,联锁强度就被稀释了。我们强制分两层:判定层只产"允许动作"布尔,执行层读这个布尔。操作员点【启动】,执行层先问判定层"CanStart 当前是不是 true",不是就弹"联锁未满足"并列出哪一条不满足。判定和操作之间隔着一道门,测试也好写——把矩阵每个格子造出来断言 CanXxx 对不对,能自动化回归。
上位机联锁和PLC互锁,边界到底怎么切?
举个例子:上位机写"镀膜靶电流 32A",PLC 不要无脑接收,要在 PLC 里做 限幅 + 超时:超过安全工作范围(比如 0~35A)直接拒绝并报警;上位机关联字长时间没心跳,PLC 自动把工艺参数回退到安全默认值。这段互锁逻辑写在 PLC 里,上位机负责生成合理目标值并监控过程,两边各守各的边界,事故概率最低。
关键变量为什么要"写死"一个上限?
联锁程序里的安全阈值(比如超压 0.8MPa、超温 260℃),C# 里很多人用配置项方便调,这没错——但要留一手:程序里编译定死一个不可修改的硬上限,配制的阈值只能比它更严,不能更松。这样哪怕现场工程师把配方参数改到天上去,编译层的硬上限也能兜住。这个"双阈值"设计,安全审计时是加分项,真出事故时是保命符。
这套联锁程序,验收时怎么证明它可靠?
行动建议:联锁写完别急着上线,先把矩阵每一个格子做成自动化测试——把急停未复位、门开着、模温不到底、真空没到位这些状态逐一造出来,断言对应的 CanXxx 必须是 false,行程覆盖率点名表。这一步能跑通,再谈交付。安全联锁不是"有逻辑就行",是"每条可能死人的路径都验证过死了"。测试做得越满,上线睡越香。
