代码之家  ›  专栏  ›  技术社区  ›  Izzo

TwinCAT 3:是否将“F\u GetSystemTime”与本地Windows时间同步?

  •  0
  • Izzo  · 技术社区  · 5 年前

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

    但是,我遇到了一个问题,即“F\u GetSystemTime”似乎与Windows时间不同步。在我的“F\u GetSystemTime”中有明显的漂移。

    有没有办法让“F\u GetSystemTime”与我的Windows时间保持同步?

    0 回复  |  直到 5 年前
        1
  •  0
  •   Filippo Boido    5 年前

    另一种可能是使用像el1262那样的带过采样的快速IOs。

    以下是如何定义内部计数器的原始示例:

    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将显示如下内容:

    '日期2019-09-21-14:30:28#530ms'

        2
  •  0
  •   Quirzo    5 年前

    使用 FB_LocalSystemTime dwCycle 秒。这样,块在被调用时总是给出当前时间,并保持自身的同步。我不认为你需要任何缓冲区计算等,只要运行这个代码每PLC周期。

    如果您的循环时间是10毫秒,则每次通话的输出都会改变10毫秒。当然,这可能不是99%的准确率,但应该做到这一点。当时间与Windows时间同步时,前一个值和当前值之间的增量当然会有一点变化。如果不正常,请将同步间隔增加到更小或更高的值。

    TIMESTRUCT ,它包含日期和时间以及毫秒。只是使用 SYSTEMTIME_TO_DT 转换它。请记住,在转换过程中毫秒是四舍五入的,因此它可能会更改秒数。您可以在之前将毫秒设置为0 保持秒数不变。

    //...
    
    VAR
        LocalSystemTime     : FB_LocalSystemTime;
        FirstTimeUpdateOK   : BOOL; //True after the time was synced OK at least once
        EmptyDateAndTime    : TIMESTRUCT := (wYear := 1970, wMonth := 1, wDay := 1);
    END_VAR
    VAR_OUTPUT
        SyncedTime          : TIMESTRUCT;
    END_VAR
    
    
    
    
    //First, set current time to 1970 if not updated yet.
    IF NOT FirstTimeUpdateOK THEN
        SyncedTime := EmptyDateAndTime;
    END_IF
    
    
    //Call the time sync block
    LocalSystemTime(
        bEnable := TRUE,    //Keep as TRUE always
        dwCycle := 5        //Sync with windows clock every 5 seconds (change to smaller/higher value to prevent small changes every 5 seconds)
    );
    
    
    IF LocalSystemTime.bValid THEN
        //Everything OK, we have valid time
        FirstTimeUpdateOK:= TRUE;
        SyncedTime := LocalSystemTime.systemTime;
    
    
    ELSIF FirstTimeUpdateOK THEN
        //We have once had the valid time, but not now. Show error?
        //...
    END_IF
    
    推荐文章