问题引入:一个真实的案例
某包装机械项目需要对产品重量进行分级。工程师用 SCL 写了一段冒泡排序,逻辑完全正确,但一运行就“假死”——触摸屏不刷新、传感器无响应,PLC 状态灯却正常。问题出在哪?
核心问题: PLC 执行冒泡排序时,循环耗时超过了看门狗时间,导致 CPU 进入 STOP 模式。
根本原因分析:三层递进
要理解这个问题,需要从三个层面逐层分析。
第一层:算法本身——O(n²)的时间复杂度
冒泡排序的原理是反复遍历数组,比较相邻元素并交换。对于 N 个数据,最坏情况下需要 N×(N-1)/2 次比较。
| 数据量 |
比较次数 |
风险等级 |
| 10 个 |
约 45 次 |
安全 |
| 100 个 |
约 5 千次 |
警告 |
| 1000 个 |
约 50 万次 |
危险 |
表1:冒泡排序计算量与数据量关系
排序 1000 个数据需要近 50 万次比较,这是算法本身的特性,与用什么编程语言无关。
第二层:PLC 性能——CPU 处理能力有限
PLC 的 CPU 性能远低于 PC。以 S7-200 SMART ST40 为例:
- 布尔指令执行速度:约 0.15μs/指令
- 1000 个数据排序:约 100 万次操作
- 理论执行时间:约 150ms(仅计算指令时间)
S7-200 SMART 的看门狗时间默认约 150ms。一旦程序执行超过这个时间,CPU 会判定“程序过长”,自动进入 STOP 模式——这就是“卡死”的真正原因。
第三层:扫描周期机制——PLC 的工作方式
PLC 采用循环扫描机制:读取输入 → 执行程序 → 通信处理 → 自检诊断 → 刷新输出。每个扫描周期必须在看门狗时间内完成,否则 CPU 停机保护。
关键结论:冒泡排序的 O(n²) 计算量 + PLC 的有限性能 + 扫描周期的时间限制 = 必然卡死
S7-200 SMART vs S7-1200/SCL
不同 PLC 和编程语言的表现有所差异:
| 特性 |
S7-200 SMART |
S7-1200 SCL |
| 编程语言 |
梯形图/指令表 |
结构化文本 (SCL) |
| 循环实现 |
FOR+间接寻址 |
FOR/WHILE/REPEAT |
| 执行特点 |
可能跨多个周期 |
增加单周期时长 |
| 超时后果 |
CPU 进入 STOP |
CPU 进入 STOP |
表2:不同 PLC/语言对比
S7-200 SMART(梯形图/LAD)
使用 FOR 循环配合间接寻址实现排序。循环可能自然跨越多个扫描周期,但一旦超过看门狗时间,CPU 进入 STOP 模式。
S7-1200 SCL
SCL 语法简洁,但程序块(OB/FB/FC)必须在单个扫描周期内完成。循环耗时直接增加扫描周期长度,更容易触发看门狗。
误区:SCL 是“高级语言”,执行更快?错误!SCL 只是代码更易读,执行效率取决于算法复杂度和 CPU 性能,与语言无关。
解决方案:四步走
针对上述三层原因,提供以下解决方案。
方案一:状态机分步执行(治本)
将排序拆分到多个扫描周期执行。每次只完成一轮比较或一个元素定位,保存当前状态(轮次、位置),下次从中断处继续。
优点:不占用单个扫描周期,不会触发看门狗,适用于任何数据量。
方案二:循环中断 OB(S7-1200)
使用 OB30 等循环中断组织块,在固定时间间隔内执行部分排序任务,将计算负载分散到时间上。
方案三:换算法(降复杂度)
冒泡排序 O(n²) 效率低。数据量大时,改用快速排序 O(n log n) 或归并排序,1000 个数据从 50 万次比较降至约 1 万次。
方案四:分批处理(限数据量)
1000 个数据分 10 批,每批 100 个分别排序后合并,降低单次计算压力。
总结
PLC 执行冒泡排序卡死的本质原因:
- 算法层: 冒泡排序 O(n²) 时间复杂度,数据量大时计算量剧增
- 硬件层: PLC 的 CPU 性能有限,百万级操作耗时过长
- 机制层: 扫描周期 + 看门狗保护,超时即停机
无论是 S7-200 SMART 还是 S7-1200 SCL,直接执行大数据量的冒泡排序都会面临同样的问题。建议采用状态机分步执行或更换更高效算法。
|