第四章 梯形图编程实战:梯形图基础、运动控制逻辑编写、状态机设计模式
4.1 梯形图,其实没那么玄乎
说实话,很多刚入行的工程师一听到「梯形图」三个字,就觉得这是老古董。我当年也有这想法——直到我在一条高速包装线上被现实狠狠教育了一回。
梯形图是什么?说白了,就是一种用图形表示逻辑的编程语言。左边是母线,右边是线圈,中间是触点。你想想看,这不就是继电器电路的翻版吗?对,它本来就是给电气工程师准备的,让他们不用学C语言也能写程序。
我个人习惯把梯形图分成三块来看:
- 输入条件:常开触点、常闭触点、上升沿、下降沿
- 逻辑处理:串联(AND)、并联(OR)、自锁、互锁
- 输出执行:线圈、置位/复位、定时器、计数器
嗯,这里要注意:梯形图的执行顺序是从左到右、从上到下。这一点和高级语言完全不一样。我在项目中遇到过有人把两个互锁的线圈写在同一行,结果PLC一运行就打架,设备直接报警停机。
核心原则:梯形图里,同一线圈不要在两个不同分支里同时输出。除非你用了置位/复位指令,否则后果自负。
4.2 运动控制逻辑怎么写?从点动到连续
运动控制,说白了就是让电机按照你的想法转起来、停下来、转到指定位置。在包装线上,最常见的动作就是:
- 点动(Jog)—— 调试时用,按着转,松手停
- 回原点(Home)—— 每次开机必须做
- 定长运动(Index)—— 切膜、送料、封口
- 连续运行(Run)—— 生产线正常跑
我给你们看一段我实际用过的梯形图逻辑,这是点动和连续运行的切换:
// 点动模式
||---[ 点动按钮 ]-------------------( 电机正转 )---|
||---[ 急停按钮/常闭 ]---[ 点动按钮 ]---( 电机反转 )---|
// 连续运行模式(带自锁)
||---[ 启动按钮 ]---[ 停止按钮/常闭 ]---( 运行中 )---|
||---[ 运行中 ]-----------------------------------( 运行中 )---|
// 输出合并
||---[ 点动模式 ]---[ 点动正转 ]---( 电机正转输出 )---|
||---[ 连续模式 ]---[ 运行中 ]---[ 正转方向 ]---( 电机正转输出 )---|
你看,逻辑其实不复杂。但坑在哪里?坑在「模式切换」的时候。我曾经遇到过操作工在点动模式下没松手,直接切到连续模式,电机突然全速跑起来,差点把模具撞坏。
避坑指南:模式切换时,一定要先强制停止所有输出,再切换。我后来在程序里加了一个「模式切换中」的中间变量,切换时先复位所有输出,延时100ms再激活新模式。
4.3 状态机设计模式——让逻辑不再乱成一锅粥
说实话,我刚入行那会儿写梯形图,就是一个字:堆。按钮多了就加行,动作多了就加分支。结果程序写到后面,自己都看不懂了。直到我学会了状态机设计模式,才真正把逻辑理清楚。
状态机是什么?就是给设备定义几个「状态」,每个状态下只处理该做的事。比如一个包装机的送膜机构,可以分成:
| 状态编号 | 状态名称 | 说明 |
|---|---|---|
| S0 | 空闲 | 等待启动指令,所有输出复位 |
| S1 | 回原点 | 执行回零动作,完成后自动跳转 |
| S2 | 送膜 | 定长送膜,到位后停止 |
| S3 | 封口 | 封口气缸动作,完成后返回S0 |
| SE | 报警 | 任何异常进入,手动复位后回S0 |
用梯形图实现状态机,核心就三句话:
- 当前状态判断:用比较指令判断当前是哪个状态
- 状态转移条件:满足条件时,把状态寄存器的值改成下一个状态编号
- 状态动作执行:每个状态下只执行对应的输出
我给你们画个流程图,你们一看就明白:
你看,状态机的好处就是:每个状态只管自己的事,不会乱。我在实际项目中,把状态编号存在一个叫 D100 的数据寄存器里,然后用比较指令判断当前状态,用 MOV 指令做状态跳转。
我的小技巧:状态编号用十进制,从0开始。0代表空闲,1、2、3...代表工作状态,99代表报警。这样调试时看数据寄存器,一眼就知道设备在干嘛。
4.4 实战案例:一个简单的送料机构
好了,理论说完了,咱们来点实际的。假设你要控制一个送料机构,动作流程是:
- 按下启动按钮,电机正转送料
- 传感器检测到物料到位,电机停止
- 气缸伸出推料
- 气缸缩回,等待下一次启动
用状态机写梯形图,大概长这样:
// 状态寄存器: D0
// 状态定义: 0=空闲, 1=送料, 2=推料, 3=缩回
// ---- 状态转移逻辑 ----
// S0 -> S1: 启动按钮按下
||---[ D0 == 0 ]---[ 启动按钮 ]---( MOV 1 TO D0 )---|
// S1 -> S2: 物料到位传感器
||---[ D0 == 1 ]---[ 物料到位 ]---( MOV 2 TO D0 )---|
// S2 -> S3: 气缸伸出到位
||---[ D0 == 2 ]---[ 伸出到位 ]---( MOV 3 TO D0 )---|
// S3 -> S0: 气缸缩回到位
||---[ D0 == 3 ]---[ 缩回到位 ]---( MOV 0 TO D0 )---|
// ---- 状态动作执行 ----
// S1: 电机正转
||---[ D0 == 1 ]---( 电机正转 )---|
// S2: 气缸伸出
||---[ D0 == 2 ]---( 气缸伸出 )---|
// S3: 气缸缩回
||---[ D0 == 3 ]---( 气缸缩回 )---|
你看,逻辑是不是特别清晰?每个状态做什么、什么时候跳转,一目了然。我后来把所有项目的程序都改成了状态机结构,调试时间至少缩短了一半。
注意:状态机一定要加「超时保护」。每个状态进入后开始计时,如果超过设定时间还没跳转,强制进入报警状态。我曾经因为一个传感器松动,设备卡在送料状态一直转,差点烧了电机。
好了,这一章的内容就到这儿。梯形图不难,难的是把逻辑理清楚。状态机设计模式,说白了就是给程序画个地图,让代码按图索骥,不会迷路。你们回去可以拿自己的项目试试,把原来的面条式逻辑改成状态机,保证你会回来感谢我。