上个月刚交付了一套大型包膜机的西门子PLC控制程序,整条设备用S7-1500做主站,气缸、模拟量、通讯、机械手全部塞进同一个CPU里跑,核心逻辑清一色封装成FB块。这几天整理项目资料的时候,不少同行在问这套程序的结构和FB块到底怎么设计的。正好把整个项目的折腾过程完整梳理一遍,从工艺流程、硬件选型到FB块封装、通讯调试、现场排坑,给准备碰类似设备的同学做个参照。
这套设备说大不大说小不小,但很有代表性:十几个气缸、模拟量信号、机械手取放膜卷、多台变频器要通讯,还带触摸屏和上位机接口。可以说把西门子PLC常见的应用场景都涵盖了。文中会涉及到具体选型和参数,都是我实际用过的方案,大家可以当成一份踩坑记录来读,比看手册要直观得多。
1. 先把设备看明白:大型包膜机的工艺流程与I/O清单
1.1 整个流程:从托盘进料到缠绕成型的动作链
大型包膜机,通俗说就是给码垛好的产品(比如饮料整箱、建材、纸品、化工袋料)自动缠绕拉伸膜,达到防尘、防潮、加固托盘的目的。很多工厂把这道工序放在产线末端,设备长时间连续运行,对控制系统稳定性要求很高。
这台设备的动作链大致是这样:
- 托盘货物由辊筒输送线送进包装工位,到位后定位挡料气缸伸出、夹紧气缸抱住托盘底部。
- 旋转臂带动膜架围绕托盘旋转,同时膜架沿立柱升降,完成螺旋缠绕。
- 缠绕到设定圈数后,旋转臂停止,断膜机构动作:压膜气缸压下固定膜尾,切刀气缸推出切断。
- 升降机构复位,输送线启动,把包装好的托盘送出,同时下一托盘进入。
- 膜卷用完或断膜时,机械手从备膜位取新膜卷,装入膜架。
这套动作里,气缸负责定位、夹紧、压膜、切膜,变频器驱动旋转臂和输送线的电机,模拟量采集膜张力信号、压缩空气压力,机械手负责换膜。工艺不算极其复杂,但环节多、互锁多、时序要求严,任何一个动作卡住都会影响整线节拍。
1.2 把I/O点摸清楚:气缸加模拟量大概需要多少模块
项目进场第一天,我就花了大半天把设备的I/O点全部盘了一遍。这一步千万别省,很多程序做到一半发现点数不够或者模块配错,就是因为前期摸底不到位。
这台设备的点表大致如下:
| 信号类型 | 数量 | 说明 |
|---|---|---|
| 数字量输入 DI | 32 | 气缸磁性开关、限位开关、急停、门开关、传感器 |
| 数字量输出 DO | 24 | 电磁阀、指示灯、蜂鸣器、风机接触器 |
| 模拟量输入 AI | 6 | 膜张力2路、压缩空气压力1路、热封温度2路、备用1路 |
| 模拟量输出 AO | 2 | 旋转臂转速给定(备用)1路、张力比例阀控制1路 |
如果只算气缸,这台设备一共14个气缸,双电控和单电控都有。双电控电磁阀每个要占2个DO,单电控占1个DO。所以DO点数一下子就上去了。加上旋转臂变频器、输送线变频器、风机启停,DO总点数到了24路。
DI点数多,一是气缸到位磁性开关占了28路(14个气缸x2个到位信号),二是限位和急停等安全信号占了剩余部分。如果你的设备气缸更多,DI点数会非常夸张,选模块时务必按最大可能点数留20%余量。
1.3 哪些环节最容易出问题:现场设备状态决定了程序策略
这个工艺里,最容易出状况的环节是断膜和换膜。膜卷在高速旋转中如果张力控制不好,容易跑偏或者断裂;断膜时切刀气缸如果和压膜气缸时序错乱,膜就会缠进设备里。还有机械手取膜卷,如果输送线还在运行或者膜架位置不对,机械手就会撞上去。
所以写程序之前,我先在纸上把每个危险环节的互锁条件列了出来。比如断膜流程里,要求旋转臂必须完全停止、压膜气缸压紧到位,切刀气缸才允许伸出。机械手取膜时,膜架必须回到换膜位、输送线必须停止、旋转臂必须断电抱闸。这些互锁后面全部做进了FB块的内部逻辑和OB1的调用条件里,宁可动作慢一点,也不能让设备出安全事故。
2. 硬件底座怎么搭:PLC选型、模块配置与网络拓扑
2.1 为什么选S7-1500而不是S7-1200
很多同行第一反应是这种规模的设备用S7-1200就够了吧?实际上我犹豫过,最后选了S7-1500(CPU 1511-1 PN)。原因有三:
第一,程序量。FB块封装得越多,程序框架越复杂,OB1里调用数量多,1200的代码存储区和数据区虽然也能装下,但余量会比较紧张。1500的程序存储区大得多,而且FB背景DB、HMI数据、工艺数据都放在一起,内存充裕,调试时能省很多心。
第二,通讯能力。这台设备要同时接两台G120变频器(PROFINET)、一台温控表(Modbus RTU)、机械手控制器(PROFINET IO或TCP/IP)、触摸屏(PROFINET),还有上位机预留接口。1500的PN口带多个IO控制器通讯更从容,1200在多个主动通讯连接时会显得吃力。
第三,在线诊断功能。1500的诊断缓冲区能记录更详细的事件,配合TIA Portal的在线监控,排查偶发故障时真的能救命。这种连续生产的设备,偶发故障最让人头疼,诊断能力必须到位。
不过如果设备规模小、气缸少、没有复杂通讯,S7-1200完全够用,价格还便宜。选型别盲目追求高端,够用并且有余量才是最合适的。
2.2 网络拓扑:PROFINET做主骨干,485做补充
整个系统的通讯架构,我是这样搭的:
- 第一层,以太网/PROFINET:S7-1500 CPU的PN口通过交换机连接触摸屏(KTP1200)、两台G120变频器、机械手控制器、上位机预留网口。
- 第二层,RS485/Modbus RTU:CPU的CM1241 RS485通讯模块挂温控表,走Modbus RTU协议,读取温度和设定值,同时把故障状态传回PLC。
- 第三层,本地信号:所有DI/DO/AI信号通过信号模块接入背板总线,不占用通讯资源。
这样分层的思路是,周期性的运动控制和IO通讯走PROFINET,实时性有保障;非周期性的仪表数据走Modbus RTU,数据量小、实时性要求不高,用485成本低且稳定;本地信号直接用硬线,不经过网络,可靠性最高。
2.3 变频器与伺服驱动的接入方式
旋转臂电机用的是西门子G120变频器,输送线电机也用了一台G120。这里有两个关键点:
第一,旋转臂的启停和转速给定,我没有用传统的硬线端子控制,而是走了PROFINET通讯。控制字和设定值直接写到变频器的PZD区,比如控制字1(STW1)发送"准备/运行/停止"指令,主设定值(NSOLL)发送速度百分比。这样省掉了模拟量输出模块的线路,还能实时读回变频器电流、频率、故障字,诊断方便得多。
第二,旋转臂在断膜时需要快速、准确停在固定角度。如果只靠变频器自由停车,惯性大会冲过位置。我用了变频器的复合制动功能,同时程序里在停车前先降速到爬行速度,等收到接近开关信号再给停车指令,让旋转臂以较低速度停在目标位置附近。这套逻辑虽然简单,但很实用,比直接加制动电阻成本低。
2.4 触摸屏和PLC的数据规划
HMI选了西门子KTP1200,12寸触摸屏,画面做了主画面、手动操作、参数设置、报警记录、I/O监控五页。程序里专门规划了一个全局DB(HMI_DATA),所有触摸屏需要读写的数据全部集中在这个DB里。
这个设计是跟做HMI的老朋友学的,好处太明显了:
- 屏上改配方、改参数,只需要操作HMI_DATA里的变量;
- 报警文本绑定的变量集中在同一个数据块,程序结构清晰;
- 后期换触摸屏或者加SCADA上位机,只需要把HMI_DATA映射过去,程序主体不用动。
有了这个DB,触摸屏组态时我基本上不用去搜PLC里的散落变量,十几分钟就能把变量连接做完。强烈建议所有项目都这么做。
3. FB块才是这个项目的灵魂:气缸、模拟量、机械手的模块化设计
3.1 气缸控制FB:双电控和单电控统一封装
气缸控制是整个程序中数量最多、最容易重复的逻辑。14个气缸,如果每个气缸都在OB1里写一遍伸出、缩回、延时、报警,程序会臃肿到没法维护。我的办法是写了一个通用FB——FB_CYL,每个气缸调用一个背景数据块。
FB_CYL的接口设计如下:
输入: bEnable BOOL // 使能 bAutoExtCmd BOOL // 自动模式伸出指令 bAutoRetCmd BOOL // 自动模式缩回指令 bManExtCmd BOOL // 手动伸出按钮(点动) bManRetCmd BOOL // 手动缩回按钮(点动) bSensorExt BOOL // 伸出到位磁性开关 bSensorRet BOOL // 缩回到位磁性开关 tTimeOut TIME // 超时时间 输出: bValveExt BOOL // 伸出电磁阀输出 bValveRet BOOL // 缩回电磁阀输出 bInPosExt BOOL // 伸出到位状态 bInPosRet BOOL // 缩回到位状态 bError BOOL // 动作超时故障 nErrorCode INT // 故障代码 静态: // 内部状态机变量(不可外部访问) state INT timer TON双电控气缸用bValveExt和bValveRet两个输出分别控制两个电磁阀;单电控气缸则只用bValveExt一个输出,如果FB内部检测到bValveRet输入为空,就自动切换成单电控模式。实际使用中,只要在OB1里把对应气缸的引脚分配好,就能实现统一的动作逻辑。
内部状态机只有几个状态:初始等待、伸出中、伸出到位、缩回中、缩回到位。每次动作前检查当前是否在合适状态,触发超时定时器。如果伸出或缩回超过设定时间还没到位,立即切断输出并置位报警,同时把nErrorCode写入对应气缸编号,方便HMI显示。
3.2 模拟量FB:从原始值到工程量的完整处理链
模拟量处理如果不写FB,每个模拟量信号都重新写一遍标定、滤波、断线检测,代码量很难看,而且容易出错。我写了FB_AIN,统一处理所有4-20mA模拟量输入。
作为4-20mA信号,实际的有效量程对应原始值5530到27648(西门子模拟量模块默认0-20mA对应0-27648,4mA对应5530)。FB_AIN内部做这几件事:
- 原始值读取:从IW地址读取原始整数。
- 断线检测:如果原始值低于1000,判定为信号断线(4-20mA低于4mA基本就是线路断了)。
- 工程量转换:把原始值从5530到27648的区间,线性映射到工程值的量程下限和上限,比如张力传感器量程0-500N。
- 一阶滤波:对转换后的工程值做一阶惯性滤波,滤波系数由输入参数设置。
实际焊接过测温、拉压力传感器的朋友肯定遇到过信号毛刺问题。张力信号尤其明显,膜卷旋转时张力会有周期性波动,如果滤波系数设得太小,程序会误触发张力报警;设得太大,反应迟钝,真实张力变化时系统跟不上。我最后把滤波时间设在0.3秒左右,既能滤掉高频毛刺,又能保证张力突变在0.5秒内反映出来。
3.3 机械手握手FB:用请求-应答机制串起来
机械手(实际是换膜机械手)和PLC的交互,走的是PROFINET,通讯方式类似IO设备,PLC直接读写机械手控制器映射过来的数据区。但通讯只是基础,更重要的是逻辑上的握手。
我写了FB_ROBOT,核心是请求-应答机制。PLC侧输出"换膜请求",机械手控制器收到后,如果各轴状态安全,就输出"允许换膜";PLC收到允许后,触发"开始换膜",机械手开始执行取卷、搬运、装膜动作;完成后输出"换膜完成",PLC清除请求,机械手回到原位等待下次换膜。
这个握手流程里,最关键的互锁条件写在了OB1的调用段前置判断里:
- 只有膜架停在换膜位,才允许发换膜请求;
- 只有旋转臂完全停止,才允许发换膜请求;
- 只有输送线无托盘占用,才允许发换膜请求。
写完FB_ROBOT后,我还在FB内部加了超时监控。如果发出换膜请求后30秒内机械手没有反馈任何信号,就报通讯或机械手故障,防止机械手卡死时PLC还在傻等。
3.4 主程序怎么组织:OB、FC、FB的调用关系
有了FB块,主程序的组织就是把这些FB按工艺顺序"串"起来。我保留了一个纯FC——FC_MAIN,专门做流程状态控制,所有的FB调用都在这个FC里按状态机的思路展开。
OB1只做三件事:调用系统诊断块、调用FC_MAIN、调用HMI数据刷新块。这样程序层级非常清晰:
- OB1(主程序):最顶层调度,扫描周期内只做基础逻辑。
- FC_MAIN(流程控制):根据当前设备状态,决定哪个FB块应该激活、哪个FB块应该禁止。比如"断膜流程中",输送线FB必须禁止运行;"换膜流程中",旋转臂FB必须禁止运行。
- FB_CYL/FB_AIN/FB_ROBOT(执行层):真正的动作执行,每个FB管理自己的时序、报警、到位检测。
- DB块:全局数据和FB背景数据分开,HMI_DATA是全局共享数据,FB背景DB只归对应FB私有。
这种做法的好处是,你看着FC_MAIN的状态机一步步走,就知道设备当前在干什么,下一步要干什么,哪个FB在运动。排查故障时,在OB1里看状态字,再进对应FB看内部状态,基本几分钟就能定位问题。
4. 通讯细节做实:PROFINET、Modbus RTU与触摸屏的数据交换
4.1 PROFINET周期性通讯与G120变频器
G120变频器接PROFINET,需要在TIA Portal里把G120的GSD文件装好,组态为PROFINET IO设备,然后定义报文。我用的是标准报文1带2个PZD字,控制字1和速度设定值,再加2个状态字。这样报文短,实时性好,响应时间在10ms级别,旋转臂的控制足够了。
程序里,通过FB_VFD_G120(我封装的一个变频器控制FB)来跟变频器交换数据。FB内部做的核心工作:
- 把PLC侧的控制字按西门子标准拼装,如bit0=ON/OFF1、bit3=使能运行、bit7=故障复位;
- 把速度给定值按16384对应100%的规格写入PZD2;
- 读回状态字1和实际频率,提取"准备就绪""运行中""故障"等标志;
- 如果通讯超时或者状态字异常,立即停机并报警。
这里有个很容易踩的坑:G120的报文控制和用硬线端子控制不一样,如果控制字没有按顺序给(先给准备就绪条件,再给使能条件),变频器是不会转的。具体来说,要先把bit0置1建立"准备"状态,等待状态字反馈"准备就绪",然后再把bit3置1,变频器才会输出。如果一上来就把所有位都置1,很多变频器会拒绝启动,或者报通讯错误。我第一次调G120时就卡在这个时序上,后来对照状态字位的定义一步步来,才跑通。
4.2 Modbus RTU与温控器的数据拉通
热封装置的温控表,选了支持Modbus RTU的仪表,通过RS485挂在CM1241模块上。通讯参数:波特率9600,8数据位,1停止位,无校验(实际用的8N1)。温控表的地址设为1。
程序里写了一个FB_MODBUS_MASTER,负责周期轮询温控表。读取两个保持寄存器:当前温度PV和设定温度SV,必要时写SV调整设定值。Modbus报文格式:
- 读寄存器(功能码0x03):发送地址、功能码、起始寄存器地址、寄存器数量、CRC16校验;
- 写寄存器(功能码0x06):发送地址、功能码、寄存器地址、写入值、CRC16校验。
这个FB里设置了超时时间和重试次数。一次请求发出去后,如果200ms内没收到响应,就重发一次;连续3次没响应,则置位通讯故障。同时,FB内部会处理响应报文,判断地址、功能码、CRC是否匹配,避免总线上的错误报文误写入数据。
4.3 机械手控制器的信息交互
机械手控制器支持PROFINET IO从站模式,但它的数据区定义比较特殊,不是标准的GSD文件,需要按照机械手厂家提供的寄存器映射表来组态。我在做映射时特意写了一张对照表,把PLC侧地址、机械手侧地址、信号含义一一列出来。
例如:
- PLC输出到机械手:bit0=换膜请求,bit1=清除故障,bit2=输送线空闲;
- 机械手反馈到PLC:bit0=允许换膜,bit1=换膜开始,bit2=换膜完成,bit3=机械手故障,bit4=机械手在原点。
这些信号在程序里全部映射到FB_ROBOT的背景DB中,HMI诊断画面也能看到实时状态。注意机械手相关信号的更新时间,由于走的是PROFINET IO,周期一般4-8ms,完全够用。但千万别把机械手的运动完成信号当作硬IO来用,因为通讯建立需要时间,PLC上电初期机械手还没连接时,这些位是无效的。程序里我在FB_ROBOT内部加了一个"通讯健康"标志,通讯没建立时禁止任何机械手动作。
4.4 通讯诊断和故障处理
通讯这块,实际调试中我养成了一个习惯:每个通讯FB内部都保留一组诊断变量,比如"最后一次通讯时间戳""连续失败次数""最近一次错误码"。这些变量通过HMI_DATA全部放到触摸屏的I/O监控画面里。
这样做的好处是,设备运行几个月后如果出现偶发的通讯异常,客户只需要看一眼触摸屏上的"最近错误码",就能大概率判断故障方向。比如Modbus通讯错误码是超时,基本就是线路问题或从站掉电;如果是CRC错误,基本就是干扰或波特率不匹配。
另外,所有通讯故障我都没有做成直接停机,而是先报警提醒,如果连续几秒内恢复正常就自动复位。因为包膜机在运行时,偶尔一次MODBUS读超时并不影响安全,但直接停机反而会让托盘卡在半路,处理起来更麻烦。当然,涉及安全互锁的通讯信号(比如机械手的急停回路)必须直接进安全逻辑,不能靠通讯判断。
5. 联动调试全过程:从单机测试到整线联动的坑与修复
5.1 空载测试阶段:气缸动作异常和磁性开关抖动
设备装好后,第一步是空载测试,不开膜卷、不送托盘,先把所有气缸手动动作挨个试一遍。结果很快就发现几个问题。
第一个问题是磁性开关抖动。气缸在伸出到位瞬间,活塞撞击端盖会产生振动,磁性开关在这个瞬间会反复通断几次。如果不处理,PLC可能把一次到位动作判断成"到位→离开→再到位",导致时序紊乱。解决办法:一是使用带延时功能的磁性开关,二是PLC的DI通道设置2ms左右的输入滤波时间,三是在FB_CYL内部程序中加入"稳定时间"判断——收到到位信号后必须持续20ms以上才判定为真。
第二个问题是两个气缸动作速度不一致。设备上有两个对称的夹紧气缸,理论上应该同时夹紧,实际调试时发现一个快一个慢。排查发现是气路三通位置不合理,靠近气源的那个气缸先动作,远处的滞后。后来在气路上加了单独节流阀,单独调节每个气缸的进气和排气流量,同时程序里对两个气缸的"同时到位"做了容差判断,允许50ms内的偏差。
5.2 模拟量信号跳变:屏蔽、接地与滤波的教训
模拟量调试时,张力信号出现了比较明显的跳变,在设备空转时实际张力应该在50N左右,显示值却在30-80N之间大幅波动。用万用表在传感器输出端量,信号很稳定,但PLC读取的原始值在跳动。这说明干扰是加在信号传输路径上的。
我先检查了信号线。发现张力传感器的电缆和变频器输出线走在同一个线槽里,而且有一段靠得很近。变频器输出的PWM波形会产生强电磁干扰,感应到模拟量信号线上,就会出现这种随机跳变。处理办法:把模拟量信号线单独走槽,和动力线保持至少20cm距离;屏蔽层一端(PLC侧)单端接地,另一端悬空。改完之后,信号跳变幅度下降了不少。
但还没完全解决。后来发现柜内24V开关电源和模拟量模块共用了同一个接地端子,存在地环路干扰。我把开关电源的接地和模拟量模块的接地分开,信号更稳定了。最后在FB_AIN里加上一阶滤波,显示值稳定在47-53N范围内,完全可接受。
5.3 联动运行时机械手与输送线的竞争问题
空载测试和单机调试都通过后,进入联动运行阶段。第一次满载联动测试,就跑出了一个让人冷汗直冒的问题:机械手正在换膜时,下一托盘已经送到了包装工位,输送线还在往里面送,差点把机械手的膜卷安装工位撞上。
根因是流程状态控制里的互锁条件不完整。我最初只把"膜架回换膜位"作为机械手的动作条件,没有把"输送线无托盘请求"加进去。而输送线的启动条件里,也没有把"机械手正在换膜"作为禁止条件。两个条件互相漏掉了对方。
修好这个bug,我在FC_MAIN里加了一组互锁矩阵,把所有可能同时动作的机构列成表格,逐个检查它们的互锁关系:
| 活动A | 活动B | 互锁要求 |
|---|---|---|
| 输送线送料 | 机械手换膜 | 禁止同时 |
| 旋转臂旋转 | 机械手换膜 | 禁止同时 |
| 旋转臂旋转 | 断膜/压膜 | 禁止同时,须先停旋转臂 |
| 断膜切刀 | 压膜气缸 | 压膜必须到位后才允许切刀伸出 |
| 膜架升降 | 换膜请求 | 膜架必须停到换膜位才允许 |
经过这轮互锁完善,后续再没有出现机构打架的情况。互锁条件宁可多写,不能少写,这是一次联动事故给我留下的最大教训。
5.4 485通讯偶发失败:终端电阻和共地的细节
Modbus RTU通讯一开始并不稳定,表现为温控表的数据偶尔读不到,一天可能出现几次通讯超时。刚开始我以为是波特率或者地址设置问题,反复检查都没发现异常。
后来我用示波器看了485总线波形,发现信号上升沿和下降沿比较缓慢,且末端有振铃现象。这是典型的缺少终端电阻的特征。温控表距离PLC大概30米,485总线的两端应该各接一个120Ω终端电阻。PLC这边CM1241模块内部带了一个终端电阻开关,我把它打开;仪表那一端则外接了一个120Ω电阻。接上之后,波形明显改善,通讯再也没有偶发超时。
还有一个容易被忽略的细节:485通讯必须保证总线上的设备共地。如果仪表和PLC分别使用不同的开关电源,两个电源的负极(参考地)如果没有连在一起,485信号的电平参考点就不一致,容易造成通讯误码。我的做法是用一根1.5平方的导线把两者的0V端子连起来,这样RS485的A/B信号就有了统一的参考电位。
5.5 系统上电顺序与程序启动保护
联动运行稳定之后,最后还补了一道安全措施:上电顺序和启动保护。
西门子PLC和变频器、机械手控制器的上电启动速度不一样。如果PLC已经运行而变频器还没就绪,或者机械手通讯还没建立,程序里相关输出会被误触发。处理办法是在FC_MAIN的状态机里加一个"系统就绪"环节,要求以下条件全部满足才允许进入自动运行:
- 所有变频器通讯已建立且无故障;
- 机械手控制器反馈"通讯正常,在原点";
- 急停回路闭合;
- 气压达到设定值;
- 膜卷到位信号为真;
- 输送线上无托盘卡阻。
只有系统就绪信号置位,自动流程才能启动。这个"软启动"逻辑看着简单,但实际项目里很多事故都是因为上电瞬间输出误动作引起的。
调试到最后,整个系统连续跑了72小时满载测试,没有出现一次停机和故障报警。交机那天客户说,这台设备从安装到稳定运行,比他们预期的周期缩短了将近一周。
这次项目做下来,我最大的体会是:FB块封装确实不是炫技,而是真能提高程序可靠性和调试效率。14个气缸的逻辑,用FB_CYL反复调用,每个背景DB独立互不干扰;模拟量、通讯、机械手各有各的FB,出了问题只改对应FB,其他部分完全不受影响。这种模块化的思路,不仅省了写代码的时间,更重要的是为后期的维护、改造、复用打下了基础。
最后再分享一个很实际的建议:所有FB块的背景DB和全局DB,变量命名一定要规范,注释一定要写清楚。这次项目交机后,客户自己的电气工程师接手维护程序,他看着FB接口和注释,基本没打电话问我,就独立完成了一次参数调整。好程序不是写完就算完,而是要让后面接手的人能看懂、改得动、敢去动。这一点,比任何高级功能都重要。