0

ABB PLC/codesys 编程中的SYS_TIME函数返回一个 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 天后经过广泛测试而失败。

如果有一个返回 LWORD 的 SYS_TIME 替代方案,这将非常有帮助,这对 50 亿年的不间断服务有好处:-)

注意 - 我相信这个功能可能特定于 ABB AC500 系列 PLC,而不是标准的 Codesys 功能,所以这个问题主要针对 ABB 和 ABB PLC 程序员。

4

2 回答 2

0

选项很少,但我会使用以下任何一种

  1. 阅读系统日期和时间并保持更新。使用 DT 时,您将获得 1 秒的分辨率。当您首先将它们转换为 DWORD 时(纪元时间),很容易在 DT 之间进行比较。请参阅我对 Codesys 时间更新的旧答案。请注意,如果您计算类似 DT1-DT2 的内容,您将得到 TIME -> 可能出现相同的溢出问题。这就是为什么 DT_TO_DWORD 是个好主意。

  2. 让自己的时间。您的 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足够精确到毫秒。所以基本上这里是一个 SYS_TIME 作为 LWORD (the TotalMilliseconds)

于 2020-05-25T05:12:57.530 回答
0

进一步研究这一点,我已经确认了两件事:

  1. SYS_TIME 绝对是 ABB AC500 的特定功能,包含在库 SysInt_AC500_V10.lib 中。
  2. 引用 ABB AC500 的在线帮助:“49 天后达到溢出。此后,计数器在 0 处重新启动。”。这样就回答了关于函数行为的部分。

我的问题的第二部分(处理这个问题的最佳方法是什么?)仍然是开放的......

于 2020-05-24T12:50:50.240 回答