结论
不要搞这些花里胡哨的。
目的
一些动作执行后,需要延时一段时间后再继续执行下面的动作。
现在的做法是,每个延时都用一个定时器。
这个做法的缺点是用的定时器太多了,并且都是局部符号,管理起来也不方便。
现在想写一个功能块,
输入需要延时的100ms的数量num_of_100ms,
功能块中用一个T0来计时,
T0的值到达指定的数量num_of_100ms后,则输出一个完成标志位。
程序
于是V0.1版本如图所示
有经验的老司机一眼就看出问题了,这个功能块没法用。
例程如下,创建两个实例TEST0(延时1000ms)和TEST1(延时2000ms),等待时间远超2000ms后,结果如下。
想要的功能是这样的:1秒后M101置位,再过1秒,M102置位。
但现在只有M101置位了。说明有问题。
查看实例TEST1,如下图所示,T0的值停留在10了。也就是说,T0到达计时后,数值就不再增加。那该怎么办呢?
如果TMR被使能,并且计时器的值达到指定值,就会停止计时。
那么只要到达指定值后,失能该实例,另外一个实例中的TMR就能继续计时了。
修改Delay_100ms功能块
修改程序
实验结果:
置位M100,1秒后,M101被置位,再过1秒,M102被置位。
满足要求。
改进
每次调用这个功能块,都要在前面加一个常闭触点,总有些麻烦。
把常闭触点放在功能块中,就可以了。。。个屁
电脑永远不会如你所愿,实际运行结果如下,由于delay_done被置位,TMR指令失效,T0不再计时,即使另一个实例中使能了T0,也无效。
那么上一个版本为什么可以呢?因为delay_done在功能块外面,它触发后,功能块就不再执行了。而这个版本,delay_done触发后,功能块依然在执行,TMR指令会被扫描。
那么要解决的核心问题就是:
delay_done触发后,让TMR不再被扫描,唯一的做法就是在功能块外面加上delay_done,
但又不想每次调用功能块的时候再加一个常闭触点,那么只能写2层调用了。
问题又来了,两个实例的计数是独立了,但是只能计数1次。
计数到达后,手动复位delay_done对应的外部继电器M101和M102,再次调用功能块,M101和M102是直接置位的,
因为delay_done置位后,TMR指令失效,但未清零,下次TMR指令使能时,还是之前那个值。
仔细一想,如果某一个实例计时到达后,就清零计时器,那么其他实例的计时不就错了吗?
所以要把计时的数量保存在每个实例中,由每个实例自己来对100ms的数量计数。
首先要明确一点,T0只有一个,要让所有实例公用T0,那么T0必须一直使能并计数,而不是由实例来控制使能。
修改程序如下,希望每100ms一个脉冲,对计数器累加。但实际情况是,没有累加。可能是TMR的S2设置的太小了。这样的话,100ms只能用来对1000ms计时了。
我现在只想发一个微笑😄
指定了T0,结果自说自话用了T5,(我当然知道是我指定的方式不对)。
这他妈当然不会计数了!
如果共用T0,让T0一直计数,由实例来主动读取T0的值,然后每次读取,与第一次读取的值做差,确实可以做到延时,但这样大大增加了CPU的计算量,得不偿失。
所以,定时器够用的话就凑活用吧。