Client - User defined timestamp clock source
In einigen Applikationen soll z.B. neben dem Sollwert auch ein Zeitstempel verwendet werden, der von einer externen Quelle stammt (z.B. einer GPS-Uhr). Dieses Beispiel zeigt die Implementierung einer Benutzerdefinierten Uhr/Uhrzeit für Zeitstempelungsaufgaben.
Download TwinCAT XAE Project (*.zip): Sample15.zip
Das hier beschriebene Beispiel nutzt die Statemachine, welche in dem Kapitel „Allgemeine Client - Projektstruktur“ beschrieben ist. Die States: 0,1,11 und 100 sind identisch zu der dort beschriebenen Statemachine. Andere States wurden für das Beispiel modifiziert oder auch neue States hinzugefügt.
Die TwinCAT IEC 61850 Client-Implementierung verwendet die Schnittstelle: „I_ScsmSystemClockEventSink“, um die Uhrzeit für Zeitstempelungsaufgaben abzufragen. Es ist möglich einen eigenen Funktionsbaustein zu verwenden, der diese spezielle Schnittstelle implementiert und den Client-Baustein so konfiguriert, dass dieser die neue Zeitquelle verwendet. In der globalen Variablenliste „TcTelecontrol“ wird dem Client-Baustein durch das Setzen der Eigenschaft „ipSystemClock:=fbMyClock“ die neue Zeitquelle zugewiesen. Der Client-Baustein wird danach jedes Mal die Methode: „OnGetSystemTime“ aufrufen, wenn von ihm ein neuer Zeitstempel benötigt wird. Die IEC 61850 Client-Server-Kommunikation verwendet Zeitstempel in mindestens zwei verschiedenen Formaten: UTC-Time und Binary-Time. Aus diesem Grund liefert diese Methode den Zeitstempel als Ausgangsvariablen in diesen zwei Formaten.
VAR_GLOBAL
ipCreator : I_AcsiCodeCreatorClass := GVL_AcsiVars.Creator.SetCodeRev(codeRev:=2).SetGuiVer(major:=1, minor:=0, build:=93, revision:=10);
fbIED : FB_IED_IED;
(* User defined clock (time stamp source) *)
fbMyClock : FB_MyClock;
fbIEDClient : FB_IEDClient := (fbConnection:=(ipIED:=fbIED, ipSystemClock:=fbMyClock, settings:=(sRemoteHost:='127.0.0.1')));
END_VAR
Das Beispiel demonstriert eine sehr einfache Software-Uhr, die mit Hilfe des RTC_EX-Funktionsbausteins realisiert wurde.
FUNCTION_BLOCK FB_MyClock IMPLEMENTS I_ScsmSystemClockEventSink
VAR
_tT : T_UtcTime:=(secondSinceEpoch:=DT#2021-04-01-00:00:00, quality:=(ClockNotSynchronized:=TRUE, ClockFailure:=FALSE, LeapSecondsKnown:=FALSE), fractionOfSecond:=[0,0,0]);(* Actual UTC time. *)
_tB : T_BinaryTime;(* Actual binary-time (EntryTime) *)
clock : RTC_EX:=(EN:=TRUE, PDT:=DT#2021-04-01-00:00:00, PMSEK:=0);
refreshTimer : TON:=(IN:=TRUE, PT:=T#1S);
END_VAR
METHOD FINAL Execute : BOOL
VAR_INPUT
END_VAR
refreshTimer();
IF Execute:=refreshTimer.Q THEN
refreshTimer(IN:=FALSE); refreshTimer(IN:=TRUE);
Update();
END_IF
METHOD FINAL OnGetSystemTime : BOOL
VAR_INPUT
ipAA: I_ScsmAssociationClass;(* Application association. If = 0 => optional or unknown. *)
END_VAR
VAR_OUTPUT
tT: T_UtcTime;(* UTC-time. *)
tB: T_BinaryTime;(* Binary-time *)
END_VAR
tT:=_tT;
tB:=_tB;
OnGetSystemTime:=TRUE;
METHOD FINAL SetClock
VAR_INPUT
tSet : DT;(* New time to set *)
END_VAR
clock(EN:=FALSE);
clock(EN:=TRUE, PDT:=tSet);
_tT.quality.ClockNotSynchronized:=FALSE;
Update();
METHOD FINAL Update
VAR_INPUT
END_VAR
clock();(* update clock time *)
(* convert to utc-time format *)
_tT.secondSinceEpoch:=clock.CDT;
_tT.fractionOfSecond:=LTIME_TO_UtcTimeFractionofSecond(in:=TIME_TO_LTIME(DWORD_TO_TIME(clock.CMSEK)));
Accuracy_To_UtcTimeQualityAccuracy(in:=E_UtcTimeAccuracy._03, bAccuracy0=>_tT.quality.Accuracy0, bAccuracy1=>_tT.quality.Accuracy1, bAccuracy2=>_tT.quality.Accuracy2, bAccuracy3=>_tT.quality.Accuracy3, bAccuracy4=>_tT.quality.Accuracy4);
(* convert to binary-time format *)
_tB.day:=Date_To_BinaryTime6Day(in:=DT_TO_DATE(clock.CDT));
_tB.timeOfDay:=DT_TO_TOD(clock.CDT) + DWORD_TO_TIME(clock.CMSEK);