ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PLC指示灯定时闪烁:S7-1200/1500梯形图三种实现方法

PLC指示灯定时闪烁:S7-1200/1500梯形图三种实现方法 “指示灯定时闪烁”可以说是PLC入门里最经典、也最容易被低估的需求。别看不起一个灯它在设备里往往代表“运行状态”“报警提示”或者“待机指示”如果闪烁逻辑处理不好轻则看着别扭重则被现场调试同事一通电话打过来问“这个灯是不是坏了”。尤其是从S7-200 Smart 转到 S7-1200/1500 的朋友最容易在定时器用法上栽跟头——博途TIA Portal里的定时器类型、调用方式和老200差别不小。这篇文章我不讲虚的直接围绕 S7-1200/1500 的梯形图LAD编程给你3种实现指示灯定时闪烁的方法每种都附详细变量表和可复现的梯形图网络描述硬件组态、参数计算、仿真调试、常见坑点一并覆盖。适合刚上手博途的初学者也适合想换个更优雅写法的老手。1. 方案选型与设计思路1.1 为什么“一个闪烁”也有技术含量很多人第一反应是闪烁还不简单输出和定时器串一下不就行了真到博途里一写就发现问题S7-1200/1500 的定时器TON输入端IN要求的是边沿信号逻辑如果你直接拿定时器常开点去控制自身线圈在200里很常见的自复位写法在1200里容易搞出“看门狗错误”或者时序错乱。另外指示灯闪烁并不只是“亮灭”两个状态它涉及三个核心参数周期时间整个亮灭循环需要多长时间占空比亮的时间占周期的比例精度是否需要精确到毫秒级还是几百毫秒的误差无所谓。比如设备启动指示灯推荐周期1秒、占空比50%即亮0.5秒、灭0.5秒而报警灯可能需要亮0.2秒、灭1.8秒这种明显“急促”的效果。你方案选得对不对直接决定后面改参数时是改一个定时器预置值就行还是要重写一段逻辑。针对S7-1200/1500我梳理出三条路线单定时器自复位 比较指令代码量最少适合固定频率的简单闪烁双定时器 TON TON 互相触发亮灭时间分别可调适用性最广时钟存储字节或循环中断不用自己写定时器调用精度最高适合需要多个灯同步闪烁或周期极其稳定的场合。这三条路线不是互斥的。你完全可以先用方法2实现基本闪烁等方法调试通过后再切换成方法3来做节拍同步。下面我逐一拆解。1.2 三种方法的对比与适用场景方案代码量可调性精度推荐场景方法一单定时器比较最少一般只能整体调周期受扫描周期影响固定频率的动作指示方法二双TON互锁中等亮灭独立可调受扫描周期影响误差可控大多数设备状态灯方法三时钟字节/循环中断很少/较多时钟字节固定频率循环中断自由可调高可精确到毫秒多灯同步、测试节拍、运动控制辅助从S7-1200到S7-1500这3种方法的编写方式几乎一致主要区别在于1500的扫描周期更快方法一和方法二在极限情况下表现更好一些。另外如果你用了S7-1500的“IEC定时器”而不是老的“S5定时器”那方法二里的定时器数据类型要用TP_TIME、TON_TIME这些别选成老式的T#格式。我下面给的示例都基于博途V17及以上版本以IEC定时器和IEC计数器为标准写法。2. 方法一单定时器自复位 比较指令2.1 这个方案为什么少了一个定时器先看最省事的一种。思路是利用TON定时器的“输出常闭点驱动自身输入”形成自复位振荡。当定时器计时到达预设值后Q点变成1同时常闭点断开定时器复位复位后Q点变0常闭点重新闭合定时器再次开始计时。如此反复就得到了一个周期固定、占空比约等于50%的方波信号。S7-1200/1500里这么写有一个关键细节TON是“1有效计时”的定时器IN端从0变成1时开始计时Q到达PT值后变为1IN端从1变回0时会立即复位。所以直接把自己的常闭触点接到IN端是可行的但扫描周期的存在会让“从开始计时到复位”之间有一个扫描周期的延时这对指示灯没有任何影响但对高精度节拍来说就不够看了。为了能让这个单定时器方案的周期和占空比更“干净”我习惯在定时器输出后面再接一个比较指令拿定时器的累计值 ET 去做区间判断。比如定时器预设值PT为2000ms当ET大于等于0且小于1000ms时输出亮当ET大于等于1000ms时输出灭这就等于把占空比从50%调成了任意比例。2.2 完整变量表与梯形图网络先建好PLC变量表命名按照IEC标准别用中文变量做定时器接口博途里中文变量名虽然允许但在定时器实例关联时容易出一些莫名其妙的报警。变量名数据类型地址/路径注释Start_SignalBoolI0.0启动闪烁的开关Lamp_OutBoolQ0.0指示灯输出Blink_TimerTON_TIMEDB1 / 定时器实例自复位定时器Blink_ETTimeDB1.ET定时器累计时间梯形图网络结构如下我用文本方式把LAD的逻辑网络挨个写清楚网络1启动允许 Start_Signal ----| |----[ Blink_Timer(IN:Blink_Timer.Q NOT, PT:T#2s) ] 网络2比较输出 Blink_Timer.ET T#0ms 且 Blink_Timer.ET T#1000ms ----( Lamp_Out )在博途里操作时要注意TON定时器需要放到“指令”选项卡的“定时器操作”里拖出然后新建一个背景DB例如“Blink_Timer”。如果你不想建DB也可以把定时器声明为全局DB变量或者在OB1的“临时变量”里声明但后者会每次扫描都初始化闪烁逻辑会失效这个坑我后面专门说。未使用自复位方案时如果用“Blink_Timer.Q NOT”作为IN在博途的LAD编辑器中你可以直接用“取反”指令包住定时器Q点来连接。但注意如果定时器还没被调用过Q点初始值是False取反后是True所以上电后定时器会直接开始计时这是正常的不需要额外加启动条件。2.3 参数计算结果说明这个方法里定时器预设值PT决定了整个周期。周期T PT亮灭各占多少由比较指令的阈值决定。以PT2000ms、阈值1000ms为例0~1000msET在设定范围内Q0.0输出True灯亮1000~2000msET超过阈值Q0.0输出False灯灭到达2000ms时定时器复位ET清零进入下一周期。如果你想让闪烁频率变成2Hz周期500ms把PT改为500ms、阈值改为250ms即可。就我自己的使用习惯来说方法一最顺手的是做“频率固定、不需要单独调亮灭时间”的场合比如P LC自身运行指示灯、通讯心跳提示灯。但它的缺点是定时器复位瞬间ET会出现跳变如果你用ET的比较值去做其他逻辑可能会有一个扫描周期的误动作。3. 方法二双定时器TON互锁亮灭时间独立可调3.1 双定时器的核心逻辑这是实际工程里用得最多的一种。核心思想是第一个定时器T1控制“亮”的持续时间第二个定时器T2控制“灭”的持续时间相互置位复位。逻辑如下启动信号为True后T1开始计时灯亮阶段T1计时到输出Lamp_Out变False同时启动T2T2计时到输出Lamp_Out变True同时复位T1T1重新开始计时。有人看到这可能会问那T1和T2会不会同时计时只要你在梯形图里做好互锁就不会。比如T1的Q点控制T2的启动T2的Q点控制T1的复位形成一个环形接力。我用过的写法有几种最简单的一种是用TON定时器和SET/RESET指令配合网络1启动灯亮 Start_Signal ----| |----------------( T1.IN : True ) Lamp_Out ----| |----( T1.IN : False ) //灯亮期间不重复启动T1 网络2T1控制灯灭、启动T2 T1.Q ----( Lamp_Out : False ) T1.Q ----( T2.IN : True ) 网络3T2控制灯亮、复位T1 T2.Q ----( Lamp_Out : True ) T2.Q ----( T1.IN : False )这个写法在实际工程中足够清楚也不容易出现双定时器同时启动的竞争。如果你更喜欢纯LAD不带赋值指令的版本那也可以把T2的常闭触点串到T1的启动回路里下面我给出网络级描述。3.2 亮灭时间可调的梯形图结构这里以“亮1秒、灭2秒”为例给出一个可以直接抄的梯形图逻辑变量表同样先准备好变量名数据类型注释Start_SignalBool启动闪烁Lamp_OutBool指示灯输出T_ONTON_TIME亮定时器PT1sT_OFFTON_TIME灭定时器PT2sT_ON_ET / T_OFF_ETTime实际调试时监视用可选梯形图网络描述网络1亮定时器运行条件 Start_Signal ----| |---- T_OFF.Q ----| / |----( T_ON.IN : True ) T_ON.Q ----( T_ON.IN : False ) // T_ON计时到后自动松开IN, 让T_ON复位 网络2亮定时器输出给灯 T_ON.Q ----( Lamp_Out : True ) 网络3灭定时器运行条件 T_ON.Q ----| |----( T_OFF.IN : True ) T_OFF.Q ----( T_OFF.IN : False ) // 灭计时到后自身复位细节提醒S7-1200/1500的TON定时器IN为False时Q立即变FalseET清零。从T_ON.Q为True变成T_OFF.Q为True的瞬间需要确保两个定时器的切换不发生“拍频”错乱。上面网络里T_ON.Q变成True后T_ON.IN会被网络1里自己的Q常闭点断开所以T_ON计时到后会自动复位而T_OFF.IN在T_ON.Q为True后开始计时。如果T_OFF.PT2s那么灯亮1秒后灭2秒周期正好3秒。可以看到这里亮灭时间完全是独立的想改闪烁节奏只需要修改T_ON.PT和T_OFF.PT不需要改动任何逻辑结构。3.3 调试心得定时器PT参数别在程序里瞎改我见过不少朋友调闪烁时间时在程序编辑器里直接双击定时器的“PT”引脚改成数值。这在仿真时没问题但一旦PLC断电重启在线修改的数值可能因为没有下载完整组态而丢失。正确做法是把PT值做成PLC变量比如T_ON_PT的数据类型为Time在HMI或者监控表里在线修改或者在定时器的PT引脚直接填一个DB变量地址然后通过数据块下载。比如T_ON(IN : T_ON_Start, PT : HMI_Set.ON_Time); T_OFF(IN : T_OFF_Start, PT : HMI_Set.OFF_Time);这样操作工在触摸屏上就能调闪烁速度不用打开博途改程序也方便以后做配方切换。另外双TON互锁方案在S7-1200上还有一个很实用的变体如果你用的是S7-1500可以直接用“Pulse Relay”或者“ToF”定时器简化。但考虑到老项目迁移和习惯兼容双TON永远是通用解无论哪个系列都跑得通。4. 方法三时钟存储字节与循环中断4.1 时钟存储字节Clock Memory Byte怎么用S7-1200/1500的CPU内部有一个很冷门但非常好用的功能——时钟存储字节。你可以在CPU组态的“系统常量”里勾选启用比如选择“Clock memory byte 100”那么MB100的每个位都会输出一个固定频率的方波位地址频率周期M100.010Hz0.1sM100.15Hz0.2sM100.22.5Hz0.4sM100.32Hz0.5sM100.41.25Hz0.8sM100.51Hz1.0sM100.60.5Hz2.0sM100.70.25Hz4.0s用这个方法实现“1秒周期闪烁”简直不要太简单在梯形图里写一句A M100.5如果是LAD就拖一个常开触点地址填M100.5输出接Q0.0完事。这个方案的好处是不占定时器资源多个灯想同步闪烁直接并联输出就行频率绝对一致没有扫描周期抖动因为时钟字节是CPU操作系统实时生成的。但缺点也很明显频率选择有限只有那8个固定值。如果项目要求“亮0.3秒、灭0.7秒”、周期1秒M100.4是0.8秒周期、M100.5是1秒周期都无法满足。这时就要用循环中断来做个更自由的“软时钟”。4.2 用循环中断OB30实现高精度自由频率闪烁循环中断Cyclic Interrupt是S7-1200/1500里特别能体现“高端玩法”的地方。我们可以把闪烁逻辑放到一个周期性调用OB比如OB30默认每100ms执行一次中然后用一个累加器变量自己去翻转输出。比如做一个周期为300ms、亮100ms的波形OB30的执行周期设为10ms也就是每10ms进一次OB30定义一个静态变量Counter每次OB30里Counter 1当Counter计数到10时即经过100ms翻转输出当Counter计数到30时即经过300ms重置Counter并恢复输出状态。这样就实现了一个完全由循环中断控制的闪烁精度只取决于OB30中断周期本身和主程序的扫描周期无关。梯形图逻辑写起来也不复杂网络1累加 ADD_I(IN1 : Counter, IN2 : 1, OUT Counter) 网络2翻转亮灭 Counter 10 且 Counter 30 ----( Lamp_Out : False ) Counter 10 或 Counter 30 ----( Lamp_Out : True ) 网络3周期复位 Counter 30 ----( MOVE 0 - Counter )在博途里添加OB30的步骤选中PLC站点 → 程序块 → 添加新块 → 选择“组织块OB30Cyclic interrupt”设置循环时间为10ms然后编译下载。用循环中断要注意一个关键点中断OB里不要写太复杂的逻辑千万别在里面调用通讯指令或者延时等待类指令否则会拉长中断执行时间甚至导致OB被操作系统终止。我一般只在OB30里放整数累加和比较输出最多再加一点数组移位保证单次执行时间远小于中断周期。如果你只是想简单做个固定频率的节拍器而不想麻烦建中断又想频率不是那8个标准值还可以用SCL写个“本地时钟”变量在OB1里每周期加一个固定偏移比如扫描周期约10ms想得到1.5Hz周期约666.7ms你可以在OB1里每周期加上10ms对应的计数值到达666.7ms翻转一次输出。但这种方法依赖扫描周期稳定只适合要求不高的场合不如循环中断稳。5. 实操过程与调试记录5.1 硬件组态和软件准备动手之前先把环境理清楚。我用的是博途TIA Portal V17PLC选择CPU 1214C DC/DC/DC实际工程中用S7-1500的话操作完全一样。如果你还在用博途V13/V14界面略有差别但定时器指令和中断OB的位置基本一致。硬件上指示灯接的是Q0.0建议加中间继电器隔离别直接用PLC输出点去驱动大功率指示灯尤其是24V指示灯虽然电流不大但启动瞬间冲击也不可忽视。S7-1200的输出点最高电流0.5A超过了会烧输出。组态时检查三点CPU属性里勾选“时钟存储字节”我习惯设成100循环中断OB30的循环时间按你的闪烁精度需求设定确保程序块里用的是IEC定时器TON_TIME而不是老的S5定时器S5TIME后者在S7-1200/1500里基本是兼容遗留选项不建议新项目用。5.2 在博途中输入梯形图的实际操作步骤用方法二来演示完整实操流程打开博途新建项目添加设备选择你的CPU型号和固件版本。在“PLC变量”里建好前面表格里的变量注意名称我用的是“T_ON”“T_OFF”这种短名称方便梯形图里引用。打开OB1从右侧指令树拖入两个“TON”定时器指令放置到不同的网络里。第一个TON的IN引脚从左侧拖入Start_Signal常开触点然后在IN引脚的下方插入T_OFF.Q的常闭触点形成只有“灭定时器结束”才能让T_ON开始计时的条件。第一个TON的Q引脚并联一个线圈节点赋值给Lamp_Out。第一个TON的Q引脚同时连接到第二个TON的IN引脚。第二个TON的Q引脚连接到T_ON的复位逻辑用复位线圈或RS触发器的复位端。编译后把PT引脚分别设为T#1S和T#2S。点击下载将组态下载到PLC然后在监控表里强制Start_Signal为True观察Q0.0输出变化。这一步的关键是“T1的Q同时控制T2的IN和T1自己的复位”如果你用传统S7-200的写法把T1常闭串到T1线圈前面在博途里很容易出现“在IN引脚上不能使用同一定时器Q”的编译错误。解决办法就是像我这样把复位逻辑单独放到一个网络里。5.3 仿真环境实测如果你手头没有真机也别急。博途内置的S7-PLCSIM可以完整仿真定时器逻辑。我经常先仿真跑一遍确认时序图正确再下载真机。仿真步骤在项目树里选中PLC点击“仿真”按钮启动S7-PLCSIM将程序下载到虚拟PLC打开“监控表”插入Start_Signal变量并设为True切换到程序状态观察定时器ET值是否在匀速增长Q0.0是否按预期翻转。仿真时我遇到的最典型问题就是定时器ET值不变化后来发现是定时器指令被放到了OB1的“常循环”之外比如误放到了“启动组织块OB100”里。OB100只在CPU启动时执行一次定时器当然不会持续工作。检查方法在项目树里双击OB1确认你的定时器网络是在OB1的程序区。5.4 现场调试时的顺序真机调试不要一上来就下载程序。我先做三个检查检查I/O地址Q0.0的实际接线端子检查指示灯是漏型还是源型接法S7-1200源型输出要接正极检查CPU运行模式是否在RUN而不是STOP。然后通过博途在线监控在监控表里先手动置位Q0.0看灯是否亮。如果灯没反应优先查接线和中间继电器线圈电压而不是查程序。灯亮了以后再把启动信号强制为True观察闪烁波形。用PLCSIM仿真的时候M100.5这类时钟存储字节在仿真器中同样有效但仿真速度有时受电脑性能影响如果你发现1Hz时钟在仿真里看起来周期偏长不要慌下载到真机就恢复正常了。6. 常见问题与排查技巧实录6.1 问题速查表现象可能原因检查/处理方法定时器ET不动定时器放在OB100或OB10里没被周期调用确认网络在OB1中Q0.0输出不翻转定时器IN被常闭点锁死检查启动条件和复位逻辑闪烁周期明显不准扫描周期太长或使用了依赖扫描周期的比较使用循环中断OB30/OB32下载后PT值恢复默认在线修改了PT但未下载完整程序把PT改为变量下载数据块时钟字节频率不对CPU组态里未启用时钟存储字节CPU属性→系统常量→勾选时钟存储字节定时器报警“定时器编号重复”S5定时器模式下定时器编号冲突换成IEC定时器不用编号多个灯不同步每个灯各用一套定时器启动时刻不同统一使用时钟字节或同一个总复位信号6.2 我在实际中踩过的三个坑第一个坑混淆了“脉冲定时器”和“延时接通定时器”。S7-1200/1500指令库里有TON、TOF、TP、TONR好几种初学者最容易把TON和TOF搞混。TOF是延时断开IN变False后延时一段时间Q才变False做闪烁时需要完全不同的一套控制逻辑。我的建议闪烁固定用TON别用TOF。第二个坑把定时器声明成了OB临时变量。在OB1的临时变量区声明TON实例虽然在编译时能过但每个扫描周期结束临时变量会被覆盖定时器内部的ET和Q状态根本保留不住表现就是定时器永远不工作。正确做法是建一个全局DB或者直接把定时器拖到梯级上让它自动生成背景DB。第三个坑仿真通过、真机不闪。这个我遇到过两次一次是24V电源负极没接好导致输出回路不通另一次是HMI画面里不小心把同一个Q0.0地址写成了强制输出。排查时先看PLC模块上的LED有没有亮再看输出通道有没有电压最后再到监控表看Q0.0的在线值。别一上来就怀疑程序逻辑。6.3 进阶技巧把闪烁逻辑封装成FB如果你同时要控制十几个指示灯每个都复制一段双TON逻辑会非常痛苦。建议把方法二的逻辑封装成一个FB块输入参数是ON_Time、OFF_Time输出是Lamp_Out内部用静态变量定义两个TON实例。然后在OB1里多次调用就好。FB接口定义FUNCTION_BLOCK FB_Blinker VAR_INPUT In_Enable : Bool; ON_Time : Time : T#500MS; OFF_Time : Time : T#500MS; END_VAR VAR_OUTPUT Out_Lamp : Bool; END_VAR VAR T_ON : TON_TIME; T_OFF : TON_TIME; END_VAR这样每次调用都会生成一个独立背景DB互不干扰。而且最重要的是HMI可以直接通过FB的实例DB地址修改变量不需要专门做一堆通信变量映射。这个封装思路同样适用于S7-200 SMART转1200/1500的老项目改起来效率高很多。7. 三种方法的取舍与个人建议回到文章标题3种方法我都试过。从实用角度看我的建议是如果只是给设备做个呼吸灯、心跳灯直接用时钟存储字节M100.5一个字都不用写如果不同状态下灯要不同的闪烁节奏比如正常1Hz、报警0.5Hz封装一个FB_Blinker调用两三次就能覆盖所有需求如果涉及多个指示灯需要严格同步或者频率要求不是整数拍子上循环中断OB30一劳永逸。S7-1200/1500相比老200的优势不只是存储更大、速度更快更在于博途里指令和数据类型更规范化。定时器闪烁这种基础逻辑恰恰是体会“新平台新思维”的最佳切入素材。我见过太多人把200的写法硬搬到1200上最后在定时器新型调用机制上耗费大量时间。其实只要你把IEC定时器的IN、Q、ET行为吃透把“复位逻辑独立成网络”这个习惯养好闪烁这个看似简单的问题根本浪费不了你十分钟。最后分享一个小技巧现场调试时如果手头没有计算机想快速判断PLC的某个Q点能不能正常输出可以直接给输出点对应的位强制为True。用博途在线监控右键变量点“修改为1”灯亮了说明硬件链路没问题再放程序。这个小操作能帮你把故障范围瞬间缩小一半比对着程序猜快得多。
返回列表