搞了十来年自动化产线项目,我越来越觉得一个很反直觉的事实:真正拉开工程师差距的,往往不是会不会写某个指令,而是程序整体能不能扛住时间。现场设备一多、联锁一复杂,那种把所有逻辑堆在OB1里的梯形图,第一版跑起来确实爽,可三个月后要加一台设备、换一个触摸屏、改一段工艺,你看着两万行程序,真的会头皮发麻。都说S7-1500要模块化编程,但“模块化”这三个字落到博途里到底怎么拆、FB和FC怎么分工、DB怎么规划、通讯怎么轮询,能给出清晰答案的人不多。这篇就把我在生产线自动化项目里的模块化打法完整梳理一遍,从OB架构到功能块封装,从32台变频器的Modbus轮询,到飞剪凸轮、星角启动、伺服电子齿轮比这些高频工艺块,再到调试现场的排查姿势,适合正在做S7-1500项目、想从“程序能跑”进阶到“程序好维护”的工程师参考。
1. 模块化编程的整体设计思路与工程收益
1.1 模块化编程到底解决了什么
先说一个我自己的经历。早些年做一条半自动装配线,30多个工位,电机、气缸、传感器加起来上百个点位。当时仗着年轻,程序按工位顺序往下写,设备动作全部串在一个OB1里,结果联调阶段改了A工位的时序,B工位莫名其妙跟着乱。后来老工程师帮我重构,把所有设备抽象成“驱动块”,每个电机、气缸都封装成独立的FB,主程序只做调用和联锁。重构完不到一周,现场调试速度反而比之前快了一倍。
这件事让我彻底想明白,模块化不是代码洁癖,它解决的是三个最实际的工程问题。
第一是并发风险。生产线不是单机设备,各个工位之间既有物理顺序,又有安全联锁。集中式程序最怕的就是“某一段逻辑里改了别人用的中间变量”,模块化用接口隔离数据,每个功能块只通过形参交换信息,从机制上避免串数据。
第二是调试效率。现场晚上十点打电话说设备停了,你在线连上CPU,如果程序是模块化的,直接看哪个FB处于故障状态、哪个DB的使能位是0,几分钟就能锁定方向。如果是几千行的平面梯形图,光是翻程序找变量就要花半小时。
第三是复用性。同一类设备的功能块,换条产线基本可以原封不动拿过去用。我手里这套电机/阀门FB,已经跟着我搬过七八个项目,只改硬件地址和工艺参数,不需要重新写逻辑。
用生活里的话说,集中式程序就像炒一大锅乱炖,所有食材丢进去,铲子一翻全混在一起。模块化则是分工明确的厨房:切菜的只管切,配菜的只管配,炒菜的只管炒,每个环节有标准的交接盘,哪天想换配菜方案,不用把整个厨房推翻重来。
1.2 先搭骨架:OB架构与程序分区
模块化不是上来就写FB,硬件组态完之后第一件事是规划任务架构,也就是OB的分配。很多项目一个OB1走天下,主循环里塞满所有东西,这恰恰是最需要避免的。
我在S7-1500项目里常规的OB分配大致是这样:
| OB | 用途 | 说明 |
|---|---|---|
| OB100 | 启动初始化 | 上电给机器人/夹爪回原点标志、复位输出、装载配方 |
| OB1 | 主循环 | 只做设备调度和逻辑调用,不写具体的设备细节 |
| OB35 | 周期中断 | 按工艺需要设100ms或50ms,跑PID、轴插补、温度调节这类需要固定周期的任务 |
| OB40/OB42 | 硬件中断 | 编码器高速计数、飞剪切断信号、急停回路这些必须立即响应的信号 |
| OB83/OB86 | 诊断中断 | DP从站/Profinet IO设备掉站的捕捉 |
| OB121/OB122 | 编程错误/IO访问错误 | 防止程序直接停机 |
OB1里我给自己的要求是:只保留FC调用、FB调用和关键联锁判断。具体到程序段,我习惯把用户程序分成几个区,每个区对应一段注释:
- 第一区:IO映射。把所有物理IO映射到统一的DB里,程序内部不直接读I点、不直接写Q点。
- 第二区:通讯数据处理。Modbus、Profinet、视觉来的数据先落到通讯DB,再做有效性校验。
- 第三区:设备功能块调用。每个设备一行CALL,像流水线一样排下去。
- 第四区:工艺联锁逻辑。工位间互锁、安全回路、配方切换。
这样做的好处是,你打开程序,按注释就能定位到任意一个功能域,而不是像翻字典一样漫无目的地找。S7-1500的博途环境对这种方式支持得特别好,OB和FB都支持符号名,项目树里一眼能看出程序结构。
1.3 数据先行:UDT与DB规划
我见过不少工程师,功能块写得挺顺,但数据块就是一张扁平的List,几百个变量堆在里面,没有结构、没有命名规范。这种DB到了后期,修改地址时真的会疯掉。
模块化编程里一定要养成UDT先行的习惯。
UDT(User Defined Type,用户自定义数据类型)是博途里非常实用的东西。你可以把一台电机抽象成一个数据结构,包含命令字、状态字、反馈、故障代码、运行时间、设定速度、保护参数,这样所有电机相关的变量就有了统一的“身份证”。建立UDT之后,在全局DB里直接声明几十个“电机”类型的变量,每个变量自动带出整套结构。后续程序里想扩展某个字段,改一次UDT,整个DB的结构跟着变,非常爽。
我的DB规划大致分几个独立块:
- DB_IO_Mapping:硬件IO映射区,每一路DI/DO/AI/AO都有注释,方便接线查点。
- DB_Device:设备数据区,用UDT批量建,电机、阀门、气缸、模拟量设备全在这里。
- DB_HMI_Interface:触摸屏/上位机接口区,所有HMI要写的设定值、要读的状态值集中管理。
- DB_Recipe:配方区,不同产品的工艺参数。
- DB_Alarm:报警管理区。
- DB_Comm_Buffer:通讯数据缓冲区,Modbus、TCP、视觉数据都先进这里。
命名方面我给自己定的规范是:全局DB用“DB_”前缀,FB用“FB_”前缀,FC用“FC_”前缀,接口结构用“TYPE_”前缀。看起来简单,但坚持一年后,团队协作时基本不需要问“这个变量在哪”,光看名字就能判断位置。
2. 核心功能块的设计与封装要点
2.1 FB还是FC:有状态就FB,无状态就FC
很多入门资料会告诉你FB带背景DB、可以存静态变量,FC没有。但对实际项目来说,选型标准应该更简单:这个功能块内部有没有记忆状态、需不需要在多次扫描之间保持数据。
电机控制就是典型的需要FB的场景。电机从启动命令到反馈确认,有一个过程,中间涉及启动延时、故障存储、运行累计时间,这些都必须靠静态变量保持。阀门、气缸、PID回路、伺服轴同理。
而像模拟量工程量换算、Modbus报文组包、ASCII码转实数、报警文本拼接这种纯计算逻辑,输入进来算完就出结果,不保存历史状态,用FC更合适。FC没有背景DB,不占用保持性存储,调用也轻,适合做工具函数。
一个工程上容易被忽视的点:FB的接口里,输入参数和输出参数尽量只通过形参交换数据,少直接读写全局DB。如果你在FB内部到处访问外部DB,那这个FB和外部程序还是耦合在一起,换项目时根本搬不走。我见过把“电机FB”里直接写死了“DB_Device.Motor1.Run”这种访问方式的,这样的模块化就是假模块化。
真正好的做法是:调用FB时,先把想控制的电机结构指针传给FB,FB内部全部基于输入/静态数据操作。这样同一个FB实例化几十次,每一个电机都是独立的一套数据。
2.2 电机、阀门类设备块的接口设计
以最常用的电机FB为例,我的接口一般这样设计:
- 输入:设备编号(诊断用)、启动命令、停止命令、故障复位、本地/远程切换、允许运行条件、启动允许时间/停止允许时间。
- 输出:运行反馈、故障状态、本地/远程状态、运行累计时间、当前命令字。
- 静态:内部延时定时器、故障梯形图状态、上电复位标志。
逻辑上,FB内部自动完成命令与反馈的互锁。比如启动命令来了,先判断是否有故障、是否允许运行、是否在本地模式,都满足才输出启动;然后等反馈,超过设定时间没反馈就置“启动超时故障”。停止命令来了,输出停止,同样等反馈。
这套逻辑写完一次,后面所有项目里的电机都调用这个FB,只需要把不同的IO映射地址和参数传进去就行。曾经有个项目,产线上有六十多台电机,我就是靠这一个FB反复实例化,把程序写得极其整齐。
阀门FB的逻辑类似,但要注意阀门有“开命令/关命令”双命令,而且很多阀没有中间位置反馈,只能靠开到位/关到位两个限位判断状态。我在阀门FB里会额外做“既不在开位也不在关位”的报警,这种半途状态往往是现场“涨死”阀门的先兆,非常值得关注。
2.3 手自动切换、模拟量归一化与HMI接口DB
手自动切换是产线项目里写烂了又必须写对的功能。核心问题是:切换瞬间输出不能跳变,否则执行机构会被猛打一下。解决思路是让手动输出和自动输出都先过一个跟踪逻辑,切换那一刻将目标输出置为当前实际输出,再做无缝过渡。
用S7-1500写的话,可以在FB里面用两个变量:Man_Output和Aut_Output,手自动切换信号做选择。具体实现时:
- 自动模式下,程序实时把
Man_Output跟随为Aut_Output,保证切换到手动时输出不跳。 - 手动模式下,程序实时把
Aut_Output跟随为Man_Output,保证切回自动时不跳。
模拟量归一化也是高频场景。S7-1500里直接用NORM_X和SCALE_X,四行搞定:原始值→归一化0.0~1.0→缩放成工程量。但千万不要在每个FB里各写一遍,我习惯写一个FC_ANormScale公用函数,传入原始值、量程上下限、数据格式,返回工程值。这样后面所有温度、压力、流量通道都统一走它,改起量程来只需改DB参数。
HMI接口这块,我强烈建议单独建一个HMI接口DB,不要直接让触摸屏映射设备DB的背景地址。原因有两点:一是HMI和PLC程序频繁交互,直接访问背景DB会把程序结构暴露给HMI,后期改名牵一发动全身;二是第三方触摸屏(比如昆仑通态)访问S7-1500优化访问的DB时往往麻烦,独立接口DB可以更灵活地处理地址映射。
2.4 顺启逆停与星角启动的模块化写法
热词里有人问“S7-1200顺起逆停”怎么写,这其实是模块化编程很好的教学案例。顺启逆停的意思是:多台设备按顺序启动、按相反顺序停止。如果是集中式梯形图,你可能会写一大堆置位复位。模块化做法是:把所有设备抽象成数组,用数组下标做启停队列。
在FB里定义一个设备数组和两个指针(启动索引、停止索引)。每次启动命令来了,按下标从小到大输出启动,每个设备启动完成后自动切换下一个;停止时从大到小逐个停。这个逻辑写成一个FB,输入设备数量和每台设备的启动/停止字,后面扩容到十几台设备,只需要改数组长度。
星角启动这个经典电路,同样适合封成FB。这个第4章我会专门讲,这里先提一点:模块化的关键是“时序参数化”,星形到角形的切换时间、星形接触器断开后的安全等待时间,都应该做成FB的输入参数,而不是在梯形图里写死定时器。这样现场调整不同功率电机时,直接改调用参数即可,不用改程序内部逻辑。
3. 一台S7-1500管理32台变频器的通讯实战
3.1 通讯架构怎么选:RTU直连、网关还是Modbus TCP
热词里有个典型问题:一台西门子PLC和32个变频器Modbus通讯控制是否可行。我的回答是可行,但架构要选对。S7-1500的情况和S7-200 SMART不一样:1500本体不标配RS485串口,如果所有变频器都是老式RS485接口,你需要额外加串口通信模块或通过串口服务器转Profinet/TCP接入。所以在方案阶段,一定要先确定变频器的通讯接口。
表格里这三种方案我都实际用过:
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| S7-1500 + CM串口模块(RTU) | 免中间设备、延迟低 | S7-1500配串口模块成本不低,且RS485布线规范要求高 | 变频器数量少、距离近、必须是485链路 |
| RS485网关转Profinet | 兼容存量老设备、接线独立 | 多一层设备,需要额外调试网关配置 | 现有产线改造、变频器都是485口 |
| 全部走Modbus TCP | 布线简单、轮询快、调试方便 | 要求变频器网口版本 | 新上项目,条件允许时优先选 |
如果项目还没采购设备,我个人极力推荐第三种。走Modbus TCP,S7-1500直接用MB_CLIENT/MB_SERVER指令,不需要额外硬件,轮询响应速度比RS485快一个数量级,后期排查还不用跑到现场摸屏蔽层。32台变频器全走TCP,只要网络划分合理,完全没压力,每秒刷新几十个寄存器是很容易实现的。
3.2 轮询表设计与MB_CLIENT/MB_MASTER的核心写法
Modbus通讯里最忌讳的就是“一窝蜂把32个从站的发送指令全部塞在一个扫描周期里”,通讯会乱。正确思路是做轮询状态机:每一时刻只发起一个从站的读写,完成后切换到下一个,如此循环。
用Modbus TCP时,我会先建一张轮询配置表,存到DB里:
- 从站编号
- 功能码(03读保持寄存器、06写单寄存器、16写多寄存器)
- 寄存器起始地址
- 数据长度
- 数据映射到哪个缓冲区
- 上次通讯时间戳
- 错误计数
然后写一个轮询FB,核心逻辑是:当前有没有请求在等待?没有的话,从轮询表里取当前索引,构建MB_CLIENT请求;有的话,检查MB_CLIENT的DONE和ERROR状态,完成后索引加一;循环到表尾再回到开头。
这里有一个项目经验:不要用一个MB_CLIENT实例反复建连断开,那样效率极低。要始终保持连接,用REQ的上升沿触发一次读写。S7-1500的MB_CLIENT如果保持CONNECT为TRUE,只做数据请求的切换,通讯会稳定很多。
如果是RS485链路,用MB_MASTER指令,思路一样,但要注意地址和功能码的对应。Modbus里的“40001地址区”对应协议地址0x0000开始,很多新手会把地址当成40001直接传进指令,结果读出来全是垃圾。标准做法是传“0x0000偏移”或“目标寄存器地址-1”。
3.3 不同品牌变频器的寄存器差异与调试避坑
现场最折磨人的不是轮询逻辑,而是不同品牌变频器的寄存器五花八门。我遇到过西门子V20、ABB ACS510、施耐德ATV310混在一个产线上的情况,三家的寄存器映射完全不同。比如:
- 西门子V20:在Modbus地址里用40100写控制字,40101写速度设定,状态字在40104左右。
- ABB ACS510:控制字和速度给定通常在40001/40002,状态字和实际转速在40103/40104附近。
- 施耐德ATV系列:地址定义比较依赖品牌内部IO映射,写启停状态和给定频率的位置和ABB又不一样。
面对这种混搭现场,我的做法是:在轮询表里给每台变频器单独配一套“寄存器映射结构”,里面存好控制字地址、状态字地址、频率地址、使能地址。这样程序里不写任何针对某个品牌的硬编码,所有品牌差异都通过配置区分。
另外还有几个高频坑:
- 寄存器格式不同:有的变频器频率给定范围是0~50.00,直接传5000;有的是0~16384(十六位满量程)。写入前一定要做量纲换算,别把50Hz传成50。
- 数据字节序不同:大端小端问题在Modbus上极其常见。遇到读出来的数值不对,先做byte swap试一下,很多变频器默认高位在前,但部分国产变频器喜欢倒过来。
- 启停逻辑要单独做:Modbus写控制字不是写一次就完事,很多变频器需要“先发准备使能、再发运行、再发方向/速度”,三组状态位配合。如果你直接把运行命令置1,变频器可能没反应。
3.4 通讯超时、干扰与故障代码排查
通讯项目调完并不代表完事,量产环境里最烦的是“偶发超时”。现场摸排过一条产线,总是固定某一台变频器时不时掉线,查了几天最后发现是485总线转接端子松动,而线缆绝缘皮看着还好,实际上已经磨损。
RS485链路调试时,我的固定排查顺序是:
- 检查手拉手拓扑,严禁星形接法。
- 检查终端电阻是否只在总线两端接入,中间设备绝不能有终端电阻。
- 屏蔽层单端接地还是双端接地,现场按抗干扰标准做,一般建议单端接地。
- 波特率往低调试验。9600看着慢,但稳定性远好于19200,特别是线缆质量一般的情况下。
- 给每一台变频器分配独立地址,并确认没有重复地址。
Modbus指令报错时,错误代码先查在线帮助,但我可以分享几个高频代码经验:
- 请求无响应/超时错误:大概率是地址不对、波特率不一致或从站没在总线上。
- 数据校验和错误:优先怀疑线路干扰,或者数据长度不对。
- 非法数据地址/非法功能码:说明你发过去的寄存器地址超出了这台变频器支持的映射范围。
Modbus TCP链路也别忘了设置超时和重试次数。正常产线负载下,32台变频器轮询一轮不应超过1~2秒,如果远超这个值,先看是不是网络规划问题,比如有人往PLC网口灌了大量广播包,把交换机和CPU都拖慢了。
4. 高频工艺功能块的落地:飞剪凸轮、伺服电子齿轮与视觉联动
4.1 追剪/飞剪的同步控制思路
飞剪和追剪是很多连续生产线(纸张、线缆、管材、包装膜)都会遇到的工艺:材料以恒定线速度往前走,在运动中要完成切断/冲孔/贴标等动作,所以执行机构必须跟着材料同步移动一段距离。这不是简单的定时器能解决的,核心是位置同步。
S7-1500做飞剪,我常用的架构是:
- 用一个高速计数器或带编码器接口的模块,实时采集主传动轴编码器位置,这个位置代表“材料走了多远”。
- 设定一个目标切断位置(比如每500mm切一刀)。
- 当编码器位置累计到设定值时,触发飞剪动作。如果是“追剪”,则先启动一个从轴(伺服或变频电机)与主材料线速度同步,在同步段完成切断/焊接,再返回起点等待下一次。
在博途里,如果工艺对象做凸轮,我们可以给从轴建立电子凸轮关系,主轴位置映射到从轴位置,实现非常精确的同步。如果不用工艺对象,也可以用高速中断:捕捉编码器到达设定位置的信号,在中断OB里发出切断指令,同时用一个FB维护同步轴的速度跟随。这种方法硬件要求低、适合中低速产线。
调飞剪时我个人有几个经验:
- 相位偏移一定要留可调参数。实际剪切点往往有机械误差,凸轮表的起点和终点相位,现场要能方便地加减几毫米。
- 加减速段要平滑。如果从轴瞬间从零跳到线速度,机械冲击非常大,建议在凸轮表里做S型曲线过渡。
- 编码器丢脉冲是头号大敌。出现切断位置越来越不准的情况,先检查编码器机械连接是否打滑,再检查高速计数模块滤波时间设置是否过短,误滤了真实脉冲。
4.2 星角降压启动的时序逻辑再拆一遍
星角启动看起来简单,封装成模块时却特别容易出错。主回路是三个接触器:主接触器KM1负责接通三相电源,星形接触器KM2把电机绕组接成星形,角形接触器KM3把电机绕组接成角形。启动时序:先KM1和KM2吸合,电机降压启动;延时几秒,等转速上升后,KM2断开,KM3吸合,切换成全压运行。
梯形图控制逻辑里,最最核心的一条是:KM2和KM3绝不允许同时吸合。一旦同时导通,相当于绕组短路,轻则跳闸,重则烧接触器烧电机。所以程序里不但要在输出侧互锁,还要把两个接触器的常闭触点串到对方的输出回路里,形成双重保护。
我把星角启动做成一个FB,接口参数包括:
- 启动/停止命令
- KM1/KM2/KM3的输出地址
- 三个接触器的反馈触点
- 星形延时时间(一般3~6s,根据电机功率和负载惯量调)
- 星形断开后的安全等待时间(防止电弧未熄就吸合角形)
内部逻辑状态机这样走: IDLE → KM1+KM2 ON → 星形延时计时 → KM2 OFF → 安全等待计时 → KM3 ON → RUN。 运行中如果KM2反馈信号没有在期待时间内消失,直接报故障停机。这个反馈检测非常有价值,现场接触器触点粘连是常见故障,检测到就能避免烧电机。
4.3 伺服电子齿轮比计算:从一个实际案例说起
热词里有一条很具体的参数:三菱JE-A伺服、5比1减速器、带5M20同步轮、线速度0.8米每秒。这个我拿实际数字算一遍,正好把电子齿轮比讲清楚。
先看机构参数。5M20同步轮,表示节距5mm、20齿,一圈的周长是节距×齿数=5×20=100mm。线速度0.8m/s换算成mm是800mm/s,那同步轮转速就是800÷100=8转/秒,换算成每分钟是480rpm。减速比5:1,电机转速就是8×5=40转/秒,即2400rpm,这个转速对任何伺服来说都是轻量工况。
三菱JE-A的编码器分辨率按常规17位算,就是131072脉冲/圈。如果直接用外部脉冲控制,电机转一圈要131072个反馈脉冲,那么运行在40转/秒时需要约524万脉冲/秒,普通PLC的100k~200kHz脉冲输出根本扛不住。所以实际工程里要么用总线伺服(Profinet/EtherCAT直接传速度指令),要么就得设置电子齿轮比,把指令脉冲频率降到PLC能接受的范围。
假设我们希望1个指令脉冲对应0.01mm材料位移。同步轮转一圈走100mm,对应电机转5圈,即5×131072=655360个电机反馈脉冲。那1个指令脉冲对应的反馈脉冲数是655360÷10000=65.536。这个数不是整数,所以电子齿轮比一般取近似值,比如分子分母配成65536/1000=65.536,刚好对上。这样PLC输出的指令脉冲频率就是800mm/s÷0.01mm=80000Hz,也就是80kHz,普通高速脉冲口完全没问题。
这个案例的结论其实很有指导意义:伺服选型时,不要只看功率,还要算一下机械减速比和电子齿轮的匹配度。很多时候所谓“伺服跑不快”,不是伺服能力不够,而是电子齿轮比没配对,导致指令脉冲频率被PLC输出能力限制住了。
4.4 视觉与PLC通讯的典型数据通路
现在产线上相机用得越来越多,视觉和PLC的通讯我已经从“选做”变成了“必做”。最常见的架构有两种:
第一种是视觉系统直接作为Profinet IO设备接入S7-1500。相机算好结果,直接写到PLC的IO输入区,PLC按一个结构体读取。这种方式延迟最低,实时性最好,适合高速检测线。缺点是需要视觉厂家支持Profinet IO协议,组态时一般要装对应的GSD文件(比如热词里提到的西门子AP GSD文件下载,就是干这个用的)。
第二种是走TCP/IP,S7-1500作为TCP客户端或服务器,用TCON、TSEND、TRCV指令与视觉系统通信。架构灵活,但一定要做好心跳检测和超时处理。视觉程序卡死了、网线松了,PLC不能傻等,要在几秒内判定通讯故障并进入安全状态。
不管是哪种方式,数据传输一般就三块内容:触发结果(拍照结果OK/NG)、测量数据(位置偏移、尺寸、角度)、命令(开始检测、切换配方)。我建议在PLC侧建一个固定的视觉通讯DB,字段和视觉厂家约定好,每次通讯先把原始报文落到这个DB里,再做解析。这样以后换相机型号、换通讯协议,只改接口层FC,不影响设备层FB。
5. 调试效率提升与问题排查实录
5.1 怎么快速查看S7-1500的资源与负载
程序写多了、块做大了,总会遇到PLC性能和存储焦虑。博途里查看S7-1500的资源使用情况很简单:在线状态下,在项目树里选中PLC,右键“资源”,就能看到装载存储器的占用情况、工作存储器的使用比例,以及各个块的大小列表。
如果是性能问题,比如现场觉得扫描周期变长、动作反应迟钝,在线后进入CPU诊断缓冲区,可以看到最近的扫描周期时间和最长周期时间。如果最大周期时间经常超过设定值,说明某个中断任务或主循环里有重负载逻辑。这时候重点排查:
- 有没有在OB1里做大量字符串处理?
- 有没有频繁访问非优化的DB?
- 有没有在中断OB里做通讯报文组包这种重型操作?
- 有没有用循环指令扫描超大的数组?
把重负载移出主循环、移到固定周期OB中按节拍处理,S7-1500的性能会明显改善。
5.2 从车企级程序里学到的模块化结构
热词里有人提到吉利/柯马汽车SICAR项目程序。车企的项目我没法贴源码,但这类项目有一个显著特点:程序结构极其工程化,设备层、工艺层、交互层分得很清楚。设备层的每一个电机、阀站、夹爪,都是独立的功能块;工艺层只编排“哪些设备在什么时候做什么动作”,不关心设备的电气细节;交互层统一处理HMI、MES、Andon呼叫。
这种分层思路,对我们做中小型项目同样适用。哪怕你只做一条几十个IO的小线,只要把程序拆成设备层(电机FB、阀FB)、工艺层(联锁逻辑、顺序动作)、交互层(触摸屏数据接口)三层,后期维护的负担就会小很多。最早我总想一上来就把全部细节写进主循环,后来学会了“工艺逻辑里不出现IO点”,程序可读性就有了质变。
5.3 高频问题速查表与实用设置
调试过程中有几个高频问题,我整理成了速查表,每次现场培训都会发出去:
| 现象 | 常见原因 | 处理建议 |
|---|---|---|
| 程序改了下载后没反应 | 在线监视的还是离线状态,或PLC运行在STOP | 先置RUN,再检查在线块版本是否一致 |
| DO/DO点不动作 | 变量被多个地方写了,或优化访问DB导致地址变化 | 全局搜索该输出,查有没有重复赋值;DB关掉优化访问再映射 |
| 第三方触摸屏读不到DB | S7-1500 DB默认优化访问,外部设备按绝对地址访问不了 | DB属性里取消“优化的块访问”,或按符号地址导出 |
| 远程设备无法访问CPU | CPU防护等级限制 | CPU属性→防护与安全→连接机制,勾选“允许来自远程对象的通信” |
| PLC有时连不上 | IP冲突、网线过长、交换机问题 | 关闭本机多余虚拟网卡,固定PLC IP,用PING测试 |
| PROFIBUS/PROFINET从站掉站 | 总线终端、DP地址、网络拓扑 | 检查站地址、终端电阻,查看诊断缓冲区定位掉站站点 |
“西门子的DO怎么映射”这个问题,我单独说一下。S7-1500的IO访问默认走过程映像区,但如果你需要绕过过程映像直接读外设输入,可以用PIP指令(读外设输入)或PQB/PIB(写外设输出)。这在高速响应的场合非常有用,比如直接捕捉编码器快速输入,或者输出一个要求几乎无延时的信号。常规情况还是优先用过程映像区,简单可靠。
5.4 程序交接和版本管理的一些心得
最后聊点程序管理的事。做产线项目,程序不是写完就结束了,后续还有验收、整改、复制线体、维护升级。我踩过最大的坑,是同一个程序文件夹里躺着“最终版”“最终版2”“真最终版”十几个博途项目。后来我给自己定了三条规矩:
第一,每个版本归档时,必须带项目名称、日期、修改内容,压缩包命名按“项目_日期_版本号_修改点”格式来。第二,所有开发过程中的调试记录,只留在线状态下的监控截图和诊断缓冲区导出,不要保留一堆离线乱改的副本。第三,现场程序要定时在线归档,至少每次整改完成之后导出一份归档。因为博途项目里在线状态和离线状态可能不一样,只留离线工程,现场CPU里的程序可能和它完全不同。
我个人的习惯是:每次出差回来,先把在线程序归档一遍,然后再打开离线项目做修改。这样即使某次改坏了,也能从归档里找回现场可用的那一版。
再补充一个小技巧:S7-1500的FB/FC有“优化块访问”能力,但当你需要和第三方系统(昆仑通态屏、上位机、视觉系统)做无符号地址映射时,反而会被优化访问卡住。如果你不确定对方能不能访问符号名,建DB时干脆从一开始就关掉“优化的块访问”,用绝对地址方式。虽然代码丑一点,但兼容性最好,尤其对接老旧上位机时能省很多沟通时间。
程序模块化这条路,说难不难,说简单也不简单。从一开始能跑,到后面好维护、易扩展、可复用,中间隔的是每一次对“为什么这样设计”的思考。少写点重复代码,多花点时间搭好结构,等到半夜不用再被现场电话叫醒的时候,你会感谢当初那个愿意多花半小时做模块化设计的自己。