S7-1500 可以使用IEC定时器和SIMATIC定时器,IEC定时器仅占用CPU的工作存储器资源,可使用的数量与工作存储器大小有关;而SIMATIC定时器是CPU特定的资源,数量固定。例如CPU1515-2PN的SIMATIC定时器个数是2048个(CPU技术数据叫S7定时器)。两种定时器相比较,IEC定时器可设定的时间要远远大于SIMATIC定时器,时间精度也高。
S7-1500 SIMATIC定时器
S7-1500 IEC定时器
S7-1500 定时器常见问题
注:SIMATIC定时器从S5系列PLC就开始使用,而IEC定时器从S7-300/400才开始使用,必须使用背景DB。S7-300/400 IEC定时器类型比较少,在S7-1500/1200 指令中增加了IEC定时器类型,使用时通常采用多重背景数据块。
S7-1500 定时器指令位置参见图1。
图1 定时器指令位置
SIMATIC定时器包含以下五种: S_PULSE:脉冲定时器 S_PEXT:扩展脉冲定时器 S_ODT:接通延时定时器 S_ODTS:保持型接通延时定时器 S_OFFDT:关断延时定时器
下边以S_ODT(接通延时定时器)为例简单说明SIMATIC定时器的使用方法。
S_ODT 指令管脚参数参考如下表1。
表1:
S_ODTS 定时器工作时序如图2。
图2 S_ODT 时序图
从基本指令的“定时器操作/原有”拖拽指令 S_ODT 放入程序段中,给管脚填写相关参数。见图3。
图3 添加S_ODT 定时器
下载程序,将M10.0置个脉冲信号,定时器T0开始工作,如图4。
图4 T0 定时器工作
定时器T0执行10S后给予输出,将M10.2置1,如图5。
图5 T0定时器到时输出
使用定时器需要使用定时器相关的背景数据块或者数据类型为IEC_TIMER(或TP_TIME、TON_TIME、TOF_TIME、TONR_TIME)的DB块变量,不同的上述变量代表着不同的定时器。
注:S7-1500的IEC定时器没有定时器号(即没有T0、T37这种带定时器号的定时器)。
S7-1500包含四种定时器:
此外还包含复位定时器(RT)和加载持续时间(PT)这两个指令。
指令位置参见上图1,定时器引脚参考下表2,定时器使用及时序图参考下表3。这四种定时器又都有功能框和线圈型两种,区别参见常见问题3。
输入的变量 | |||
---|---|---|---|
名称 | 说明 | 数据类型 | 备注 |
IN | 输入位 | BOOL | TP、TON、TONR:0=禁用定时器,1=启用定时器TOF:0=启用定时器,1=禁用定时器 |
PT | 设定的时间输入 | TIME | |
R | 复位 | BOOL | 仅出现在TONR指令 |
输出的变量 | |||
名称 | 说明 | ||
Q | 输出位 | BOOL | |
ET | 已计时的时间 | TIME |
表2 定时器引脚汇总
生成脉冲 LAD:
或-( TP )- SCL:TP
表3 定时器使用及时序图
S7-1500定时器创建有以下几种方法:
1. 功能框指令直接拖入块中,自动生成定时器的背景数据块,该块位于“系统块>程序资源”中,参见图6。
图6 自动生成定时器的背景数据块
2. 功能框指令直接拖入FB块中,生成多重背景,参见图7。
图7 多重背景
3. 功能框指令直接拖入FB、FC块中,生成参数实例,从TIA博途V14开始,参见图8。
图8 参数实例
4. 在DB块、FB的静态变量、FC和FB的INOUT变量中新建IEC_TIMER、TP_TIME、TON_TIME、TOF_TIME、TONR_TIME(后面四个从TIA博途V11开始)类型变量,在程序中将功能框定时器指令拖入块中时,在弹出的“调用选项”页面点击“取消”按钮,之后将该建好的变量填入指定位置。对于线圈型指令,这是首选方法。
(1) DB块中新建IEC_TIMER等类型变量(LAD/FBD),如果是IEC_TIMER等类型变量的数组,S7-1500从V2.0版本开始支持,参见图9~图11。
图9 DB块中的定义
图10 功能框定时器使用
图11 线圈型定时器使用
(2) FB的静态变量中新建IEC_TIMER等类型变量(LAD/FBD),如果是IEC_TIMER等类型变量的数组,S7-1500从V2.0版本开始支持,参见图12。
图12 静态变量中定义
(3) FC和FB的INOUT变量中新建IEC_TIMER等类型变量(LAD/FBD),如果是IEC_TIMER等类型变量的数组,S7-1500从V2.0版本开始支持,从TIA博途V14开始支持IEC_TIMER等类型变量的变长数组(ARRAY[#]),参见图13。
图13 INOUT中定义
(4) 以上三种方法的SCL版本,从TIA博途V14开始支持,参见图14。
图14 SCL中使用
从以上4个示例可以看出,IEC_TIMER、TP_TIME、TON_TIME、TOF_TIME、TONR_TIME五种数据类型没有本质的区别,可以互换使用,为使得程序明确,建议只使用定时器对应名字的数据类型。
5. 在插入DB时,选择IEC_TIMER类型的数据块,将该数据块填在指令上方。此种方法生成的数据块等同于第一种的背景数据块,位于“系统块>程序资源”中,从TIA博途V11开始,线圈型指令同样适用,参见图11。
图15 新建IEC_TIMER类型DB
1. 为什么定时器不计时?
答:可能原因如下:
(1)定时器的输入位需要有电平信号的跳变,定时器才会开始计时。如果保持不变的信号作为输入位是不会开始计时的。TP、TON、TONR需要IN从“0”变为“1”启动,TOF需要IN从“1”变为“0”启动。
(2)定时器的背景数据块重复使用。
(3)只有在定时器功能框的Q点或ET连接变量,或者在程序中使用背景DB(或IEC_TIMER类型的变量)中的Q点或者ET,定时器才会开始计时,并且更新定时时间。参考下表4。
不计时
表4 定时器的使用
2. 如何编程自复位定时器并产生脉冲?
答:正确答案参考表4,同时附上2种常见错误编程方式。 原因:S7-1500的定时器的时间更新发生在定时器功能框的Q点或ET连接变量时,或者在程序中使用背景DB(或IEC_TIMER类型的变量)中的Q点或者ET时。即如果程序中多次使用同一背景DB的Q点,或者既使用定时器功能框的Q点或ET连接变量,又使用背景DB的Q点,以上两种情况都会造成定时器在一个扫描周期内的多次更新,可能造成定时器不能正常使用的情况。
表5 自复位定时器示例
正确方法的流程,将程序根据指令分为两部分,如图16所示:
图16 分解正确指令
阶段1.初始"DB2".脉冲=False,于是"DB2".脉冲取反为True,触发计时器开始计时,输出的"DB2".脉冲=False,状态不变;定时时间不到,则始终在阶段1;
阶段2.当定时时间到发生在①所处的位置,在TON处定时器更新,Q输出True,因此输出的"DB2".脉冲=True,等到下周期时"DB2".脉冲取反为False,导致输出的"DB2".脉冲=False,等再到下周期时就回到了阶段1;
阶段3.当定时时间到发生在②所处的位置,不影响定时器的更新,需要到下一周期才会改变输出,就回到了阶段2。
从上可知,定时器实现了自复位,并且"DB2".脉冲=True只保持一个周期,形成了脉冲。
以第一个错误方法解释一下为什么这种方法不能实现自复位定时器并产生脉冲,如图17所示,将程序根据指令分为三部分:
图17 分解错误指令
阶段1.初始第一行"IEC_Timer_0_DB".Q=False,触发计时器开始计时,第二行,当定时时间不到,"IEC_Timer_0_DB".Q=False保持不变,输出的"DB2".脉冲=False;定时时间不到,则始终在阶段1;
阶段2.当定时时间到发生在①所处的位置,在第一行的"IEC_Timer_0_DB".Q处定时器更新,更新后,"IEC_Timer_0_DB".Q=True,取反为False,此时作为TON的输入,使得定时器复位,第二行的"IEC_Timer_0_DB".Q=False,输出的"DB2".脉冲=False,到下周期时就回到了阶段1;
阶段3.当定时时间到发生在②所处的位置,在第二行的"IEC_Timer_0_DB".Q处定时器更新,更新后,"IEC_Timer_0_DB".Q=True,输出的"DB2".脉冲=True,等到下周期时,"IEC_Timer_0_DB".Q=True,取反为False,此时作为TON的输入,使得定时器复位,第二行的"IEC_Timer_0_DB".Q=False,输出的"DB2".脉冲=False,等再到下周期时就回到了阶段1;
阶段4.当定时时间到发生在③所处的位置,不影响定时器的更新,需要到下一周期才会改变输出,就回到了阶段2。
从上可知无论定时器时间到发生在哪个点,定时器都可以实现自复位,但是只有当定时时间到发生在②所处的位置时,"DB2".脉冲=True只保持一个周期,形成了脉冲,而在①和③时"DB2".脉冲始终为False无法形成脉冲。在正常程序中②的执行时间在整个扫描周期中占比很小,因此只有很低的概率可以实现脉冲。所以不能使用此种方法,第二个错误方法与之类似。
3. 如何使用定时器实现精确定时?
答:不能做到。
举例来说,定时1s的接通延时定时器,当程序扫描到定时器功能框的Q点或ET时或者扫描到背景DB(或IEC_TIMER类型的变量)中的Q点或者ET时,如果时间为997ms,只会继续定时等下一次扫描,而下一次扫描到可能就是1003ms,此时定时器接通。也就是说几乎不可能正好1s接通,如果再配合计数器实现更长时间的定时,误差只会越来越大。
所以精确定时还是推荐使用循环中断(OB30)配合计数器来实现。
4. 定时器指令中,功能框和线圈型的区别?
答:原理上是完全一样的,细微区别:
(1) 功能框定时器上可以定义Q点或ET,在程序中可以不必出现背景DB(或IEC_TIMER类型的变量)中的Q点或者ET;而线圈型定时器必须使用背景DB(或IEC_TIMER类型的变量)中的Q点或者ET;
(2) 功能框定时器在使用时可以自动提示生成背景块,或者选择不生成;而线圈型定时器只能通过手动方式建立背景块;
(3) 线圈型定时器如果出现在网络段中间时不影响RLO的变化,如图18所示,"DB46".Static_1和I1.0同步变化。
图18 线圈型定时器示例
P.S.
系统数据类型 |
---|
说明
系统数据类型 (SDT) 由系统提供并具有预定义的结构。系统数据类型的结构由固定数目的可具有各种数据类型的元素构成。不能更改系统数据类型的结构。
仅当系统数据类型的类型相同且名称匹配时,才可相互分配。这一规则同样适用于系统生成的 PLC 数据类型,如 IEC_Timer 等。
系统数据类型只能用于特定指令。下表给出了可用的系统数据类型及其用途:
系统数据类型 | 长度(字节) | 说明 |
---|---|---|
IEC_TIMER | 16 | 声明有 PT、ET、IN 和 Q 参数的定时器结构。时间值为 TIME 数据类型。例如,此数据类型可用于“TP”、“TOF”、“TON”、“TONR”、“RT”和“PT”指令。 |
IEC_LTIMER | 32 | 声明有 PT、ET、IN 和 Q 参数的定时器结构。时间值为 LTIME 数据类型。例如,此数据类型可用于“TP”、“TOF”、“TON”、“TONR”、“RT”和“PT”指令。 |
IEC_SCOUNTER | 3 | 计数值为 SINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_USCOUNTER | 3 | 计数值为 USINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_COUNTER | 6 | 计数值为 INT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_UCOUNTER | 6 | 计数值为 UINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_DCOUNTER | 12 | 计数值为 DINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_UDCOUNTER | 12 | 计数值为 UDINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_LCOUNTER | 24 | 计数值为 UDINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
IEC_ULCOUNTER | 24 | 计数值为 UINT 数据类型的计数器结构。例如,此数据类型用于“CTU”、“CTD”和“CTUD”指令。 |
ERROR_STRUCT | 28 | 编程错误信息或 I/O 访问错误信息的结构。例如,此数据类型用于“GET_ERROR”指令。 |
CREF | 8 | 数据类型 ERROR_STRUCT 的组成,在其中保存有关块地址的信息。 |
NREF | 8 | 数据类型 ERROR_STRUCT 的组成,在其中保存有关操作数的信息。 |
VREF | 12 | 用于存储 VARIANT 指针。这种数据类型通常用于 S7-1200/1500 Motion Control 指令中。 |
SSL_HEADER | 4 | 指定在读取系统状态列表期间保存有关数据记录信息的数据结构。例如,此数据类型用于“RDSYSST”指令。 |
CONDITIONS | 52 | 用户自定义的数据结构,定义数据接收的开始和结束条件。例如,此数据类型用于“RCV_CFG”指令。 |
TADDR_Param | 8 | 指定用来存储那些通过 UDP 实现开放用户通信的连接说明的数据块结构。例如,此数据类型用于“TUSEND”和“TURSV”指令。 |
TCON_Param | 64 | 指定用来存储那些通过工业以太网 (PROFINET) 实现开放用户通信的连接说明的数据块结构。例如,此数据类型用于“TSEND”和“TRSV”指令。 |
HSC_Period | 12 | 使用扩展的高速计数器,指定时间段测量的数据块结构。此数据类型用于“CTRL_HSC_EXT”指令。 |
AssocValues | 16 | 定义数据结构。这将定义使用消息来发送哪些关联值。此数据类型用于“Gen_UsrMsg”指令。 |
调用 IEC 定时器 |
---|
说明
IEC 定时器可声明为单实例或多重实例并在程序代码中进行调用。
在块接口中,将 IEC 定时器声明为结构中多重实例的语法如下所示:
IEC 定时器声明为 ARRAY 元素
块接口中的声明
程序代码:
SCL |
---|
#MyARRAY[1].TOF(IN := <操作数>, PT := <操作数>) |
块接口中的声明
程序代码:
SCL |
---|
#MyARRAY[#index](IN := <操作数>, PT := <操作数>) |
匿名结构中的 IEC 定时器
块接口中的声明
程序代码:
SCL |
---|
#MyStruct.FirstTime.TOF(IN := <操作数>, PT := <操作数>) |
块接口中的声明
程序代码:
SCL |
---|
#MyStruct.FirstTime(IN := <操作数>, PT := <操作数>) |
全局数据块中的 IEC 定时器
数据块中的声明:
程序代码:
SCL |
---|
"MyGlobalDB".Timer.FirstTime.TOF(IN := <操作数>, PT := <操作数>) |
数据块中的声明:
程序代码:
SCL |
---|
"MyGlobalDB".Timer.SecondTime(IN := <操作数>, PT := <操作数>) |
在块接口中,将 IEC 定时器声明为元素
块接口中的声明
程序代码:
SCL |
---|
#Timer.FirstTime.TOF(IN := <操作数>, PT := <操作数>) |
块接口中的声明
程序代码:
SCL |
---|
#Timer.SecondTime(IN := <操作数>, PT := <操作数>) |
ARRAY DB 中的 IEC 定时器
ARRAY DB 中的声明:
程序代码:
SCL |
---|
"MyARRAYDB"."THIS"[0].FirstTime.TOF(IN := <操作数>, PT := <操作数>) |
ARRAY DB 中的声明:
程序代码:
SCL |
---|
"MyARRAYDB"."THIS"[0].SecondTime(IN := <操作数>, PT := <操作数>) |