该如何处理?SYS_TIME 作用于 ABB PLC代码系统编程返回一个DWORD,表示PLC开机后的毫秒数。(或者可能是硬复位其他事件?找不到这方面的文档。)
在Codesys中,一个DWORD的最大大小是2。32-1 = 4,294,967,295.
这意味着 SYS_TIME只过了49.7天就溢出来了!
谁能确认一下SYS_TIME函数在49.7天过后到底返回什么?它是否会整数溢出并重新从零开始计数?
这对使用SYS_TIME函数有很重要的影响,比如警告某个事件发生后多久了。(例如,通过modbus读取远程设备)。
假设这只是一个整数溢出,并且SYS_TIME重置为零,那么程序员可以通过重置他们正在使用的变量来记录最后已知的事件时间来处理这个问题。
(* Assuming now, last_event_time are suitably declared DWORDs *)
now := SYS_TIME(TRUE);
IF last_event_time > now THEN
last_event_time := 0;
END_IF
(* continue, performing check of how long since last event occurred etc.... *)
我希望我漏掉了什么东西,能提供一个替代的方法。
然而--这是一个GOTCHA,可能会绊倒一个没有想到这一点的PLC程序员,导致一个表面上功能齐全的PLC程序在现场使用49天后失效。
如果能有一个替代SYS_TIME的函数,返回一个LWORD,可以使用50亿年不间断的服务,那将会很有帮助。)
NB - 我相信这个函数可能是针对ABB AC500系列PLC的,而不是标准的Codesys函数,所以这个问题主要是针对ABB &ABB PLC程序员的。
进一步研究,我确认了两件事。
我的问题的第二部分(什么是处理这个问题的最佳方法?
有几个选项,但我会使用以下任何一个选项。
读取系统日期和时间并保持更新。使用DT时,您将获得1秒的分辨率。如果你先将它们转换为DWORD(纪元时间),就很容易在DT之间进行比较。请看我的 Codesys时间更新的旧答案. 注意,如果你计算像DT1-DT2这样的东西,你会得到一个TIME ->的结果;同样也可能出现溢出问题。这就是为什么DT_TO_DWORD会是好主意。
自己做时间。你的PLC有一个周期时间,它应该总是精确的相同。用它来计算。
这是一个简单的例子,有不同的数据类型。
注意,如果需要的话,也可以使用一些Codesys库来读取周期时间,虽然不知道是哪一个。例如,请看 这个.
PROGRAM PRG_Time
VAR CONSTANT
TASK_CYCLE_TIME_MS : WORD := 10; //Update this!
END_VAR
VAR_OUTPUT
Total : LREAL;
TotalMilliseconds : LWORD;
TotalSeconds : DWORD;
Milliseconds : WORD;
END_VAR
Total := Total + TASK_CYCLE_TIME_MS / 1000.0;
TotalMilliseconds := TotalMilliseconds + TASK_CYCLE_TIME_MS;
Milliseconds := Milliseconds + TASK_CYCLE_TIME_MS;
//Calculate seconds
IF Milliseconds >= 1000 THEN
TotalSeconds := TotalSeconds + 1;
Milliseconds := Milliseconds - 1000;
END_IF
该 LREAL
是精确到毫秒的。所以这里基本上是以LWORD形式的SYS_TIME(简称为 TotalMilliseconds
)