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定时器T030秒、T125秒、T25秒。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为1Q0.0为1Q0.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为1Q0.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.0Q0.0输出同时T0开始计时5秒后T0动作Q0.0断开。松开I0.0T0复位Q0.0保持断开。这才是正确的“延时断开”逻辑。另一个坑是定时器复位不彻底。有些PLC的定时器在使能条件断开后会自动复位有些则需要手动复位。如果不清楚这个区别程序就会出现“第二次启动时定时器从上次的值继续计时”的问题。我的经验是不管PLC是否自动复位都在逻辑里显式加一个复位条件。比如用停止按钮的常开触点并联在定时器使能端确保每次启动前定时器都是清零状态。4.5 输入滤波与位逻辑的“抖动”问题物理按钮在按下和松开时触点会有几毫秒到几十毫秒的抖动。如果PLC的输入滤波时间设置得太短就会把抖动当成多次按下导致逻辑误动作。这个问题在计数器逻辑里特别明显按一次按钮计数器加了3。解决方法是设置输入滤波时间。大多数PLC都支持在每个输入点的属性里设置滤波时间通常设为10ms到20ms。如果PLC不支持单独设置可以在程序里加一个延时确认逻辑T0 I0.0 (延时20ms) M0.0 T0这样I0.0必须持续为1超过20msM0.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为例。新建程序段开始画梯形图。第一步定义变量。在变量表里添加输入输出变量变量名地址数据类型注释StartBtnI0.0BOOL启动按钮StopBtnI0.1BOOL停止按钮FaultSigI0.2BOOL故障信号Motor1Q0.0BOOL电机1输出Motor2Q0.1BOOL电机2输出RunFlagM0.0BOOL运行标志第二步画启保停逻辑。在程序段里先画启动按钮的常开触点并联运行标志的常开触点再串联停止按钮的常闭触点和故障信号的常闭触点最后接运行标志线圈。|----[ 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 多台设备联锁的逻辑设计单台设备的位逻辑相对简单多台设备联锁就复杂多了。我以一个实际项目为例一条输送线有上料机、传送带、下料机三台设备。启动顺序是上料机→传送带→下料机停止顺序是下料机→传送带→上料机。任何一台设备故障后续设备立即停机前序设备延时停机。这个逻辑用位逻辑实现需要定义以下变量变量名地址注释StartBtnI0.0启动按钮StopBtnI0.1停止按钮Fault1I0.2上料机故障Fault2I0.3传送带故障Fault3I0.4下料机故障FeederQ0.0上料机输出ConveyorQ0.1传送带输出UnloaderQ0.2下料机输出SysRunM0.0系统运行标志FeederDoneM0.1上料机完成标志ConveyorDoneM0.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和ST8.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为TRUEMotor2为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编程的门口不是因为他们不够聪明而是因为他们跳过了位逻辑这个必经之路。希望这篇内容能帮你把这条路走通。
阅读完成 · 觉得有帮助?