题目:
在自动化设备中,经常会遇到这样的控制需求:
气缸伸出后,规定 3 秒内必须收到伸出到位信号;夹爪闭合后,规定 2 秒内必须收到夹紧到位信号;输送线启动后,规定 5 秒内必须检测到运行反馈;升降机构下降后,规定 4 秒内必须收到下限位信号。
如果动作已经发出,但是在设定时间内没有收到完成反馈,则触发超时报警。
本例编写一个通用功能块,用 SCL 实现多路设备动作的超时监控。
设计分析:
动作超时报警在项目中非常常见。
有些工程师喜欢每个动作都单独写一个 TON 定时器,例如:
1#气缸伸出超时一个定时器;
1#气缸缩回超时一个定时器;
2#夹爪夹紧超时一个定时器;
2#夹爪松开超时一个定时器。
设备点位少的时候,这样写没什么问题。
但是一旦工位多、气缸多、动作多,程序里就会出现大量重复逻辑。后期调试、查报警、改时间,都会比较麻烦。
本例换一种写法:
用一个 FB 管理多路动作超时。
每一路动作包含三个核心信号:
动作正在执行:actionActive
动作完成反馈:actionDone
超时时间设定:timeoutSetMs
当动作执行中,并且完成反馈没有到达时,程序开始累计时间。
累计时间超过设定值后,输出对应的超时报警。
创建功能块:
创建功能块 FB,命名为:
ActionTimeoutMon
该功能块用于监控多路动作是否超时。
定义接口变量:
定义输入变量:
定义输出变量:
定义静态变量:
定义临时变量:
数组长度本例按照 32 路动作设计,实际项目中可以根据设备规模修改。
程序代码:
调用方法:
在循环 OB 或循环中断 OB 中调用 FB:
ActionTimeoutMon
如果在 OB1 中调用,可以将 cycleMs 设置为一个估算周期,或者使用项目中已有的周期时间变量。
如果对时间精度要求比较高,建议在循环中断 OB 中调用,例如 100 ms 调用一次,则:
cycleMs := 100
举例:
第 1 路监控气缸伸出;
第 2 路监控气缸缩回;
第 3 路监控夹爪夹紧;
第 4 路监控夹爪松开。
对应关系可以这样设计:
actionActive[1]:气缸伸出命令已经发出;
actionDone[1]:气缸伸出到位;
timeoutSetMs[1]:3000。
当伸出命令发出后,如果 3 秒内没有收到伸出到位信号,则:
timeoutAlarm[1] := TRUE
HMI 上可以根据报警数组显示对应的报警文本。
工程注意事项:
动作超时报警最好锁存。
也就是说,超时发生后,即使动作完成反馈后来又到了,报警也不要自动消失。否则现场人员还没来得及看清楚故障原因,报警已经没了。
更推荐的做法是:
故障原因消除后,由操作员按复位按钮清除报警。
另外,actionActive 不建议直接等于输出点。
例如气缸伸出,不要简单写成:
actionActive := YV_Extend
更好的做法是使用“动作步骤正在执行”的状态作为 actionActive。
因为有些设备在故障、急停、手动模式切换时,输出点可能被切掉,但动作步骤本身仍然需要诊断信息。
常见问题:
第一,把超时报警写得太分散。
今天在这个 FC 里写一个 TON,明天在那个 FB 里写一个 TON。最后 HMI 报警、设备动作、调试诊断全部散在不同地方,项目越做越难维护。
第二,报警不锁存。
timeoutAlarm := timer.Q;
这样写最大的问题是:条件一消失,报警也消失。
现场调试时最怕这种报警,发生过,但是没留下痕迹。
第三,超时时间写死在程序里。
例如直接写:
IF elapsedMs >= 3000 THEN
设备调试阶段,经常需要调整动作时间。建议把超时时间放到 DB 或 HMI 参数中,方便调试和维护。
第四,动作信号和完成信号命名不清楚。
不要写 Flag1、Temp2、Mtr_1 这类名字。
建议写成:
CylLiftDownActive
CylLiftDownDone
CylLiftDownTimeout
后期查问题时,变量名本身就是文档。
总结:
本例学习了以下内容:
学习 FOR 循环语句的使用;
学习数组变量在多路设备监控中的应用;
学习动作超时报警的基本设计方法;
学习报警锁存和复位的处理思路;
学习如何把重复的 TON 逻辑封装成通用 FB。
设备项目做多了就会发现,PLC 程序最怕的不是某一段逻辑复杂,而是同一种逻辑到处复制、到处改、到处藏。
动作超时报警这种高频逻辑,适合尽早统一封装。
后面如果继续扩展,还可以在这个 FB 中增加报警代码、报警文本索引、首发报警记录、动作最大耗时记录等功能。
实例分享链接:
https://pan.quark.cn/s/654e499f7756