4、PLC编程基础(二):定时器、计数器、比较指令、传送指令、算术运算指令

好,咱们接着聊PLC编程。上一章我们把位逻辑指令和基本数据类型捋了一遍,算是打了地基。这一章,咱们要开始盖房子了——定时器、计数器、还有那些让你数据处理能力上几个台阶的指令。

说实话,搞PLC这行,你要是只会点动自锁,那跟没入门差不多。真正让程序“活”起来的,就是这些带时间、带计数、带运算的指令。我当年刚入行时,师傅丢给我一个项目,让我用定时器做个电机星三角启动,我愣是折腾了一宿没搞定。后来才明白,不是指令难,是没理解它的“脾气”。

4.1 定时器:TON、TOF、TP

定时器这东西,说白了就是个“延时开关”。你给它一个启动信号,它就开始倒计时,时间到了就输出。但不同型号的定时器,行为模式完全不一样。我见过不少新手把TON和TOF搞混,结果设备动作全乱套。

4.1.1 TON(接通延时定时器)

这是最常用的定时器。它的逻辑很简单:输入端IN从0变1(上升沿)时,开始计时。计时值达到预设时间PT后,输出Q变为1。如果中途IN变回0,计时器立刻复位,输出也变回0。

嗯,这里要注意:TON的计时是“累计”的,但前提是IN一直保持为1。一旦IN掉电,时间清零。

