首页 > 解决方案 > TwinCAT 3:将“F_GetSystemTime”与本地 Windows 时间同步?

问题描述

我正在开发一个应用程序,在该应用程序中我使用“F_GetSystemTime”对高精度数据进行时间戳记。此函数返回自 1601 年 1 月 1 日以来的 100ns 间隔数。

我还通过 NTP 服务器将本地 Windows 时间同步到全球网络时钟。这可确保日历系统时间不会长期漂移。

但是,我遇到了一个问题,“F_GetSystemTime”似乎与 Windows 时间不同步。在几周的时间里,我的“F_GetSystemTime”出现了明显的偏差。

有没有办法让“F_GetSystemTime”与我的 Windows 时间同步?

标签: twincat

解决方案


您可以构建一个具有任务周期精度的内部计数器。假设您有一个 10 毫秒的 PLC 周期,您可以使用 10 毫秒的时间戳记录您的数据。如果您想更精确,您可以减少主要 plc 任务的周期时间,或者创建一个具有更快周期的单独任务。

另一种可能性是使用带有过采样的快速 IO,例如 el1262。

这是一个如何定义内部计数器的原始示例:

声明部分:

PROGRAM MAIN
VAR
    bInit           : BOOL;
    nTime           : UINT;
    tBufferTime     : TIME;
    dtBufferDT      : DT;
    nCalcBuffer     : UDINT;
    sMs             : STRING;
    sLogTime        : STRING;
    sLogTimeWithMs  : STRING;
    stSystemTime    : TIMESTRUCT;
    fbLocalTime     : FB_LocalSystemTime;
END_VAR

实现部分:

fbLocalTime(bEnable := TRUE);
IF NOT bInit
THEN
    dtBufferDT := SYSTEMTIME_TO_DT(fbLocalTime.systemTime);
    IF fbLocalTime.bValid 
    THEN
        bInit := TRUE;
    END_IF
ELSE
    nTime := nTime + 1;
    tBufferTime := UINT_TO_TIME(nTime*10);
    IF tBufferTime = T#1S
    THEN
        //Add a second to your system time
        ntime := 0;
        nCalcBuffer := DT_TO_UDINT(dtBufferDT)+1;
        dtBufferDT := UDINT_TO_DT(nCalcBuffer);
        sLogTime := DT_TO_STRING(dtBufferDT);
        sLogTimeWithMs := sLogTime;
    ELSE
        //Add ms string time-stamp
        sMs := TIME_TO_STRING(tBufferTime);
        sLogTimeWithMs := CONCAT(sLogTime,sMs);
    END_IF
END_IF

sLogTimeWithMs 将显示如下内容:

'DT#2019-09-21-14:30:28T#530ms'

为您提供 10 毫秒精度的正确时间,无需进一步同步。

然后,您可以对字符串进行润色,以便将其从不需要的字符(如 DT#、T# 或 ms)中清除。


推荐阅读