ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PLC编程思路进阶:星-角降压启动与32台变频器Modbus轮询

PLC编程思路进阶:星-角降压启动与32台变频器Modbus轮询 干了十来年现场调试带过的新人没有二十也有十五六个发现一个特别普遍的现象梯形图那些基本指令个个背得滚瓜烂熟可一碰到真实项目就发懵。给他一个一拖三的启动柜或者一句32台变频器走485轮询光标在屏幕上闪半天最后憋出来一段能跑但根本没法改、没法查、没法交给别人的程序。说到底缺的不是指令而是PLC编程思路。这篇文章我不打算讲什么软元件编号规则也不打算复述手册。我想把拿到需求之后脑子里那套推演过程摊开来讲——从工艺表怎么翻成I/O清单到状态机怎么落地再到一台PLC带32台变频器时通讯怎么排班、数据怎么映射、出错怎么兜底。中间会拿一拖三星-角降压启动和32台变频器Modbus轮询这两个非常典型的实例把每一步的思路和参数计算都写透。不管你现在是刚学完西门子S7-1200基础课还是已经能独立做汇川、三菱FX、欧姆龙的小项目只要你想把程序写得别人能看懂、三年后自己还能改这篇应该都能给你点东西。1. 拿到需求先别开软件PLC编程思路的四个前置动作我带新人的第一课永远是这句写程序的时间最多占整个项目的三成剩下的七成都在纸上。这段话听起来像老生常谈但它直接决定了你后面是花两天还是花两周。1.1 把要它干什么翻译成三张表绝大部分现场需求业主给你的是口头描述或者一张粗糙的工艺图按下启动电机先星接降压启动几秒后切成角接运行按停止就全停。就这么一句话你要把它拆成三张表。第一张是动作时序表。按时间轴把每个执行机构的动作状态列出来哪个先动、哪个后动、中间隔多久、谁和谁绝对不能同时动。星-角这个例子里时序表就三行0秒主接触器和星接触器同时吸合T秒星接触器先断开T0.1秒角接触器再吸合。这0.1秒就是后面硬互锁和死区时间的来源。第二张是I/O分配表。输入按按钮、限位、故障信号分组输出按接触器、指示灯、阀分组。分配表不只是记个地址还要标出信号类型常开还是常闭是24V源型还是漏型是NPN传感器还是PNP传感器。现场至少有三分之一程序明明没错却不动作的故障根子就在这张表没标清楚。PLC晶体管输出分NPN和PNP这件事新手最容易栽买的时候看型号后缀接线的时候看公共端接正还是接负别等柜子装完才发现传感器和输入模块对不上。第三张是中间变量和标志位表。哪些是运行标志哪些是故障锁存哪些是步序号。这张表看着虚实际上是你程序可读性的骨架。我自己的习惯是M0.0~M0.7留给系统级标志急停、复位、模式M1.0之后按工位分区块每个区块预留20个点中间空着的部分永远不占用方便后期加东西。这三张表在手你打开博途或者GX Works2的时候其实只是抄写而已。1.2 状态机写法把边想边写这个坏习惯掐死热词里有个plc编程状态机写法说明不少人都意识到了这个问题。我把它说得再直白一点经验法是想到哪写到哪状态机法是先定义所有可能的状态再定义状态之间怎么跳。交通灯是理解状态机最便宜的例子。东西向绿灯、东西向黄灯、南北向绿灯、南北向黄灯四个状态每个状态两个转移条件当前状态定时到状态机图一画出来程序几乎是自动生成的。真正复杂的设备比如电梯楼层请求、方向判定、开门保持、超时保护用经验法写出来的梯形图能堆到两百行还查不出问题用状态机拆主状态不超过十个每个挂两三个条件写起来反而轻松。三菱FX用STL步进指令西门子用GRAPH或者自己写整数步序号本质上是一回事。我特别推荐新手用整数步序号 CASE语句或者比较指令的方式起步而不是一上来就写一堆自锁。原因是步序号是显式的你在线监控的时候能直接看到现在走到第几步出问题一眼定位。自锁写多了程序是隐式的你只能靠经验去猜哪个逻辑把它顶掉了。1.3 三种写法的取舍什么时候用什么写法适用场景优点风险直接自锁经验法单台设备、动作少于5个上手快、代码短改需求时容易牵一发动全身步序号/STL步进法有明确先后顺序的流程易调试、易加步步数多了要画清楚否则乱跳状态机CASE多模式、多分支、带互锁结构清晰、易扩展前期设计耗时间我的实际选择标准很简单动作之间有强顺序关系的用步进动作之间是并行且互相约束的用状态机只有一两个动作的直接自锁别折腾。硬套状态机去做一个启保停跟用高射炮打蚊子一样维护的人还得先学习你的思路。1.4 先写异常再写正常这一条是我踩坑最多的。新手习惯先把正常流程写完能跑通了再回头加保护。问题是回头加的这部分往往加得到处都是最后散落在十几个网络里谁也说不清。正确的顺序是反过来先想清楚所有异常出口再写正常逻辑。以星-角启动为例异常出口至少包括启动过程中热继电器动作、运行中按停止、急停被按下、切换过程中接触器反馈超时、PLC上电时输出误动作。每一个出口都要在标志位表里占一个位置然后正常逻辑里所有转移条件都必须带上无故障这个前提。这不是洁癖这是你半夜不被电话叫起来的基础。2. 实例拆解一台PLC控制三台电机星-角降压启动热词里星-角降压启动主回路电路图请编写plc控制星角降压启动的梯形图程序这条是典型的课程设计题也是很多人第一次独立写程序的题材。我拿它做第一个实例因为它把顺序、互锁、定时、保护四件事全占了而且三台一起做能顺带讲清楚模块化和多重实例的价值。2.1 主回路和I/O分配先定下来星-角降压启动的核心原理不复杂电机有六个接线端子U1/V1/W1 和 U2/V2/W2启动时把U2/V2/W2短接成星点每相绕组承受的电压从380V降到约220V启动电流降到直接启动的三分之一左右转速上来之后再换成角接绕组承受全电压。所以每台电机要三个接触器主接触器KM1、星接触器KM2、角接触器KM3外加一个热继电器FR。必须先说清楚适用边界这是很多人忽略的只有额定运行电压380V、额定接法为角接的电机才能用星-角启动而且它适合风机、水泵这类轻载或空载启动的负载。重载启动、需要大启动转矩的场合比如带重载输送机、破碎机星-角降压反而可能启动不起来得换成软启动器或者变频器。另外切换瞬间的冲击电流仍然存在电网容量紧的场合也要慎重。I/O分配上三台电机如果共用一套启停信号输入点可以省很多地址名称类型说明I0.0启动按钮常开三台同时启动I0.1停止按钮常闭三台同时停止I0.2急停常闭硬线切断程序封锁I0.3~I0.5FR1~FR3常闭热继电器动作信号I0.6~I0.8KM1~KM3辅助常开接触器反馈可选Q0.0~Q0.2KM1/KM2/KM31号输出主/星/角Q0.3~Q0.5KM1/KM2/KM32号输出主/星/角Q0.6~Q0.8KM1/KM2/KM33号输出主/星/角这里有个细节值得说停止按钮和热继电器我用常闭输入。原因不是习惯是安全——常闭回路的导线断了、端子松了PLC读到的是停止设备停下来这是失效安全如果接常开断线读到的永远是正常隐患就埋下去了。急停更是必须走硬线直接切主回路接触器的线圈电源PLC程序里的急停只是辅助封锁不能作为唯一手段。2.2 梯形图分段为什么这样分我的分段方式是每台电机独立一段段内再按运行标志—星启动—切换死区—角运行四小段组织。这样做的好处后面讲多重实例的时候会体现出来现在先把单台的逻辑写清楚。// 单台电机星-角启动逻辑IEC风格梯形图文字化表达 // 1号机启动 I0.0 停止 I0.1 急停 I0.2 热继 I0.3 // 输出Q0.0 KM1(主) Q0.1 KM2(星) Q0.2 KM3(角) // 内部M10.0 运行标志 M10.1 星阶段 M10.2 角阶段 // M10.3 故障 T100 启动延时(8s) T101 切换死区(0.15s) Network 1 运行标志 置位/复位 I0.0 I0.1(F) I0.2(F) I0.3(F) M10.3(F) |----| |----|/|------|/|------|/|-------|/|----------( S ) M10.0 I0.1(F) 或者 I0.2(F) 或者 I0.3(F) 或者 M10.3 |----|/|---------|/|---------|/|---------| |--------( R ) M10.0 | | | ----------------------------( R ) M10.1 ( R ) M10.2 Network 2 星阶段启动主接触器 星接触器同时吸合 M10.0 M10.2(F) Q0.2(F) |----| |------|/|------|/|-----------------------------( ) Q0.0 M10.0 M10.2(F) Q0.2(F) |----| |------|/|------|/|-----------------------------( ) Q0.1 M10.0 M10.2(F) Q0.2(F) |----| |------|/|------|/|-----------------------------( S ) M10.1 Network 3 启动延时 M10.1 |----| |---------------------------------------[ TON T100, 8s ] Network 4 切换死区星接触器先断角接触器延后0.15s再合 T100.Q |----| |---------------------------------------[ TON T101, 0.15s ] Network 5 角运行阶段 T101.Q Q0.1(F) |----| |------|/|-------------------------------------( ) Q0.0 T101.Q Q0.1(F) |----| |------|/|-------------------------------------( ) Q0.2 T101.Q |----| |---------------------------------------------( S ) M10.2 ( R ) M10.1这段逻辑里有三个地方是新手最容易写错的我逐个说。第一星和角的互锁必须是双向的而且要在输出侧也做一遍。逻辑上Q0.1和Q0.2互锁只是第一道防线柜内KM2和KM3的辅助常闭触点还必须硬线互锁把对方的常闭触点串进自己线圈回路。原因很简单如果接触器机械卡死、或者触点粘连软件互锁是拦不住的那一刻就是相间短路柜子直接炸。我在现场见过一次损失不小从那之后我所有的星-角柜都强制加硬互锁。第二切换必须有死区时间而且死区不能太短也不能太长。电弧熄灭需要时间一般0.05~0.2秒我取0.15秒。太短星接触器电弧还没灭角接触器就合上去等于瞬间短路太长电机转速掉太多切换时的电流冲击反而更大等于白降压了。这个值按接触器容量和负载惯量微调不是拍脑袋定死的。第三主接触器在切换过程中不能断。你看上面的逻辑Q0.0在整个过程里一直是通的只有星和角在换。这一点极其重要主接触器一断电机就脱离电源开始自由停车再合上就是重新启动冲击比直接启动还大。很多课程设计的答案里主接触器跟着星接触器一起断这是错的。2.3 定时器参数怎么算而不是怎么猜启动延时T100取多少这不是随便填个5秒。经验公式是电机从静止加速到额定转速的95%左右所需的时间。工程上常用的估算方式是取电机功率对应的经验值——小容量7.5kW以下一般4~6秒中等容量15~55kW6~10秒大容量可以到15秒甚至更长。更靠谱的做法是看负载特性风机水泵类负载惯量大、加速慢取偏大值轻载机械取偏小值。判断取值的实测方法也很简单在切换瞬间用钳形表看电流。如果切换时电流接近甚至超过直接启动电流说明延时太短转速没上来如果切换时电流很小、切换很平滑说明可以适当缩短延时以提高效率。这个实测步骤我建议每次都做一遍比翻手册准。三台电机如果容量一致、负载一致可以共用一套定时器参数如果容量不同就必须分三组或者用多重实例把每台的参数独立存起来下面第4节详细讲。同时启动三台大电机这件事本身也要注意总启动电流是叠加的必须核算变压器容量和进线断路器。程序上能做的是分批启动比如1号机启动完成后延时3秒再启动2号机避免三台同时冲击电网。这个需求一旦提出来你就知道为什么程序结构要模块化了——用复制粘贴三份逻辑的做法改个延时就要改三个地方早晚出事。2.4 那些手册上不会写的星-角注意事项接触器容量选择上星接触器流过的电流只有主接触器的约三分之一理论上可以选小一号。实际中我一般还是选和主接触器同规格或者小一档因为切换瞬间的冲击电流和分断时的电弧都不小省这点钱不值当。热继电器的整定值按电机额定电流的1.0~1.1倍整定且必须接在角接触器回路侧也就是相电流位置而不是主回路上否则整定值要除以1.732很多现场接错了整定值一直按错的方式调。这个细节我在至少三个工地上纠正过。还有一个容易忽略的PLC上电瞬间的输出保持。有些老型号PLC上电时输出点会有短暂抖动如果接触器线圈功率小、动作快可能出现上电就启动的恐怖现象。解决办法是在程序里加一个上电初始化用一个只在第一个扫描周期接通的位把所有输出和标志位清一遍同时确保所有启动逻辑都以运行标志为前提而不是直接以按钮为前提。3. 从3台到32台多变频器Modbus通讯的程序设计思路plc控制32台变频器程序设计和一个西门子PLC与32个变频器modbus通讯控制是否可这两条热词问的是同一个问题一台PLC能不能带这么多从站。答案是能而且很常见但前提是你得把轮询这件事想明白否则写出来的程序会卡死、会丢数据、会在某一台变频器断线的时候整体瘫痪。3.1 为什么是RS485总线而不是模拟量或者逐台硬线先说选型逻辑。32台变频器每台要控制启停、给频率、读运行状态和故障码至少四五个信号。如果走硬线就是32×5160个I/O点加上模块、端子、线缆、线槽柜子得做成两个成本翻几倍而且接线和维护是噩梦——换一台变频器得对着一百多根线找。走模拟量也不行模拟量只能给频率和读反馈启停和故障还得硬线而且32路模拟量输出模块本身就很贵精度还受干扰影响。RS485走Modbus RTU是最经济合理的方案两根线手拉手串起来屏蔽双绞线一台PLC最多能带32个标准负载正好卡在临界点上。这里必须注意32台是RS485标准驱动能力的上限实际中如果你用的是普通收发芯片加上线缆长度和干扰32台往往跑不稳。经验做法是两个一是选用驱动能力更强的通讯模块或者加485中继器二是在变频器的通讯参数里把每台的负载特性考虑进去必要时分成两条总线各挂16台。分两条总线还顺带解决了一轮轮询太慢的问题上了两台通讯口就能并行轮询。3.2 轮询架构为什么不能让32台同时发Modbus RTU是主从结构同一时刻总线上只能有一对设备在说话。你如果让32台从站同时应答总线上的电平就会互相冲撞结果是全部乱码。所以必须由主站一台一台地问问完一台再问下一台这就叫轮询。轮询的实现方式我推荐用一个整数步序号配合CASE语句而不是用32个定时器硬堆。核心思路是这样的// 变频器轮询主状态机的简化框架ST语言 CASE #iStep OF 0: // 空闲等待使能 IF #bEnable THEN #iIndex : 0; #iStep : 10; END_IF; 10: // 发送第 iIndex 台变频器的读请求 #wSlaveAddr : 1 #iIndex; // 站号 1~32 #bReadReq : TRUE; #iStep : 20; 20: // 等待响应或超时 IF #bReadDone THEN #bReadReq : FALSE; #iErrCount[#iIndex] : 0; #iStep : 30; ELSIF #bReadTimeout THEN #bReadReq : FALSE; #iErrCount[#iIndex] : #iErrCount[#iIndex] 1; #iStep : 30; // 超时也往下走不卡死 END_IF; 30: // 数据搬运把接收缓冲写进对应变频器的数据区 #aFreq[#iIndex] : #wRecvBuf[1]; #aStatus[#iIndex]: #wRecvBuf[0]; #iIndex : #iIndex 1; IF #iIndex 32 THEN #iIndex : 0; END_IF; #iStep : 40; 40: // 写请求只在需要时发比如频率变化或启停指令 IF #aWrFlag[#iIndex] THEN #wSlaveAddr : 1 #iIndex; #bWriteReq : TRUE; #iStep : 50; ELSE #iStep : 10; // 无事可做直接进下一台 END_IF; 50: // 等待写完成或超时之后回到 10 开始下一台 IF #bWriteDone OR #bWriteTimeout THEN #bWriteReq : FALSE; #aWrFlag[#iIndex] : FALSE; #iIndex : #iIndex 1; IF #iIndex 32 THEN #iIndex : 0; END_IF; #iStep : 10; END_IF; END_CASE;这段框架里有两个设计意图必须讲清楚。第一超时也往下走。新手最容易犯的错是超时之后一直等结果一台变频器掉线整个轮询就停在那里另外31台全部失联。正确做法是超时计数后跳过让轮询继续转掉线的那台在后台重试。第二只有需要写的才发写请求。变频器的频率不会每轮都变如果每轮32台都读写一遍通讯周期直接翻倍没必要。3.3 通讯周期到底要多久把账算出来很多人判断能不能带32台靠感觉其实这个可以算。Modbus RTU每字节是11位1起始位8数据位1停止位无校验帧与帧之间需要至少3.5个字符时间的静默间隔。以读两个保持寄存器为例请求帧是地址1功能码1起始地址2数量2CRC28字节响应帧是地址1功能码1字节数1数据4CRC29字节。合计17字节。波特率单帧裸传输时间含静默间隔约2×3.5字符32台读一轮32台读写各一轮960017×11÷9600≈19.5ms≈28ms≈0.9s≈1.8s19200≈9.7ms≈18ms≈0.58s≈1.15s38400≈4.9ms≈13ms≈0.42s≈0.83s这个表信息量很大。首先9600波特率下读写各一轮要1.8秒意味着每台变频器的数据刷新率约1.8秒一次。这个速度用来做监控、做联锁、做启停控制是够的但如果你想用通讯做闭环调速1.8秒的响应延迟完全不可接受。这就是为什么工业现场控制频率通常靠变频器自身的PID闭环PLC只负责给目标值和读状态而不是让PLC去算PID再通过485下发。想清楚这一点你的程序架构就不会走偏。其次波特率不是越高越好。38400在总线长、干扰大、变频器多的场合误码率会上升实际中我一般用19200兼顾速度和稳定。上表算的是理想情况实际还要加上变频器的内部处理时间一般每台再加5~15ms。所以32台按19200算实际一轮读写大约1.5秒我的经验值和理论值基本吻合。3.4 数据映射与分段偏移量热词里有plc分段偏移量这是做多台设备数据管理必须掌握的概念。32台变频器每台要存运行状态、输出频率、输出电流、故障码、给定频率五个字。如果给每台单独定义一堆变量名写32套程序能写到你怀疑人生。正确的做法是用数组ARRAY 结构体STRUCT按索引寻址。西门子里可以这样定义TYPE UDT_VFD STRUCT wStatus : WORD; // 状态字位0运行 位1正转 位3故障 wFreqOut : INT; // 输出频率单位0.01Hz即 5000 50.00Hz wCurrent : INT; // 输出电流单位0.1A wFaultCode: WORD; // 故障码 wFreqSet : INT; // 给定频率单位0.01Hz wCtrlWord : WORD; // 控制字位0启停 位1复位 bOnline : BOOL; // 通讯在线标志 iErrCnt : INT; // 连续错误计数 tWatchdog : TON; // 单机看门狗 END_STRUCT; END_TYPE // 数据块中定义数组 VAR aVFD : ARRAY[0..31] OF UDT_VFD; END_VAR访问第7台变频器的频率就是aVFD[6].wFreqOut。分段偏移量的含义正在这里如果不用结构体而用连续的WORD数组第 i 台的第 k 个参数地址就是基地址 i×每台字数 k。用结构体之后编译器替你算了偏移你只需要关心索引出错的概率大幅下降。程序里所有轮询、报警、趋势、组态画面都可以用循环和索引来批量处理32台和3台在代码量上没有本质区别——这是模块化最直接的收益。数据类型的坑这里要提醒一句变频器返回的频率、电流大多是缩放过的整数不同品牌缩放系数不一样。我接触过的几类有的频率单位是0.01Hz有的是0.1Hz电流有的是0.1A有的是0.01A。换算错了画面上显示输出频率500.00Hz找问题能找一下午。所以每接一个新品牌的变频器第一步永远是拿一台单独接上手动读写几个寄存器把缩放关系用实测确认下来别信手册上的通常。另外INT是16位带符号最大32767如果某个参数可能超过这个范围就得用DWORD这也是数据类型应用里最常见的翻车点。3.5 断线、误码和恢复这部分决定项目能不能验收轮询能跑起来只是及格能处理异常才是合格。看门狗机制。每台变频器配一个自己的定时器或者用统一的轮询计数做软件看门狗如果在预定周期内没有成功通讯就把bOnline置假同时在上位画面报警并允许组态画面显示离线。离线之后要不要停机这取决于工艺如果是风机水泵这类一般允许单台离线继续运行并报警如果是联动的生产线通常要触发停机保护。这个策略必须在设计阶段和业主确认清楚写进程序。重试策略。连续错误计数达到3次我一般会做两件事一是判定这台离线二是把它的站号加入重点重试队列在正常的轮询间隙额外多问一次。这里注意别做成死循环重试同一台那样只会拖慢其他31台。退避重试的思路更稳妥前3次正常速度重试之后降低频率比如每轮只试一次。误码的识别。Modbus RTU的CRC校验本身就是一道防线返回CRC错误的帧直接丢弃并计入错误。但还有一种情况是帧超时——从站返回的数据长度不对比如响应帧应该是9字节实际只收到5字节。这种半截帧如果不处理后面的解析就会错位。所以接收缓冲区的长度校验必须做不能只看收到数据了就当真。上电顺序的影响。变频器上电到通讯就绪有几百毫秒到几秒不等的初始化时间PLC如果在变频器还没准备好的时候就开始轮询会连续报错。我的习惯是程序启动后延时10秒再使能通讯同时每个变频器的错误计数在连续成功3次之后自动清零这样即使刚开始报错稳定之后也能自动恢复。3.6 硬件层面的几个硬要求软件写得再好线接错了也是白搭。RS485这块有几条必须遵守的规矩。拓扑必须是手拉手菊花链绝对不能星型分叉。星型接法会让阻抗不连续反射严重短距离可能侥幸能用超过50米必然出问题。终端电阻。总线两端各接一个120Ω终端电阻中间节点不要接。总线长度短、节点少的时候可以省32台这种规模强烈建议加上。屏蔽层单端接地。屏蔽双绞线的屏蔽层只在PLC侧接地变频器端悬空或用高频电容接地。两端都接地会形成地环流引入的干扰比不接还大。A/B极性不要接反。A接A、B接B同一根线上的所有设备保持一致。这个错误的表现很典型完全没响应也没有报错帧。接线时用不同颜色的线区分做端子时按统一顺序排列能让后面排查省一半时间。共地与隔离。变频器和PLC的参考地如果电位差大会烧通讯口。选带隔离的通讯模块或者至少把485的参考地GND连起来是保护设备的低成本手段。另外通讯线和动力线必须分开走线槽平行距离越短越好交叉时尽量垂直交叉。这些是电气安装的基本功但恰恰是通讯类故障最常见的根因。站号规划。32台变频器站号设为1~32不要用0和超过247的号。改站号这一步最枯燥也最容易漏建议做一张表贴在现场标注每台设备的站号和安装位置后面维护的人会感谢你。4. 程序结构的组织让32台设备和3台设备一样好维护前面讲了两个具体实例的写法这一节我想讲更上层的东西——代码怎么组织。这部分在教程里几乎没人讲但它是能跑的程序和能交付的程序之间的分界线。4.1 分层结构把不同性质的事情分开放我现在的程序基本都是四层结构从上到下是调度层、工艺层、设备层、通讯层。这个划分不是学术概念是为了让修改局部化。调度层管模式切换、启停总控、批次逻辑、报警汇总。这一层只调用下面几层的接口不关心底层细节。工艺层管工序、步序、联锁条件。星-角那个例子的启动—星—切换—角就属于这一层。工艺层的变化最频繁业主今天说延时5秒、明天说改成8秒改的都是这里。设备层是每个设备电机、变频器、阀、气缸的功能封装。变频器的启停、给频率、复位故障、故障判断都封装成一个功能块通过多重实例调用32次。这一层几乎不随工艺变化。通讯层管Modbus的收发、轮询状态机、数据映射。它是所有变频器的公共通道独立出来之后即使以后从Modbus换成EtherNet/IP或者Profinet改动也局限在这一层。分层的价值在于故障定位。画面显示某台变频器频率不动你先看通讯层有没有数据有数据说明通讯没事再看设备层有没有把频率写进去写了说明是工艺层没给指令这样三步定位比在两千行程序里翻要快得多。4.2 多重实例32台设备只写一份逻辑西门子plc多重实例这条热词说的正是这个。做法是把设备逻辑写成一个功能块FBFB内部用静态变量Static保存自己的状态然后在调用的时候给每个实例分配一块背景数据块。32台变频器就调用32次同一个FB各自有独立的背景数据块互不干扰。好处非常直观改一处逻辑32台同时生效。比如业主忽然要求通讯离线时自动停机你在FB里加两行改一次就够了。如果用复制粘贴写32份你得改32次而且必然有漏掉的。同时程序总行数大幅下降在线监控的时候每台设备的背景数据块可以单独打开看它自己的状态和错误计数非常清晰。用多重实例还有个小技巧FB的接口尽量精简与工艺相关的参数走输入引脚设备自身的状态走静态变量。我见过有人把定时器预设值也做成静态变量然后在外面逐个赋值结果32个值散落在32个地方改起来还是麻烦。正确做法是把这类可能按设备调整的参数统一放在一个数组里初始化的时候批量灌进去。4.3 资源占用、扫描周期与在线调试博途中查看plc资源使用情况也是被高频搜索的说明很多人踩过资源不够的坑。程序跑着跑着CPU报存储器不足或者扫描周期超限往往是因为FB背景数据块太多、或者循环里做了耗时的操作。我的经验值是这样S7-1200这类小型机装载存储器和工作存储器的余量建议留30%以上扫描周期方面32台变频器轮询这种应用如果每轮都在一个扫描周期里把所有32台的数据搬运一遍扫描周期会被拉长。做法是把搬运逻辑拆开每台轮询完成后只处理它自己那一条数据分摊到多个扫描周期里扫描周期就能保持平稳。在线调试上有几个实用手段。强制表和监控表的区别要分清监控表只是看值强制表会真的改写I/O用不好会出安全事故——我要求所有现场人员在强制输出之前必须先确认输出回路上没有人工作。交叉引用是查双线圈的利器如果同一个Q点被两处赋值程序里就会互相打架运行表现是输出时好时坏交叉引用一点就现原形。扫描周期监控也要养成习惯正常项目应该稳定在几毫秒到几十毫秒如果突然跳到一个很大的值通常是有循环或者某个功能块被异常反复调用。关于现在流行的AI代码生成我的态度是可以用但要清楚它的边界。用它生成一段CRC校验、一段字符串解析、一段坐标变换效率确实高因为这类代码逻辑确定、边界清晰你看着能验证。但用它生成工艺逻辑是非常危险的——AI不知道你的设备在什么工况下会卡料不知道哪个动作绝对不能同时发生也不知道你的安全回路是怎么设计的。我一般的用法是把它当成帮我写样板、帮我查语法最终的安全和工艺逻辑一定自己过一遍尤其是所有涉及互锁和急停的部分必须逐行确认。4.4 变量命名和注释给三年后的自己留路这一条听起来是小事但它决定了一个项目能不能被别人接手。我的命名规则基本固定输入用I_开头加功能I_StartBtn输出用Q_开头Q_KM1中间标志用M_定时器用T_数据块用DB_或者按用途命名。中文注释只写为什么不写是什么——// 星接触器断开这种注释没有价值// 星角切换死区防止电弧未熄弧造成相间短路才有。还有一条程序版本必须和图纸、HMI、变频器参数表一起归档。我见过太多程序是最新的图纸是三年前的这种局面修一次设备要花两倍时间。我的做法是在程序开头建一个版本数据块记录版本号、日期、修改人和修改内容每次改完必须更新并且导出一份带日期的备份。这个习惯看着麻烦但在你半夜被叫到现场、需要回退到上一个版本的时候你会庆幸自己做过。5. 常见问题与排查实录这一节我把这些年现场遇到的高频问题整理成速查表都是能直接照着查的。5.1 通讯类问题速查现象可能原因排查动作完全无响应无错误码A/B接反、终端电阻缺失、站号不对用串口调试工具单独连一台确认能通部分设备通、部分不通站号重复、线缆中间接头氧化、分叉拓扑逐个断开排查确认手拉手连接通讯时通时断屏蔽层两端接地、动力线与信号线同槽检查接地和走线加装隔离模块频繁CRC错误波特率不一致、校验位设置不同、干扰大逐台核对通讯参数降低波特率试有响应但数据不对寄存器地址偏移算错、缩放系数错用厂商调试软件读同一寄存器比对通讯正常但变频器不动作控制字位定义不对、需要先给使能位核对变频器手册的控制字位表这里我要专门提醒一个反直觉的点波特率不一致时有时候看起来能通。原因是数据位恰好凑出了能识别的帧。所以参数核对不能靠能通就行要逐台用统一参数表核对写下来打钩。5.2 逻辑类问题速查输出时有时无像是有东西在抢。九成是双线圈。用交叉引用查同一个输出点或同一个标志位被赋值的地方超过一处的都要重点看。定时器明明该到时间了却不动。三个可能定时器的使能条件断了定时器在某个条件下被复位了定时器的时间基准设错了比如把100ms基准当成10ms用。西门子里定时器的时间是跟着TON指令的PT引脚走的三菱的T0是100ms基准、T200是10ms基准这种差异在跨品牌移植程序的时候最容易出错。边沿检测失效。上升沿检测依赖上一个扫描周期的状态如果这个信号是在同一个扫描周期里被程序刚改写的边沿就不会触发。这种自己改、自己检的写法必然出问题正确做法是先检测原始输入再进行处理中间用一个中间位过渡。按下按钮没反应但监控里输入点是亮的。检查程序里这个输入点是不是被多处使用并且有位置把它置位/复位了检查输入滤波时间是不是太长有些模块可以设输入滤波默认几毫秒改大了会吃掉短脉冲检查是不是硬件上这个按钮接到了别的公共端。扫描周期突然变长。查循环、查字符串处理和浮点运算是否在每周期都执行、查是否有FOR循环的次数设得过大。32台变频器的数据刷新如果全挤在一个周期做也会明显拉长周期分包处理就能解决。5.3 硬件与干扰类问题PNP/NPN传感器配PLC输入。源型输入公共端接0V通常配PNP传感器漏型输入公共端接24V通常配NPN传感器。买之前确认PLC输入类型确认传感器输出类型两端对齐。我见过一次现场装了30多个传感器全部接错改线改了一整晚。晶体管输出负载能力。PLC晶体管输出单点一般0.5A直接接接触器线圈很容易超出。长时间超载会烧输出点正确做法是加中间继电器用小电流控制大电流。线圈两端还要并续流二极管或者RC吸收抑制反向电动势。干扰导致的误动作。变频器、伺服、接触器都是干扰源。除了走线隔离还在PLC电源前面加隔离变压器或者滤波器模拟量输入端加屏蔽和滤波。这些硬件上的投入比在程序里加一堆滤波要划算得多。5.4 跨软件与跨品牌的那些差异会用西门子不代表会用三菱反之亦然。的差别不只是指令名字西门子的DB块、FC/FB、优化块与非优化块的寻址方式完全不同三菱FX的M、D、T寄存器寻址是直接的欧姆龙用PLC地址和符号两种方式。跨品牌移植的时候最容易出问题的就是数据寻址和定时器基准其次是数据类型的长度和符号性。我一般建议同一家工厂尽量统一品牌实在要混用就在中间加一层信号映射表把不同品牌的地址统一映射到一套逻辑命名上写程序的时候只用逻辑名硬件地址只在一个数据块里出现一次。这样以后换品牌改一个块就够了。上位机侧同理HMI和SCADA的变量关联WINCC也好、MCGS也好都建议通过中间变量关联而不是直接连接底层I/O地址否则底层一改画面上几十个点全废。另外提一句仿真和在线调试的区别。现在不少平台有仿真功能逻辑验证很方便但仿真跑通不等于现场能跑因为仿真不模拟真实的干扰、不模拟接触器的机械动作时间、不模拟通讯的误码。我要求所有新程序在现场必须先做三件事不带负载单独测输出动作、带负载空转测逻辑、带料试运行。这三步做完再谈交付。6. 几条我压箱底的实操心得最后我想分享几个不成体系的习惯都是踩坑之后慢慢养成的写不进任何教程但确实能省事。程序里我永远会保留一个调试模式。用一个只在维护时才能打开的开关打开之后各个步骤的延时自动缩短到原来的十分之一。原因很简单现场调试一个8秒的启动流程你等一遍要8秒改一次参数再等8秒一天下来光等就浪费几小时。有了调试模式动作快放逻辑验证的效率翻倍正式运行前关掉就行。当然这个开关要设密码或者放在维护菜单里不能让操作工随意动。数据块我习惯按每台设备一个结构体数组的方式建并且在数组里预留几个空的成员比如iSpare1、wSpare2。这个习惯纯粹是被逼出来的项目交付之后业主总会加需求加一个运行小时计、加一个启动次数统计如果数组里没有预留我就要去动数据结构一改就得重新下载整个数据块现场停机不说还可能把已积累的累计数据清零。预留几个成员加功能的时候直接往里填风险小很多。还有一个是关于什么时候不该用新技术。现在平台的功能越来越花什么自定义数据类型、面向对象、程序模板看着很香。但你的程序将来可能要交给一个只会梯形图、用惯了传统写法的维护电工。你写一堆高级语法出了小问题他看都看不懂最后还是要你去。我的一般原则是结构和思路可以高级具体到单条逻辑的实现尽量用最朴素的方式。一个自锁加一个定时器能解决的问题就别写成带方法的函数块。关于不同品牌变频器混用的场景我也说两句。汇川、ABB、施耐德、西门子的变频器Modbus寄存器映射基本没有统一的说明书厚薄也不一样。我的做法是每接一个新品牌先花半天时间把用到的十几个寄存器整理成一张对照表包括地址、功能、数据类型、缩放系数、读写权限然后按这张表去写参数映射。这张表存下来下次遇到同一个品牌直接复用几年下来就是一本自己的手册比任何资料都好用。现场动手之前有件事我从来不打折扣确认输出回路上没人在干活。强制输出、试动作、下载程序任何一个动作之前都要喊一声、看一眼。我见过因为程序下载时输出瞬间复位导致设备误动作的情况幸好没造成机械损伤。程序上的保护做得再厚物理层面的确认永远不能被替代。写了这么多落到一句话PLC编程真正的难点从来不是记住多少条指令而是你有没有在动手之前把设备的每一个状态、每一种可能的意外都想清楚并且把这份想清楚的结果用别人能看懂的方式写下来。指令会过时型号会换代这套推演的方式不会。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进