前阵子做的一条小型输送分拣线改造,控制核心用的就是西门子1200,整套程序在博途(TIA Portal)里从组态、编程、仿真一直跑到现场试车。这次案例做完,我对S7-1200的选型边界、程序块怎么划分、状态机怎么写、调试时会遇到哪些坑都有了比较具体的认识。如果你正准备用1200做类似的小型自动化设备,或者手里拿着博图程序案例却不知道从哪里下手,这篇文章应该能帮你少走不少弯路。
文章不聊那种大而全的理论,而是按我做项目的真实顺序来:先讲为什么选1200,再讲I/O怎么规划、博途里怎么组态,接着拆程序结构和分拣逻辑,最后把仿真调试和现场常见的坑一次性捋清楚。不管你是刚接触博途的新手,还是已经写过几个1200项目但想优化结构的老工程师,都能在里面找到可以直接搬走的东西。
1. 项目背景与选型:为什么这个案子交给西门子1200来做
1.1 原设备的问题和改造诉求
这条分拣线原来的控制方式是“继电器+时间继电器”的老套路。设备本身不复杂:一条来料输送带、两个推料气缸、三个光电检测点、一台变频器驱动输送带,再加上手动/自动切换、产量计数和报警提示。总点数算下来,数字量输入8个左右,数字量输出6个左右,另外预留一到两路模拟量通道备用。
老设备最大的痛点在于:换产品规格时要人工去调时间继电器,刻度不准,生产时抖动又大;继电器触点频发拉弧,故障排查全看师傅经验,图纸画得也不全。客户提的需求并不激进,就是想要一套稳定、可调、有明确报警提示的系统,最好以后还能接触摸屏。
这种需求用小型PLC来做是最合适的。传统继电器方案虽然成本最低,但控制柜里的中间继电器和时间继电器加起来几十个,接线复杂、调试费劲、后期排障靠手摸,一点都不划算。
1.2 为什么在S7-200 SMART和S7-1200之间选了1200
我在选型时主要对比了西门子的S7-200 SMART和S7-1200。S7-200 SMART在小系统里的性价比确实能打,指令简单、上手快,很多老工程师闭着眼睛都能写。但有一个限制在当时很关键:它在通信能力上对PROFINET的支持比较弱,而我判断这套设备后续一定会接触摸屏,还可能把变频器和远程IO挂到同一张网络上。S7-1200的CPU本体集成了PROFINET口,组态触摸屏时不需要额外转换卡,上位机访问也更方便。
具体型号我选了CPU 1214C DC/DC/DC。这里有个选型逻辑值得说一下:1211C虽然便宜,但本体集中度低,只有6路数字量输入和4路输出,做这个案子虽然勉强够,但几乎没有备用点;1212C好一点,不过模拟量通道少;1214C本体带14DI/10DQ,还集成了2路模拟量输入,扩展余地大,而且价格和1212C差距不大。国内中小型设备里1214C用得最多,后续备件好买、图纸参考也多,所以直接一步到位选了1214C。
预算方面多说一句:PLC本体价格只是整个控制系统的一小部分,程序开发、调试周期、后期维护成本才是大头。选1200不选200 SMART,多出来的那点硬件成本,在第一轮现场调试节省的两三天时间里就赚回来了。
1.3 一个控制系统的第一步其实是画I/O清单
很多人打开博途就急着建工程、拖块、写程序,等写了一半才想起来有几个传感器没算进去,于是又回去改硬件组态、改地址分配,程序里一片引用错误。这种边写边改的做法在小项目里还能忍,在稍微大点的系统里就是灾难。
我做完需求梳理后,先画了一张I/O清单,再开工建工程。这张表长这样:
| 信号名称 | 信号类型 | PLC地址 | 备注 |
|---|---|---|---|
| 启动按钮 | DI | I0.0 | 常开,上升沿有效 |
| 急停按钮 | DI | I0.1 | 常闭,断开为急停 |
| 变频器故障 | DI | I0.2 | 变频器干接点 |
| 来料检测 | DI | I0.3 | 光电传感器,检测到为1 |
| 气缸伸到位 | DI | I0.4 | 磁性开关或接近开关 |
| 气缸缩到位 | DI | I0.5 | 磁性开关或接近开关 |
| 计数光电 | DI | I0.6 | 产品通过时给脉冲 |
| 手动/自动选择 | DI | I0.7 | 1为自动,0为手动 |
| 输送带接触器 | DO | Q0.0 | 控制电机启停 |
| 气缸电磁阀 | DO | Q0.1 | 两位五通阀 |
| 运行指示灯 | DO | Q0.2 | 绿色 |
| 故障指示灯 | DO | Q0.3 | 红色 |
| 蜂鸣器 | DO | Q0.4 | 报警输出 |
这里有一个很关键的设计习惯:急停按钮接常闭点,程序里也要按常闭逻辑去处理,同时硬件回路上让它直接切断接触器电源。这样万一急停线路断线,PLC会立刻识别成急停状态,而不是“没按就继续跑”。这种安全冗余的思路,越早养成越好。
I/O表定下来之后,后面所有工作都有据可依,图纸、编程、电气接线、HMI组态全都用同一套地址,沟通成本低很多。
2. 博途里的硬件组态和I/O清单设计
2.1 新建工程时最容易忽略的固件版本问题
打开博途,选择“创建新项目”,项目名建议直接带设备名、日期和版本号,比如“分拣线_20250612_V1.0”。这样后面维护时看着项目列表就能知道这个项目是什么设备、什么时候改过、当前是第几版,不会出现一堆“新建项目1”“新建项目2”分不清的情况。
添加设备时选择CPU 1214C DC/DC/DC,这里有一个特别容易踩的坑:固件版本。博途软件版本不同,可选的CPU固件版本也不同。如果软件比较旧,而手上CPU固件比较新,在设备视图里就要手动选一个与CPU兼容的固件版本。我之前有一次没注意,选了老固件版本,下载时提示设备不兼容,折腾了很久才发现问题。按采购这台CPU的实际固件版本来选,能省很多时间。
2.2 PROFINET IP地址和触摸屏连接规划
S7-1200的PROFINET口默认IP是192.168.0.1,但在现场,我通常会给PLC单独规划一个稳定网段。比如PLC设为192.168.1.10,触摸屏设为192.168.1.11,子网掩码255.255.255.0。两者挂在同一个工业交换机下面,博途组态时在“属性—以太网地址”里设置好IP,触摸屏和PLC之间的通讯就不需要再做任何驱动程序配置,直接拖变量连接即可。
下载时,博途可以选“PN/IE接口”,填入CPU的IP地址后驱动下载。如果现场没有设置好PC网卡和PLC同网段,会搜不到设备。这时候不要来回猜,先把PC网卡手动改成192.168.1.x网段,再重新扫描,基本都能找到。
2.3 PLC变量表坚持用符号名
在博途的“PLC变量表”里,把I0.0、Q0.0这些绝对地址全部定义成有意义的符号名,比如“I0_3_FeedDetect”表示来料检测、“Q0_1_Cylinder”表示气缸电磁阀。编程时一律用符号名,不要直接写绝对地址。
这样做的最大好处是:后期如果因为现场接线变化而改了地址,只需要改变量表,程序逻辑完全不用动。我曾经维护过一个老项目,图纸和实际接线差了三个点,就是因为变量名全是“I0.0”这种地址,谁都不敢乱动。用符号名之后,这种问题基本消失。
博途还支持从Excel导入导出变量表,在点位多的时候非常高效。可以先用Excel把点位整理好,列好名称、地址、数据类型、注释,再导入博途,比自己一项一项敲快得多。
2.4 保持性区域提前设置
S7-1200支持对数据块里的变量设置保持性,也就是说断电之后这个值还能记住。设备上的产量累计、计件数、当前模式这些数据,一旦掉电清零,现场会很麻烦。所以我在变量表或者全局DB里,直接把需要保持的变量设置为“保持”。这个设置在博途的PLC变量表“保持性”列里就能勾选,也可以在“保持性存储器”里按地址范围设置。
这个步骤虽然小,但真到了现场才发现反而很被动。试想一下,设备跑了一上午生产了三千个产品,下午一断电,产量归零,谁都没法交代。
3. 程序框架:OB、FB、FC、DB怎么分工才不会失控
3.1 不要把逻辑全堆在OB1里
我第一次写1200的时候,把所有逻辑全部写在OB1里,一个OB1几十个网络,从下料、传送、气缸到报警全混在一起。当时觉得能跑就行,后来设备出故障,我一个网络一个网络往下翻,光标都找不到问题在哪个块里,那种感觉真的不想再来一次。
这个案例里,我采用了比较规范的程序框架:
- OB1:主循环,只做程序块的调用,不直接写工艺逻辑。
- OB30:循环中断,100ms执行一次,用来做报警扫描、运行时长累计。
- FB1__MOTOR:电机控制块,包含启动、停止、故障互锁。
- FB2__CYLINDER:气缸控制块,包含伸出、缩回、到位超时保护。
- FB10__CONVEYOR:输送线工艺主流程,状态机就在这里。
- FC100__ALARM:报警判断和汇总。
- DB10__PARAM:存放所有可调参数。
- DB20__STATS:存放产量、运行时间、故障次数。
这种结构的好处是:每个块只管一件事,主流程只管状态流转,设备控制块只管执行动作,报警块只管汇总报警,互不干扰。以后排查问题,先看工艺主流程卡在哪一步,再查对应设备的控制块,基本十分钟内能定位。
3.2 FB和FC怎么选
FC没有自己的背景数据块,每次调用都要把参数重新传入、传出;FB有背景DB和静态数据,适合描述一个“设备对象”。
拿气缸来举例:气缸有伸出时间、缩回时间、伸到位、缩到位、当前状态这些信息。我把气缸封装成一个FB,输入是“伸出指令”“缩回指令”,输出是“到位”“超时报警”,静态参数里存动作时间。这样一条线有两个气缸,就调用FB2两次,每次分配一个背景DB,互不干扰。下次换个设备还是用气缸,同一个FB直接复用,改一下参数就能用。
这不是炫技,而是实实在在地减少重复代码。程序做得越小巧,后期维护的人越轻松。
3.3 定时器的正确打开方式
S7-1200和S7-200 SMART在定时器上有一个明显区别。S7-1200不再用老式的T37、T38这类定时器,而是用TON、TOF、TP这些指令。使用TON时,需要给它指定一个背景DB,或者用临时实例。很多人第一次用1200,明明写了TON却没有分配背景DB,编译就报错,或者两个TON共用一个背景DB,程序里表现完全混乱。
我的习惯是:每个设备的动作定时器都用自己FB的背景DB来保存,不共用一个定时器。比如气缸伸出延时2秒,这个延时计时器就存在气缸FB的背景DB里。这样定时器实例和设备的生命周期是绑在一起的,不会出现交叉干扰。
另外,如果程序里有按固定周期执行的任务,比如每100ms采集一次状态并累计运行时间,建议放在OB30循环中断里。OB30的周期在硬件组态里设置,执行精度比在OB1里用定时器累加高得多。
3.4 把所有可调参数收进一个DB
客户现场最常提的需求就是“把这个延时改短一点”“那个时间再加两秒”。如果把时间参数像常量一样写死在程序里,每次调整都要改程序、重新编译、下载,很麻烦。我的做法是把所有可调参数集中放进DB10__PARAM,比如气缸动作时间、分拣等待时间、故障恢复延时,全部定义成符号变量,再通过HMI画面绑定。
现场调试时直接在触摸屏输入数值,PLC程序内部自动读取参数DB。这种做法节省的调试时间非常可观,而且参数调整都有迹可循,不会被悄悄改得面目全非却没人知道。
4. 分拣工艺的核心逻辑:状态机的实现过程
4.1 先把工艺边界理顺再写代码
这个案例的工艺过程可以描述为:产品从料仓落到输送带,输送带把产品向前输送,到达分拣位后,由光电传感器检测到产品,气缸将产品推入旁路料斗,之后气缸缩回,继续等待下一个产品。连续生产时需要累计产量,并在触摸屏上显示。
在写程序前,我把这个流程拆成了几个清晰步骤:等待启动和来料、启动输送带延时、等待产品到达分拣位、气缸伸出推料、气缸缩回并计数。每一步都对应一个状态号。这样做的好处是:现场调试时如果流程卡住,我一眼就能看出卡在第几步,再针对那一步去查传感器或执行机构。
4.2 用SCL写一个带状态机的主流程
SCL是博途里的结构化文本语言,写顺序控制比梯形图更清晰。下面是一段简化后的状态机骨架,演示了从等待来料到分拣计数的主要过程:
CASE #Step OF 10: // 等待启动和来料 IF "DB_PARAM".AutoMode AND "I0_3_FeedDetect" THEN #Step := 20; END_IF; 20: // 启动输送带,延时后等待产品到达 "Q0_0_Conveyor" := TRUE; IF #TimerConveyor.Q THEN #Step := 30; END_IF; 30: // 等待产品到达分拣位 IF "I0_6_CountSensor" THEN #Step := 40; END_IF; 40: // 气缸伸出推料 "Q0_1_Cylinder" := TRUE; IF "I0_4_ExtendDone" AND #TimerExtend.Q THEN #Step := 50; END_IF; 50: // 气缸缩回,完成一次计数 "Q0_1_Cylinder" := FALSE; IF "I0_5_RetractDone" AND #TimerRetract.Q THEN "DB_STATS".TotalCount := "DB_STATS".TotalCount + 1; #Step := 30; END_IF; END_CASE;这段代码在实际项目里当然不会这么简单,气缸和电机部分应该封装在FB里。这里想表达的核心思想是:状态机决定“下一步该做什么”,设备控制块负责“这个动作怎么完成”。把这两层分开,故障时定位就会非常快:状态卡在40步?说明要么气缸没伸到位,要么伸出延时没到,直接去查气缸FB即可。
4.3 手动自动切换必须做到无扰动
手动自动切换是现场非常容易出问题的环节。如果自动运行时,手动画面还能直接强制输出;或者手动运行的时候突然切到自动,设备从停止状态直接启动,都容易出事故。我采用的原则是:输出信号不允许有双重来源。
程序里做一个统一输出逻辑:
IF "DB_PARAM".AutoMode THEN "M_DEV_Cmd" := #AutoCmd; ELSE "M_DEV_Cmd" := #ManualCmd; END_IF;自动模式下只认自动逻辑的指令,手动模式下只认手动操作指令。切换的瞬间,还需要把设备控制块的状态复位到安全状态,让所有执行机构停止输出。等操作员重新发出启动指令后,设备才按照当前模式继续运行。这样才能保证从手动到自动、从自动到手动的切换不会产生意外动作。
4.4 计数信号要加滤波,别让假脉冲骗了你
计数光电在输送线上很容易因为产品抖动、光线变化产生多个脉冲,如果直接拿这个信号去计数,产量数字会明显偏大。我的习惯是给计数信号加一个去抖滤波,比如信号持续50毫秒才认为有效一次。在SCL里可以写一个简单的TON计时,延时时间到了并且信号还保持着,才去触发计数。
这个细节看着小,但在实际生产中非常重要。好的计数不是让你数出理论值,而是让你数出的每个数字都能对得上实物,否则客户第二天就会打电话问“为什么产量莫名其妙多了一百件”。
4.5 报警逻辑和HMI显示
报警系统在这个案例里包括三类:急停触发、变频器故障、气缸动作超时。急停和变频器故障都是直接输入信号,气缸超时是设备控制块内部判断:气缸发出伸出指令后,如果在设定时间内没有收到伸到位信号,就认为气缸异常,触发报警。
所有报警汇总到FC100里,输出一个总报警位,一方面驱动Q0.3故障指示灯和Q0.4蜂鸣器,另一方面把它作为HMI上的报警变量。HMI里配置好报警文本后,现场就能直接看到“变频器故障”这样的具体信息,而不是看着一个灯瞎猜。这一步能明显降低操作人员的处理时间。
5. 仿真下载与在线调试:把程序真正跑起来的几条硬经验
5.1 用PLCSIM先跑一遍虚拟分拣流程
博途自带的PLCSIM可以模拟S7-1200运行,不需要实物PLC就能验证程序逻辑。点击仿真按钮,把程序下载到虚拟PLC后,可以在PLCSIM的变量视图里强制输入信号,比如把I0.3强制为1,观察状态机是否从10跳到20、Q0.0是否变为TRUE。这样能在上电之前把明显低级的状态机死步、延时逻辑写反都揪出来。
但仿真有它的边界:PLCSIM不模拟真实接线,I/O信号都是软件里强制出来的,仿真通过只能说明PLC内部逻辑是对的,不能说明现场接线、传感器、气缸这些是对的。所以仿真结果是“逻辑验证”,不是“现场验收”。
5.2 在线监视的三种方式
现场调试时我最常用三种在线监视方式。第一种是打开程序块的在线视图,直接在SCL或梯形图上看各变量的实时值,当前状态在哪个STEP一目了然;第二种是监控表,把要看的变量拖进去,按列观察实际值和强制值,适合批量对比信号;第三种是HMI变量状态,适合确认触摸屏和数据块通讯是否正常。
使用在线监视前,PLC必须处于RUN状态,程序块也要和PLC内的程序一致,否则在线视图上会显示“程序块不一致”的提示,需要先下载程序再重新监视。
5.3 强制信号是调试利器,也是事故温床
调试时为了跳过某些检测条件,我经常会在监控表里强制点位。比如临时把I0.4气缸伸到位强制为1,让流程继续往下走。这个功能非常强大,但也非常危险。
有一次调试时我强制了到位信号,测试完忘了取消强制,切换回自动流程后,气缸实际没伸到位,程序却因为强制信号认为它到位了,继续执行下一步,差一点造成机械碰撞。从那以后我给自己定了一条铁律:做任何可能产生机械动作的操作前,先切断动力电源;强制完信号必须立刻解除强制,并在调试记录里登记。这条规矩看着麻烦,关键时刻能救命。
5.4 下载程序时最容易犯的错
博图里的下载分“硬件组态下载”和“程序下载”。如果改了设备组态,比如新增扩展模块、修改IP地址,一定要整站下载,否则CPU和扩展模块之间通讯不正常。只改了程序逻辑的话,下载程序块即可,速度快、影响小。
另一个重要习惯是:从现场PLC上传旧程序。如果设备已经运行一段时间,程序换过多个版本,你电脑里的项目不一定是当前最新版本。此时先“从设备上传程序”到电脑,保存成项目,再决定是否修改下载。盲目用电脑里的旧版本去覆盖现场新程序,是一种非常危险的操作。
6. 整理几个最容易翻车的问题和对应的解决办法
6.1 HMI读取DB变量报“访问错误”怎么办
S7-1200的数据块默认是“优化访问”模式,触摸屏通过符号名访问非常方便。但如果你习惯了用绝对地址,比如DB10.DBD4这种方式去绑定HMI变量,而DB10又开着优化访问,编译时就会出现访问错误或无法绑定。
解决办法有两个:一是保持优化访问模式,HMI绑定变量时直接选PLC变量列表里的名称;二是把该DB取消“优化块访问”,重新编译后再生成绝对地址。我建议选第一种,既然博途已经提供了符号寻址,就别再回到绝对地址的老路上。
6.2 CPU固件和博途版本不匹配
这个问题在项目开工或者后期维护时经常遇到。博途软件版本较旧,而CPU固件是新的,添加设备时又选了老固件,下载时会提示“设备版本不兼容”。相反的情况也存在:CPU固件旧、博途软件新,有时可以选择升级CPU固件,但升级前必须断电并确认软硬件版本确实兼容,不能随便操作。
我的建议是:在设备视图里直接选择CPU上实际固件版本,或者略低于实际版本的兼容选项。选购PLC时也顺便记录一下现场使用的博途版本,方便日后维护。
6.3 多个OB同时写一个变量引发的数据混乱
S7-1200的程序可以同时存在OB1和OB30等多个组织块。如果在OB1里写某个产量变量,又在OB30里也写了同一个变量,两个组织块的执行顺序不断叠加,可能出现变量被覆盖、逻辑结果时好时坏的怪现象。这种问题最隐蔽的,因为它不报错,只是实际动作偶尔不对。
我给自己的约定是:一个变量只在一个OB里执行写操作,其它OB只允许读取。比如产量累计只在OB1的状态机里写,OB30只负责读取并做报警判断。这个简单约定能避免一大批“查不出原因”的诡异故障。
6.4 模拟量量程换算写清楚
虽然这个案例的模拟量通道是预留备用的,但我想提一下量程换算。S7-1200的模拟量输入原始值范围是0到27648,对应的是0到100%的信号。如果外接的是4到20mA传感器,要显示成实际工程值,需要做量程标定。换算关系其实就是一次函数:
工程值 = (原始值 / 27648) × (量程上限 - 量程下限) + 量程下限这里要注意,4到20mA对应的原始值不是从0开始的,而是约5530到27648,所以要先把原始值减去5530,再做比例换算。这个细节我见过很多人出错,尤其是第一次接模拟量时,显示出来全是负数或者最大值。把换算公式写在功能块的注释里,后面维护的人会感谢你。
6.5 版本管理和项目归档
做完一个阶段,我会把整个项目归档一次,归档文件带日期和版本号。同时额外导出一份PLC变量表、报警文本表和参数表。为什么这么做?因为项目文件是单机文件,硬盘损坏、误删、同步工具覆盖都可能导致项目丢失,但变量表和参数表只要有纸质或PDF版,照着改回来的工作量就小得多。
另外,每次现场改动必须同步更新图纸。很多设备做久了之后,程序版本和接线图已经对不上,新接手的人根本不敢改,只能靠猜。这种技术债是最难还的。
6.6 编程时的注释习惯
千万不要等到程序快写完了才回去补注释。写完一个网络、写完一个功能块,立刻把注释补上,顺便把当初为什么这么写也记下来。两三个月后你再看自己写的程序,如果没有注释,连你自己都要靠猜。我做项目时对注释的要求是:一个功能块头部必须写明功能、输入输出、使用日期、调用位置。这不算麻烦,反而能让你在后续维护中节省数倍时间。
这个案例做完之后,我最大的感受是:1200加上博途这套组合,对小中型自动化项目来说,确实能做到“程序结构清爽、调试效率高、维护方便”。但前提是你要把功夫下在写程序之前——I/O表理清楚、地址分配合理、块结构提前规划好,后面写代码就像填空一样顺畅。如果你正准备开始一个类似的项目,我建议先从这三张表入手:I/O清单、程序块清单、参数DB清单。这三张表画齐了,你已经成功了一半。