1. 为什么“位逻辑”才是PLC编程的真正分水岭
干了十几年工控,带过的徒弟少说也有二三十个,我发现一个特别有意思的现象:那些卡在PLC编程门口死活进不去的人,十有八九不是被什么复杂指令难住的。什么PID整定、什么运动控制、什么SCL高级语言,这些他们反而觉得“有章可循”。真正让他们栽跟头的,是看起来最不起眼的位逻辑。
你随便找个学PLC的人问问,梯形图里那个常开触点、常闭触点、线圈输出,谁看不懂?但你要是给他一个稍微绕一点的逻辑——比如“三台电机顺序启动、逆序停止,并且任何一台故障时后续电机立即停机,但故障排除后需要手动复位才能重新启动”——很多人就懵了。不是指令不会,是脑子里那套逻辑映射关系没建立起来。
我见过太多人抱着“指令手册”死磕,把MOV、ADD、CMP背得滚瓜烂熟,结果写出来的程序跑起来就是不对。为什么?因为PLC编程的本质不是“写指令”,而是用布尔逻辑描述物理世界的因果关系。位逻辑就是这个因果关系的原子单元。你连“与或非”在梯形图里怎么对应实际电路都搞不清楚,后面学再多花哨功能都是空中楼阁。
这篇文章我打算把“位逻辑”这件事彻底讲透。从为什么它这么重要,到怎么一步步建立逻辑思维,再到实际编程中那些教科书不会告诉你的坑,全部掰开揉碎。不管你是刚入行的新手,还是带了几年项目但总觉得程序“不够稳”的老手,这篇内容都值得你花时间看完。
2. 位逻辑的本质:从继电器电路到梯形图的思维跃迁
2.1 继电器逻辑是PLC的“母语”
很多人学PLC一上来就打开编程软件,对着梯形图界面开始画。这个路径不能说错,但确实少了一个关键环节——理解继电器逻辑。PLC诞生的初衷就是替代继电器控制柜,所以它的底层逻辑和继电器电路是一一对应的。
我拿一个最简单的例子说明。一个启动按钮、一个停止按钮、一个接触器线圈,组成经典的启保停电路。在继电器时代,你需要一个常开按钮、一个常闭按钮、一个接触器辅助常开触点,加上导线连接。到了PLC里,常开按钮对应梯形图里的常开触点,常闭按钮对应常闭触点,接触器线圈对应输出线圈,辅助触点对应自锁用的常开触点。一一对应,没有例外。
注意:很多新手搞不清楚“常闭按钮”和“常闭触点”的区别。物理按钮的常闭是指“不按时导通、按下时断开”,而梯形图里的常闭触点是指“对应位为0时导通、为1时断开”。这两个概念如果混淆,程序逻辑必错。
我建议每个学PLC的人,在动手编程之前,先拿纸笔画一遍继电器电路图。把每个按钮、每个接触器、每个中间继电器的状态变化都标出来。这个过程看起来笨,但它能帮你建立物理世界到逻辑世界的映射直觉。有了这个直觉,后面看梯形图就不是看“符号”,而是看“电流怎么走”。
2.2 梯形图的“能流”概念为什么重要
梯形图看起来像电路图,但它有一个关键区别:能流是虚拟的。在真实电路里,电流从火线经过触点流到零线,形成回路。在梯形图里,“能流”从左母线流向右母线,经过触点、线圈,但它是逻辑上的“真值传递”,不是物理电流。
这个区别导致一个常见误区:很多人以为梯形图里左边的元件一定比右边的“先执行”。实际上,PLC的扫描机制是从上到下、从左到右逐行扫描,每行内的逻辑关系是并行的。也就是说,同一行里串联的触点,不存在谁先谁后的问题,它们共同决定这一行的通断。
我举个例子。下面这段逻辑:
|----[ I0.0 ]----[ I0.1 ]----------------( Q0.0 )----| |----[ I0.2 ]----+ | | | | |----[ I0.3 ]----+ |这里Q0.0的输出条件是:(I0.0 AND I0.1) OR I0.2 OR I0.3。注意,I0.2和I0.3是并联的,它们和前面的I0.0、I0.1是什么关系?是(I0.0 AND I0.1) OR I0.2 OR I0.3,还是I0.0 AND (I0.1 OR I0.2 OR I0.3)?答案是前者。因为并联分支是从I0.1后面分出去的,所以I0.0是公共条件。
这种“并联分支从哪里分出去”的问题,是新手最容易画错的地方。画错了,逻辑就完全变了。我的经验是:画梯形图之前,先用布尔表达式把逻辑写出来。比如上面这个,先写Q0.0 = (I0.0 AND I0.1) OR I0.2 OR I0.3,然后再画梯形图。这样就不会被图形界面误导。
2.3 位逻辑的四种基本运算在实际项目中的对应
位逻辑说到底就是四种基本运算:与、或、非、异或。但在实际项目里,它们对应的物理场景千变万化。我整理了一个对照表,方便你建立直觉:
| 逻辑运算 | 梯形图表现 | 典型物理场景 | 注意事项 |
|---|---|---|---|
| 与(AND) | 串联触点 | 多条件同时满足才动作,如“门关好且启动按钮按下才运行” | 串联顺序不影响逻辑,但影响可读性 |
| 或(OR) | 并联触点 | 多条件任一满足就动作,如“本地启动或远程启动” | 并联分支的起点要明确 |
| 非(NOT) | 常闭触点 | 条件不满足时动作,如“故障信号消失才允许启动” | 注意物理常闭和逻辑常闭的区别 |
| 异或(XOR) | 两个触点一常开一常闭串联后再并联 | 两条件互斥,如“手动模式和自动模式不能同时有效” | 实际项目中用得少,但面试常考 |
这个表看起来简单,但真正在项目里灵活运用,需要大量练习。我见过一个做了五年项目的工程师,写一个“三选二”表决逻辑,硬是用了十几个中间继电器,程序冗长不说,还容易出错。其实用位逻辑的与或组合,三行就能搞定。
3. 从零构建位逻辑思维的四个阶段
3.1 第一阶段:把物理电路翻译成梯形图
这个阶段的目标是建立映射能力。给你一个继电器电路图,你能直接画出对应的梯形图;反过来,给你一个梯形图,你能说出它对应的物理电路是什么。
我通常让新手从最简单的“点动控制”开始。一个按钮、一个接触器,按下按钮接触器吸合,松开按钮接触器断开。这个电路太简单了,但它是所有逻辑的起点。然后加上自锁,变成启保停。然后加上热继电器保护,变成带过载保护的启保停。然后加上运行指示灯、停止指示灯。一步步加,每一步都对应一个位逻辑的变化。
这个阶段的关键是动手画,不是用软件,是用纸笔。软件会帮你检查语法错误,但不会帮你检查逻辑错误。纸笔虽然笨,但能强迫你思考每一个触点的状态。
实操心得:我让徒弟画图的时候,要求他们在每个触点旁边标注“0状态”和“1状态”下触点是通还是断。比如常开触点,0状态断、1状态通;常闭触点,0状态通、1状态断。这个标注过程看起来多余,但它能帮你避免90%的逻辑错误。
3.2 第二阶段:用布尔表达式描述逻辑
当你能够熟练翻译简单电路后,下一步是脱离图形,用布尔表达式描述逻辑。这个阶段的目标是训练你的抽象思维能力。
比如“三台电机顺序启动”这个需求,用自然语言描述是:按下启动按钮后,电机1启动;电机1启动后延时5秒,电机2启动;电机2启动后延时5秒,电机3启动。按下停止按钮后,三台电机同时停止。
用布尔表达式怎么写?设启动按钮为I0.0,停止按钮为I0.1,电机1输出为Q0.0,电机2输出为Q0.1,电机3输出为Q0.2,定时器为T0、T1。
Q0.0 = (I0.0 OR Q0.0) AND NOT I0.1 T0 = Q0.0 (延时5秒) Q0.1 = T0 AND NOT I0.1 T1 = Q0.1 (延时5秒) Q0.2 = T1 AND NOT I0.1这个表达式写出来,梯形图就一目了然了。而且你会发现,用表达式描述逻辑,比直接画梯形图更不容易出错。因为表达式是线性的,你可以逐项检查;梯形图是二维的,容易看漏。
3.3 第三阶段:处理互锁、联锁和时序
实际项目里,位逻辑很少是孤立的。它总是和互锁、联锁、时序控制纠缠在一起。这个阶段的目标是处理复杂逻辑关系。
互锁的典型场景是正反转控制。电机正转和反转不能同时输出,否则会短路。所以在正转输出回路里串一个反转输出的常闭触点,在反转输出回路里串一个正转输出的常闭触点。这就是最基本的互锁。
联锁的典型场景是流水线。前一道工序完成,后一道工序才能启动;后一道工序停止,前一道工序才能停止。这种逻辑用位逻辑实现,需要引入“完成信号”和“允许信号”的概念。
时序控制的典型场景是红绿灯。红灯亮30秒,然后绿灯亮25秒,然后黄灯亮5秒,循环。这个逻辑用定时器加位逻辑就能实现,但要注意定时器的级联和复位。
我拿红绿灯举个例子。假设红灯Q0.0、绿灯Q0.1、黄灯Q0.2,定时器T0(30秒)、T1(25秒)、T2(5秒)。
Q0.0 = NOT Q0.1 AND NOT Q0.2 AND NOT T0 T0 = Q0.0 (延时30秒) Q0.1 = T0 AND NOT T1 T1 = Q0.1 (延时25秒) Q0.2 = T1 AND NOT T2 T2 = Q0.2 (延时5秒)这个逻辑看起来简单,但实际写的时候要注意:T0计时到之后,Q0.0断开,Q0.1接通,T0需要复位。如果T0不复位,下一轮循环就乱了。所以还要加复位逻辑。这就是位逻辑和定时器配合的典型坑。
3.4 第四阶段:优化逻辑,减少中间变量
当你能够写出正确的逻辑后,下一步是优化。优化有两个方向:减少中间变量,提高程序可读性。
减少中间变量的典型例子是“三选二”表决逻辑。假设三个传感器A、B、C,任意两个为真时输出Q为真。用布尔表达式写:
Q = (A AND B) OR (A AND C) OR (B AND C)这个表达式直接对应梯形图,三个并联分支,每个分支两个串联触点。不需要任何中间变量。但如果你用中间变量,可能会写成:
M0 = A AND B M1 = A AND C M2 = B AND C Q = M0 OR M1 OR M2这样写逻辑没错,但多用了三个中间变量。在小型项目里无所谓,但在大型项目里,中间变量过多会导致程序难以维护。
提高可读性的典型做法是给中间变量起有意义的名字。比如“系统运行中”用M0.0,“故障报警”用M0.1,“自动模式”用M0.2。这样后面的人看程序,不用去猜每个位是什么意思。
注意:优化逻辑的前提是逻辑正确。我见过太多人为了“简洁”把逻辑写错,然后花几个小时调试。我的建议是:先写对,再写好。第一版程序哪怕用一百个中间变量都没关系,只要逻辑对,后面慢慢优化。
4. 位逻辑编程的五个典型坑与排查方法
4.1 双线圈输出:最隐蔽的逻辑杀手
双线圈输出是指同一个输出线圈在程序里出现了两次。在梯形图里,这通常是因为复制粘贴代码后忘记修改输出地址,或者是因为逻辑分支太多,不小心在多个地方写了同一个输出。
双线圈输出的后果是:后面的输出会覆盖前面的输出。因为PLC扫描是从上到下的,最后扫描到的那个线圈状态决定实际输出。如果你在程序开头写了Q0.0 = I0.0,在程序结尾又写了Q0.0 = I0.1,那么Q0.0的实际状态只取决于I0.1,前面的逻辑完全失效。
排查方法很简单:在编程软件里用“交叉引用”功能,查看每个输出线圈被引用了多少次。如果某个输出被多次引用,就要检查是不是双线圈。大多数主流PLC编程软件都有这个功能,比如西门子的TIA Portal、汇川的InoProShop、三菱的GX Works。
实操心得:我养成了一个习惯,每个项目写完后,都会用交叉引用表把所有输出线圈过一遍。这个习惯帮我抓出了至少几十个双线圈问题。特别是多人协作的项目,别人写的程序段里可能也有同样的输出,交叉引用一查就露馅。
4.2 常闭触点的“双重否定”陷阱
常闭触点在梯形图里表示“条件不满足时导通”。但如果你在常闭触点前面又加了一个常闭触点,就变成了“条件满足时导通”。这种双重否定是新手最容易绕晕的地方。
举个例子。假设I0.0是“故障信号”,正常时为0,故障时为1。你想实现“无故障时输出Q0.0”,那么用常闭触点:
|----[ / I0.0 ]----------------( Q0.0 )----|这个逻辑是对的:I0.0为0时,常闭触点导通,Q0.0输出;I0.0为1时,常闭触点断开,Q0.0不输出。
但如果你写成:
|----[ / I0.0 ]----[ / I0.0 ]----( Q0.0 )----|两个常闭触点串联,逻辑就变成了:I0.0为0时,两个常闭都导通,Q0.0输出;I0.0为1时,两个常闭都断开,Q0.0不输出。看起来和上面一样?不对。如果I0.0的状态在扫描周期内变化,两个常闭触点的状态可能不一致,导致逻辑混乱。而且这种写法完全没有意义,纯粹是画蛇添足。
更隐蔽的是“常闭触点+NOT指令”的组合。有些PLC支持NOT指令,对前面的逻辑结果取反。如果你在常闭触点后面又加了NOT,逻辑就变回了常开。这种写法在维护时极其容易出错。
4.3 扫描周期导致的“逻辑竞争”
PLC的扫描周期是“输入采样→程序执行→输出刷新”循环。在一个扫描周期内,输入状态是固定的,但程序执行过程中,如果前面的逻辑改变了某个中间变量的状态,后面的逻辑会立即使用新状态。这就是“逻辑竞争”。
我举个实际例子。假设你有两段逻辑:
// 第一段 M0.0 = I0.0 AND NOT I0.1 Q0.0 = M0.0 // 第二段 Q0.1 = M0.0 AND I0.2如果I0.0为1、I0.1为0、I0.2为1,那么M0.0为1,Q0.0为1,Q0.1也为1。看起来没问题。但如果第一段里M0.0被后面的逻辑修改了呢?比如:
// 第一段 M0.0 = I0.0 AND NOT I0.1 Q0.0 = M0.0 // 第二段 M0.0 = I0.3 Q0.1 = M0.0 AND I0.2这时候M0.0在第一段被赋值为I0.0 AND NOT I0.1,在第二段又被赋值为I0.3。Q0.0用的是第一段的值,Q0.1用的是第二段的值。如果I0.0为1、I0.1为0、I0.3为0、I0.2为1,那么Q0.0为1,Q0.1为0。但如果你把两段逻辑调换顺序,结果就完全变了。
这种问题在大型程序里非常常见,而且极难排查。我的建议是:中间变量的赋值和使用尽量放在同一个程序段里,不要跨段使用。如果必须跨段,就要在变量命名上做区分,比如M0.0用于第一段,M0.1用于第二段。
4.4 定时器与位逻辑的配合失误
定时器在PLC里是“功能块”,不是简单的位逻辑。但定时器的使能端、复位端、输出端都是位逻辑。如果配合不好,就会出现“定时器不计时”“定时器计时不准”“定时器无法复位”等问题。
最常见的坑是定时器使能条件用了自己的输出。比如:
T0 = Q0.0 (延时5秒) Q0.0 = T0这个逻辑看起来是“Q0.0输出5秒后自动断开”,但实际上T0的使能条件是Q0.0,而Q0.0又取决于T0。这就形成了死锁:Q0.0不输出,T0不计时;T0不计时,Q0.0不输出。程序跑起来Q0.0永远不会输出。
正确的写法是:
T0 = I0.0 (延时5秒) Q0.0 = I0.0 AND NOT T0按下I0.0,Q0.0输出,同时T0开始计时;5秒后T0动作,Q0.0断开。松开I0.0,T0复位,Q0.0保持断开。这才是正确的“延时断开”逻辑。
另一个坑是定时器复位不彻底。有些PLC的定时器在使能条件断开后会自动复位,有些则需要手动复位。如果不清楚这个区别,程序就会出现“第二次启动时定时器从上次的值继续计时”的问题。我的经验是:不管PLC是否自动复位,都在逻辑里显式加一个复位条件。比如用停止按钮的常开触点并联在定时器使能端,确保每次启动前定时器都是清零状态。
4.5 输入滤波与位逻辑的“抖动”问题
物理按钮在按下和松开时,触点会有几毫秒到几十毫秒的抖动。如果PLC的输入滤波时间设置得太短,就会把抖动当成多次按下,导致逻辑误动作。这个问题在计数器逻辑里特别明显:按一次按钮,计数器加了3。
解决方法是设置输入滤波时间。大多数PLC都支持在每个输入点的属性里设置滤波时间,通常设为10ms到20ms。如果PLC不支持单独设置,可以在程序里加一个延时确认逻辑:
T0 = I0.0 (延时20ms) M0.0 = T0这样I0.0必须持续为1超过20ms,M0.0才会动作。抖动时间通常小于20ms,所以M0.0只会动作一次。
注意:输入滤波时间不是越长越好。如果设得太长,比如100ms,快速操作时PLC可能反应不过来。我的经验是:普通按钮设10ms,接近开关设5ms,急停按钮设0ms(急停必须立即响应)。
5. 用汇川PLC和InoProShop实战位逻辑编程
5.1 为什么选汇川PLC作为练习平台
市面上PLC品牌很多,西门子、三菱、欧姆龙、松下、汇川、信捷,各有各的编程软件。我选汇川PLC作为实战平台,原因有三个:
第一,汇川的InoProShop软件免费。西门子的TIA Portal虽然功能强大,但正版授权费用不低。对于初学者来说,汇川的软件可以免费下载、免费使用,没有授权困扰。
第二,汇川PLC的指令系统和西门子类似。汇川的AM系列、Easy系列,指令风格和西门子S7-200 SMART、S7-1200很接近。学会了汇川,再学西门子会容易很多。反过来也一样。
第三,汇川PLC在国内中小型项目里占有率很高。特别是包装机械、纺织机械、线缆设备这些行业,汇川PLC用得非常多。学好了直接能用在工作里。
5.2 InoProShop里位逻辑编程的实操步骤
打开InoProShop,新建一个工程,选择对应的PLC型号。我以AM401为例。新建程序段,开始画梯形图。
第一步,定义变量。在变量表里添加输入输出变量:
| 变量名 | 地址 | 数据类型 | 注释 |
|---|---|---|---|
| StartBtn | I0.0 | BOOL | 启动按钮 |
| StopBtn | I0.1 | BOOL | 停止按钮 |
| FaultSig | I0.2 | BOOL | 故障信号 |
| Motor1 | Q0.0 | BOOL | 电机1输出 |
| Motor2 | Q0.1 | BOOL | 电机2输出 |
| RunFlag | M0.0 | BOOL | 运行标志 |
第二步,画启保停逻辑。在程序段里,先画启动按钮的常开触点,并联运行标志的常开触点,再串联停止按钮的常闭触点和故障信号的常闭触点,最后接运行标志线圈。
|----[ StartBtn ]----[ / StopBtn ]----[ / FaultSig ]----( RunFlag )----| |----[ RunFlag ]----+ | | |第三步,用运行标志驱动电机输出。再画一个程序段:
|----[ RunFlag ]----[ / FaultSig ]----( Motor1 )----| |----[ RunFlag ]----[ / FaultSig ]----( Motor2 )----|第四步,编译下载。点击编译按钮,检查有没有语法错误。如果没有错误,连接PLC,下载程序。然后在线监控,观察每个触点和线圈的状态变化。
这个例子虽然简单,但它包含了位逻辑编程的所有核心要素:常开触点、常闭触点、并联分支、串联逻辑、中间变量、输出线圈。把这个例子吃透,后面复杂的逻辑都是在这个基础上叠加。
5.3 用InoProShop的交叉引用功能排查双线圈
InoProShop有一个很实用的功能叫“交叉引用”。在菜单栏里找到“工具”→“交叉引用”,或者直接按快捷键。交叉引用表会列出每个变量在程序里的所有引用位置,包括读和写。
如果你怀疑有双线圈,就在交叉引用表里找输出变量。比如Q0.0,如果它在多个程序段里被写成线圈,交叉引用表会全部列出来。你一眼就能看出哪些是重复的。
我实测下来,InoProShop的交叉引用功能比三菱的GX Works更直观。三菱的交叉引用需要手动刷新,汇川的是实时更新的。而且汇川的交叉引用表可以直接双击跳转到对应的程序段,排查效率很高。
实操心得:我建议每写完一个程序段,就打开交叉引用表看一眼。特别是输出变量,确保每个输出只在一个地方被赋值。这个习惯能帮你省下大量调试时间。
5.4 汇川Easy系列PLC的位逻辑编程注意事项
汇川Easy系列是紧凑型PLC,性价比很高,但在位逻辑编程上有几个需要注意的地方。
第一,Easy系列的输入滤波时间默认是10ms。如果你用接近开关或者光电传感器,响应速度可能不够。需要在硬件配置里把对应输入点的滤波时间改小,比如改成3ms或5ms。
第二,Easy系列的定时器编号是有限的。比如Easy521有256个定时器,看起来很多,但如果程序里大量使用定时器,可能会不够用。我的建议是:能用位逻辑实现的延时,尽量不用定时器。比如用扫描周期计数来实现短延时。
第三,Easy系列的M区(中间继电器)是掉电保持的。这意味着PLC断电重启后,M区的状态会保持断电前的值。如果你不希望某个中间变量保持,需要在程序初始化段里手动清零。这个特性在西门子PLC里是可以配置的,但汇川Easy系列默认就是保持。
6. 位逻辑进阶:从单机控制到系统联锁
6.1 多台设备联锁的逻辑设计
单台设备的位逻辑相对简单,多台设备联锁就复杂多了。我以一个实际项目为例:一条输送线,有上料机、传送带、下料机三台设备。启动顺序是上料机→传送带→下料机,停止顺序是下料机→传送带→上料机。任何一台设备故障,后续设备立即停机,前序设备延时停机。
这个逻辑用位逻辑实现,需要定义以下变量:
| 变量名 | 地址 | 注释 |
|---|---|---|
| StartBtn | I0.0 | 启动按钮 |
| StopBtn | I0.1 | 停止按钮 |
| Fault1 | I0.2 | 上料机故障 |
| Fault2 | I0.3 | 传送带故障 |
| Fault3 | I0.4 | 下料机故障 |
| Feeder | Q0.0 | 上料机输出 |
| Conveyor | Q0.1 | 传送带输出 |
| Unloader | Q0.2 | 下料机输出 |
| SysRun | M0.0 | 系统运行标志 |
| FeederDone | M0.1 | 上料机完成标志 |
| ConveyorDone | M0.2 | 传送带完成标志 |
启动逻辑:
SysRun = (StartBtn OR SysRun) AND NOT StopBtn AND NOT Fault1 AND NOT Fault2 AND NOT Fault3 Feeder = SysRun AND NOT FeederDone T0 = Feeder (延时3秒) FeederDone = T0 Conveyor = FeederDone AND NOT ConveyorDone T1 = Conveyor (延时3秒) ConveyorDone = T1 Unloader = ConveyorDone停止逻辑:
Unloader = ConveyorDone AND NOT StopBtn T2 = NOT Unloader (延时2秒) Conveyor = FeederDone AND NOT ConveyorDone AND NOT T2 T3 = NOT Conveyor (延时2秒) Feeder = SysRun AND NOT FeederDone AND NOT T3故障逻辑:
FaultAny = Fault1 OR Fault2 OR Fault3 Unloader = ConveyorDone AND NOT FaultAny T4 = NOT Unloader (延时1秒) Conveyor = FeederDone AND NOT ConveyorDone AND NOT T4 T5 = NOT Conveyor (延时1秒) Feeder = SysRun AND NOT FeederDone AND NOT T5这个逻辑看起来复杂,但拆开看就是几个启保停电路加上定时器级联。关键是要理清楚启动顺序和停止顺序的因果关系。启动时,前一台设备的完成信号是后一台设备的启动条件;停止时,后一台设备的停止信号是前一台设备的停止条件。
6.2 模式切换的逻辑处理
实际项目里,设备通常有手动模式和自动模式。手动模式下,每个动作单独控制;自动模式下,按流程自动运行。模式切换的逻辑用位逻辑实现,需要注意切换时的状态保持和互锁。
我见过一个典型的错误:手动模式下电机正在运行,切换到自动模式后,电机突然停了。原因是自动模式的逻辑里没有考虑手动模式下的运行状态。正确的做法是:模式切换时,先停止所有输出,再切换到新模式。或者用“模式切换请求”信号,等所有设备停止后才真正切换。
// 模式切换请求 ModeSwitchReq = ManualMode AND NOT AutoMode OR AutoMode AND NOT ManualMode // 模式切换允许 ModeSwitchAllow = ModeSwitchReq AND NOT Feeder AND NOT Conveyor AND NOT Unloader // 模式切换执行 ManualMode = ManualMode AND NOT ModeSwitchAllow OR AutoMode AND ModeSwitchAllow AutoMode = AutoMode AND NOT ModeSwitchAllow OR ManualMode AND ModeSwitchAllow这段逻辑看起来有点绕,但核心思想是:模式切换必须等所有设备停止后才能执行。ModeSwitchAllow为1时,ManualMode和AutoMode互换状态。这样就不会出现“运行中切换模式导致设备异常”的问题。
6.3 安全逻辑的位逻辑实现
安全逻辑是位逻辑编程里要求最高的一部分。急停按钮、安全门、光幕这些安全信号,必须用常闭触点接入PLC,并且在程序里用常闭触点串联在输出回路里。这样即使PLC程序出错,安全信号也能直接切断输出。
我以急停按钮为例。急停按钮的物理触点是常闭的:不按下时导通,按下时断开。接入PLC时,I0.5在正常状态下为1,急停按下时为0。
|----[ / I0.5 ]----[ / I0.6 ]----( SafetyRelay )----|这里I0.5是急停按钮,I0.6是安全门。两个常闭触点串联,任何一个断开,SafetyRelay就不输出。SafetyRelay再串联到所有输出回路里:
|----[ SafetyRelay ]----[ RunFlag ]----( Motor1 )----|这样即使程序逻辑出错,只要急停按钮按下,SafetyRelay断开,所有电机都会立即停机。
注意:安全逻辑不能只靠PLC程序实现。急停按钮必须同时切断接触器线圈的电源,这是硬件安全回路的要求。PLC程序里的安全逻辑是“第二道防线”,不是“唯一防线”。
7. 位逻辑学习的常见问题速查
7.1 逻辑写对了但程序跑不对,怎么排查
这是最常见的问题。逻辑在纸上推演是对的,下载到PLC里跑起来就是不对。排查思路如下:
第一步,在线监控。打开编程软件的在线监控功能,观察每个触点和线圈的实时状态。看看哪个触点的状态和预期不符。
第二步,强制变量。如果某个输入信号没有实际接入,可以用强制功能模拟输入。比如强制I0.0为1,观察程序反应。注意:强制功能只能在调试时用,正式运行时必须取消强制。
第三步,分段排查。把程序分成几个独立的段,逐段禁用,观察问题出在哪一段。大多数PLC编程软件都支持“段禁用”功能。
第四步,检查扫描周期。如果程序很大,扫描周期可能超过100ms。这时候输入信号的变化可能被漏掉。可以在程序里加一个扫描周期计数器,观察扫描周期是否正常。
7.2 定时器不动作的常见原因
定时器不动作,通常有以下几个原因:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 定时器不计时 | 使能条件不满足 | 在线监控使能端状态 |
| 定时器计时到但不动作 | 输出端被双线圈覆盖 | 用交叉引用检查输出 |
| 定时器计时不准 | 扫描周期波动 | 检查程序大小,优化逻辑 |
| 定时器无法复位 | 复位条件不满足 | 检查复位逻辑,确保复位信号有效 |
| 定时器编号冲突 | 同一个定时器被多次使用 | 用交叉引用检查定时器编号 |
我遇到最多的是“定时器编号冲突”。特别是在复制粘贴代码时,忘记修改定时器编号,导致两个逻辑用了同一个定时器。这种情况下,两个逻辑会互相干扰,定时器行为完全不可预测。
7.3 输入信号抖动导致逻辑误动作
输入信号抖动是现场调试的常见问题。按钮、接近开关、光电传感器都可能产生抖动。解决方法有三种:
第一种,硬件滤波。在输入端子并联一个电容,或者选用带滤波功能的传感器。这种方法效果最好,但需要改硬件。
第二种,软件滤波。在程序里加延时确认逻辑,输入信号持续为1超过一定时间才认为有效。这种方法灵活,但会增加程序扫描时间。
第三种,PLC内置滤波。大多数PLC都支持在每个输入点的属性里设置滤波时间。这种方法最简单,但滤波时间设置需要经验。
我的建议是:优先用PLC内置滤波,设置10ms到20ms。如果还不够,再加软件滤波。硬件滤波是最后的选择,因为改硬件麻烦。
7.4 程序能跑但“不够稳”的优化方向
有些程序逻辑是对的,但运行起来总感觉“不够稳”。可能的原因和优化方向:
第一,扫描周期过长。程序太大,扫描周期超过50ms,导致输入响应不及时。优化方法是精简程序,把不必要的高速逻辑移到中断程序里。
第二,中间变量过多。中间变量太多会导致程序可读性差,维护困难。优化方法是合并逻辑,减少不必要的中间变量。
第三,没有初始化逻辑。PLC上电时,M区和Q区的状态是不确定的。如果没有初始化逻辑,程序可能从错误的状态开始运行。优化方法是在程序开头加一段初始化逻辑,把所有中间变量和输出清零。
第四,没有故障自诊断。程序运行中可能出现各种异常,如果没有自诊断逻辑,故障很难定位。优化方法是加一段故障检测逻辑,监控关键变量的状态,异常时报警并记录。
8. 位逻辑的延伸:从梯形图到SCL和ST
8.1 为什么位逻辑是SCL和ST的基础
现在越来越多的项目用SCL(结构化控制语言)或ST(结构化文本)来写PLC程序。这两种语言看起来和梯形图完全不同,但它们的底层逻辑还是位逻辑。
比如SCL里的IF语句:
IF StartBtn AND NOT StopBtn THEN RunFlag := TRUE; END_IF;这个逻辑和梯形图里的启保停是完全等价的。如果你不理解位逻辑,写SCL也只是把梯形图的符号换成文字,逻辑还是错的。
我见过很多用SCL写程序的工程师,代码看起来很“高级”,但逻辑漏洞百出。原因就是他们跳过了位逻辑这个基础,直接学SCL的语法。语法学会了,但逻辑思维没建立起来。
8.2 用SCL重写位逻辑的注意事项
用SCL重写位逻辑,有几个和梯形图不同的地方需要注意:
第一,赋值顺序。SCL是顺序执行的,赋值顺序会影响结果。比如:
RunFlag := StartBtn AND NOT StopBtn; Motor1 := RunFlag; RunFlag := FALSE; Motor2 := RunFlag;这段代码里,Motor1为TRUE,Motor2为FALSE。因为RunFlag在中间被改成了FALSE。如果换成梯形图,两个输出都用RunFlag,结果会不一样。所以在SCL里,中间变量的赋值和使用要特别小心顺序。
第二,边沿检测。梯形图里有专门的边沿检测触点(上升沿、下降沿),SCL里需要用R_TRIG和F_TRIG功能块。如果直接用IF语句判断,可能会在一个扫描周期内多次触发。
第三,逻辑运算的优先级。SCL里的AND、OR、NOT有优先级,AND高于OR。如果搞不清楚优先级,就要加括号。梯形图里不存在优先级问题,因为图形本身就表达了逻辑关系。
8.3 位逻辑在SCADA和HMI中的应用
位逻辑不仅用于PLC程序,还用于SCADA和HMI的画面逻辑。比如一个按钮在HMI上按下时,需要判断当前模式、当前权限、当前设备状态,才能决定是否允许操作。这些判断逻辑本质上还是位逻辑。
我以威纶通触摸屏为例。在威纶通的宏指令里,可以用位逻辑判断按钮的使能条件:
if (GetBit(StartBtn) == 1 && GetBit(StopBtn) == 0 && GetBit(FaultSig) == 0) { SetBit(RunFlag, 1); }这段宏指令的逻辑和PLC里的启保停是一样的。如果你不理解位逻辑,写出来的宏指令也会有同样的逻辑错误。
实操心得:我建议学PLC的人,在学HMI和SCADA之前,先把位逻辑彻底搞透。因为HMI和SCADA的逻辑错误比PLC更难排查,PLC还能在线监控,HMI和SCADA只能靠日志和调试工具。
9. 我个人在实际项目中的几点体会
带了这么多年项目,我越来越觉得位逻辑是PLC编程的“内功”。那些花哨的指令和功能块是“招式”,招式可以速成,但内功需要日积月累。我见过太多人追求“高级”功能,结果连最基本的启保停都写不稳。
我的建议是:每个项目开始前,先用纸笔把逻辑关系画清楚。不要一上来就打开编程软件。纸笔虽然慢,但它能强迫你思考每一个逻辑关系。等你把逻辑关系理清楚了,再用软件实现,效率反而更高。
另外,不要怕用中间变量。很多新手觉得中间变量用多了显得“不专业”,其实恰恰相反。中间变量用得好,程序可读性会大幅提升。关键是给中间变量起有意义的名字,并且控制数量。我的经验是:一个程序段里,中间变量不超过5个,超过就说明逻辑太复杂,需要拆分。
最后,多读别人的程序。特别是那些运行了几年、经过现场考验的程序。看看别人是怎么处理互锁、联锁、时序的。读程序的时候,不要只看逻辑,还要想“为什么这么写”。这个“为什么”才是最有价值的部分。
位逻辑这个东西,说简单也简单,说难也难。简单是因为它只有四种基本运算,难是因为这四种运算可以组合出无穷无尽的逻辑关系。但只要你把基础打牢,后面学什么都会快很多。我见过太多人卡在PLC编程的门口,不是因为他们不够聪明,而是因为他们跳过了位逻辑这个必经之路。希望这篇内容能帮你把这条路走通。