// 梯形图示例(结构化文本描述)
// 当 I0.0 接通后,延时 5 秒,然后 Q0.0 输出
TON(Timer := T1,
    IN := I0.0,
    PT := T#5S);
Q0.0 := T1.Q;
我的经验: 做设备急停逻辑时,我习惯用TON做一个“去抖”延时。比如传感器信号抖动,加个20ms的TON,能过滤掉99%的误触发。这招我在一条包装线上用过,效果立竿见影。

4.1.2 TOF(断开延时定时器)

TOF跟TON正好相反。输入端IN从1变0(下降沿)时,开始计时。计时期间输出Q保持为1,直到计时时间到,Q才变0。如果IN在计时期间又变回1,计时器复位,Q保持为1。

你想想看,这玩意儿适合什么场景?比如风机停止后,需要继续吹一会儿散热。用TOF就特别顺手。

// TOF 示例:当 I0.0 断开后,延时 3 秒,Q0.0 才断开
TOF(Timer := T2,
    IN := I0.0,
    PT := T#3S);
Q0.0 := T2.Q;
避坑指南: 我曾经在一个项目中,用TOF控制冷却风扇的延时停止。结果发现风扇停了又转,转了又停。查了半天,原来是TOF的IN信号在计时期间被其他逻辑干扰了。记住:TOF的IN必须保持稳定,否则计时会反复复位。

4.1.3 TP(脉冲定时器)

TP这个家伙有点特别。它不管你的输入信号是长是短,只要检测到一个上升沿,它就输出一个固定宽度的脉冲。时间宽度由PT设定。在脉冲输出期间,即使输入信号变化,输出也不受影响。

说白了,TP就是一个“单稳态触发器”。我在做按钮信号处理时特别喜欢用它——不管操作工是按了一下还是按住了,程序只认一个固定长度的脉冲。

// TP 示例:I0.0 每触发一次,Q0.0 输出一个 2 秒的脉冲
TP(Timer := T3,
    IN := I0.0,
    PT := T#2S);
Q0.0 := T3.Q;

4.2 计数器:CTU、CTD

计数器,顾名思义就是数数的。但PLC里的计数器,比你想的要聪明一点。它不光能数,还能设定目标值,到了就干活。

4.2.1 CTU(加计数器)

每来一个上升沿,当前计数值CV就加1。当CV大于等于预设值PV时,输出Q变为1。你可以用R端复位,把CV清零。

// CTU 示例:I0.0 每接通一次,计数加1,计满10次后 Q0.0 输出
CTU(Counter := C1,
    CU := I0.0,
    R := I0.1,
    PV := 10);
Q0.0 := C1.Q;
实用技巧: 做产品计数时,我建议把计数器的PV值设得比实际需求大一点,然后用比较指令去判断。这样方便后期调整,不用改程序里的硬编码。

4.2.2 CTD(减计数器)

CTD跟CTU相反。每来一个上升沿,CV减1。当CV小于等于0时,输出Q变为1。它也有一个加载端LD,可以把PV值预装到CV里。

我个人习惯用CTD做“倒计时”显示。比如一个工位需要处理10个工件,每处理一个减1,减到0就提示完成。这种逻辑比用CTU加完再比较要直观得多。

// CTD 示例:初始值10,每来一个脉冲减1,减到0时输出
CTD(Counter := C2,
    CD := I0.0,
    LD := I0.1,
    PV := 10);
Q0.0 := C2.Q;

4.3 比较指令

比较指令就是用来比大小的。等于、大于、小于、大于等于、小于等于、不等于,一共六种。在PLC里,比较的结果是一个布尔值(真或假),可以直接驱动线圈或者控制程序流程。

我记得有一次调试一个恒压供水系统,PID的输出要跟设定值比较,然后决定是否切换水泵。当时就是用比较指令做的逻辑判断,简单又可靠。

// 比较指令示例:当 MW10 大于等于 50 时,Q0.0 输出
IF MW10 >= 50 THEN
    Q0.0 := TRUE;
ELSE
    Q0.0 := FALSE;
END_IF;
指令 含义 应用场景
== 等于 判断是否达到目标值
> 大于 超限报警
< 小于 欠量检测
>= 大于等于 启动条件判断
<= 小于等于 停止条件判断
<> 不等于 状态异常检测

4.4 传送指令

传送指令,说白了就是“复制粘贴”。把一个数据从一个地方搬到另一个地方。在西门子PLC里,最常用的是MOVE指令。它可以传送字节、字、双字、甚至整个数组。

你可能会问:直接赋值不就行了?但在PLC里,有些数据块或者外设地址,必须用MOVE才能正确读写。比如从模拟量输入模块读数据,MOVE一下,数据格式才正确。

// MOVE 指令示例:将 MW20 的值传送到 MD30
MOVE(IN := MW20,
     OUT := MD30);
我的习惯: 做数据初始化时,我经常用MOVE指令把0传送到所有相关变量里。这比在变量表里一个个设默认值要快得多,而且程序启动时执行一次,确保状态干净。

4.5 算术运算指令

算术运算就是加减乘除,还有取余、取整、三角函数等。在PLC里,这些指令通常用于处理模拟量信号、计算PID输出、或者做数据转换。

举个例子:一个4-20mA的传感器,读进来的数值是0-27648。你要把它转换成实际的温度值,就得用算术运算。先减偏移,再乘系数,最后加零点。这一套下来,加减乘除全用上了。

// 算术运算示例:将模拟量输入 AIW0 转换为实际温度值
// 假设 0-27648 对应 0-100 摄氏度
#temp_real := INT_TO_REAL(AIW0);
#temp_real := #temp_real * 100.0 / 27648.0;
指令 功能 注意事项
ADD 加法 注意数据类型,避免溢出
SUB 减法 结果可能为负,确认变量类型
MUL 乘法 乘积可能超出范围,建议用大类型
DIV 除法 除数不能为0,否则CPU会报错停机
MOD 取余 常用于循环计数或分频
避坑指南: 我曾经在一个项目中,因为除法指令的除数为0,导致CPU直接停机。生产线停了半小时,损失不小。从那以后,我每次做除法前,都会加一个判断:如果除数为0,就跳过去或者给一个默认值。这个习惯,救了我好几次。

好了,这一章的内容就这些。定时器、计数器、比较、传送、算术运算,这些指令组合起来,能解决现场90%的控制逻辑。下一章,咱们聊聊更高级的——功能块和函数调用。到时候你会发现,PLC编程其实跟写软件差不多,模块化、复用性,都是好东西。