2017-01-20 7 views
0

Wir arbeiten an einer Datenlogging-Anwendung in Beckhoff TwinCAT3. Um die Zeit zu erhalten, wir sind zur Zeit LTIME(), das Umwandeln dann, dass in C# ms mit:Wie bekomme ich den Unix-Zeitstempel in TwinCAT3?

ulong valA = reader.ReadUInt64(); // this gets the LTIME 
long ftime = (long)(valA/100); 
DateTime t = DateTime.FromFileTime(ftime); 
return (t.ToUniversalTime().Ticks - 621355968000000000)/10000; 

Es muss ein besserer Weg geben. Außerdem sehen wir einen Unterschied zwischen dieser Zeit und der Computerzeit (die in der Taskleiste).

Was ist der beste Weg, um MS seit 1970 (GMT) von der Computeruhr zu bekommen? Ich sehe NT_GetTime. Das sieht aus, als müssten wir dann Mathe auf der Struktur machen

Danke für alle Zeiger.

+0

Wichtiger Hinweis: Insbesondere wenn die Zeitspanne zwischen Ihren Datenpunkten sehr genau sein muss, ist es wichtig, wie Sie die Zeit auf der SPS auflösen. NT_GetTime ist jittering/nicht so genau. Siehe [Infosys] (https://infosys.beckhoff.com/content/1031/tcplclib_tc2_utilities/18014398544903307.html) –

Antwort

0

Der Schlüssel dazu ist FB_TzSpecificLocalTimeToFileTime zu verwenden, um den aktuellen T_FILETIME mit aktuellen Zeitzoneninformationen (ST_TimeZoneInformation) in UTC zu konvertieren. Dies wird Ihnen eine UTC-Windows-Dateizeit (Ticks) geben, die in UTC-Unix-Zeit umgewandelt werden muss.

Hier ist ein Funktionsblock Umsetzung dieses Prozesses:

Declaration

FUNCTION_BLOCK UnixTimestamp 
VAR_OUTPUT 
    seconds: ULINT; 
    milliseconds: ULINT; 
END_VAR 

VAR 
    localSystemTime : FB_LocalSystemTime := (bEnable := TRUE, dwCycle := 1); 
    getTimeZoneInformation : FB_GetTimeZoneInformation; 
    timeZoneInformation : ST_TimeZoneInformation; 
    specificLocalTimeToFileTime : FB_TzSpecificLocalTimeToFileTime; 
    fileTime: T_FILETIME; 
    onZerothSecondLastCycle : BOOL; 
END_VAR 

Implementation

// Get local system time 
localSystemTime(); 

// On the zeroth second of each minutesync timezone information 
IF (timeZoneInformation.standardName = '' OR (localSystemTime.systemTime.wSecond = 0 AND NOT onZerothSecondLastCycle)) THEN 
    getTimeZoneInformation(sNetID := '', bExecute := TRUE, tzInfo => timeZoneInformation); 
END_IF; 

// Convert local system time to unix timestamps 
specificLocalTimeToFileTime(in := Tc2_Utilities.SYSTEMTIME_TO_FILETIME(localSystemTime.systemTime), tzInfo := timeZoneInformation, out => fileTime); 
seconds := (SHL(DWORD_TO_ULINT(fileTime.dwHighDateTime), 32) + DWORD_TO_ULINT(fileTime.dwLowDateTime))/10000000 - 11644473600; 
milliseconds := (SHL(DWORD_TO_ULINT(fileTime.dwHighDateTime), 32) + DWORD_TO_ULINT(fileTime.dwLowDateTime))/10000 - 11644473600000; 

onZerothSecondLastCycle := localSystemTime.systemTime.wSecond = 0; 

Usage

VAR 
    unixTime: UnixTimestamp; 
    timestampSeconds: ULINT; 
    timestampMilliseconds: ULINT; 
END_VAR 

----- 

unixTime(); 
timestampMilliseconds := unixTime.milliseconds; 
timestampSeconds := unixTime.seconds;