Use NTP provider
An NTP provider is available on the CX70xx from image version 140501 or higher.
The NTP provider can be used on different CX70xx Embedded PCs to provide approximately the same time. There is typically a deviation of ±5 ms between two CX70xxs.
Further information on how to insert the NTP provider into TwinCAT as a TcCOM module and put it into operation can be found here: https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_grundlagen/6326712203.html&id=
Example program for using the NTP provider
Variable declaration in the ST editor
PROGRAM TimeSync
VAR
(*
Time format:
FileTime64 8 Byte len begin 1.1.1601 Bit/100ns
DCTime64 8 Byte len begin 1.1.2000 Bit/100ns
*)
Test_FileTime64:T_FILETIME64; (* not used only to see where
this time begin to see the different *)
Test_DCTime64:T_DCTIME64; (* not used only to see where
this time begin to see the different *)
nLocalTime : T_FILETIME64; // Filetime 64 - Local RTOS Time
nPLC_DC_TASKTime : T_FILETIME64; (* Filetime 64 - Local DC Time | Local DC Time =
System Time see DiffSysTimeToPLCDCTime *)
nSysTime AT %I* : T_FILETIME64; // Filetime 64 - Sytem Time
nExtTime AT %I* : T_FILETIME64; // Filetime 64 - TCNet Ext NTP Time
nSysToExtTimeOffset AT %I* :LINT; // Offset this is the offset from ExtTime to SysTime
nSysToExtTimeDeviation AT %I* :LINT; (* Only for Info: Diff from NTP to the NPT Filter
time is it < 1ms then is bIsSynchronized = TRUE *)
bIsConnected AT %I*:BOOL; // Connection to the NTP Server
bIsSynchronized AT %I*:BOOL; // see nSysToExtTimeDeviation
FB_LocalSystemTime: FB_LocalSystemTime; // Functionblock for read the local RTOS Time
dt_LocalTime: DT; // Time & data - local RTOS Time
dt_PLC_DC_TASKTime: DT; (* Time & data - This is the time from the TaskInfo Array, this
is the same time as the Sytem Time from the NTP Object *)
dt_nSysTime: DT; // Time & data - Sytem Time from the NTP Object
dt_nExtTime: DT; // Time & data - NTP Object Ext NTP Time
PlcTaskSystemInfo : PlcTaskSystemInfo; // Task Info
DiffSysTimeToPLCDCTime: LINT; // Local DC Time = System Time
DiffLocalTimeToExtTime: LINT; (* local Time - ExtTime = same time like
the nSysToExtTimeOffset Time *)
FB_EcDcTimeCtrl64_1:FB_EcDcTimeCtrl64; // FB to get Sec/min/Hour... from a DCTime64
nExtTime64: ULINT; // Format DCTime64 from nExtTime
sec_1: WORD; // nExtTime Sec
Min_1: WORD; // nExtTime Min
msec_1: WORD; // nExtTime mSec
nLocalTimeDC64: ULINT; // DCtime64 - from local filetime64
MaxPLCTime: UDINT;
lrTimeoffset: LREAL; // Offest Time in LREAL [ms]
lrTimeDeviation: LREAL; (* Deviation Time [ms] this time show you the diff to the
NTP filter time, if its <1ms the is bIsSynchronized = TRUE *)
FB_CX7000_LED_WD: FB_CX7000_LED_WD; // NPT Status via WD LED from CX7000
END_VAR
Program in the ST editor
PlcTaskSystemInfo:=_TaskInfo[1]; (* Get Task Info Data we need it to read the
PlcTaskSystemInfo.DcTaskTime *)
dt_PLC_DC_TASKTime:=Systemtime_TO_DT(DCTime64_TO_SYSTEMTIME(LINT_TO_ULINT(PlcTaskSystemInfo.DcTaskTime))); // Get Local DC Time to DT
nPLC_DC_TASKTime:=DCTIME64_TO_FILETIME64(LINT_TO_ULINT(PlcTaskSystemInfo.DcTaskTime)); // Get Local DC Time to FileTime64
MaxPLCTime:=MAX(PlcTaskSystemInfo.LastExecTime,MaxPLCTime);
lrTimeoffset:=LINT_TO_LREAL(nSysToExtTimeOffset)/1000/10; // Read NTP Offset Time and convert it to Real in [ms]
lrTimeDeviation:=LINT_TO_LREAL(nSysToExtTimeDeviation)/1000/10; // Read NTP Offset Time and convert it to Real in [ms]
// Read the local time from RTOS
FB_LocalSystemTime(
sNetID:= ,
bEnable:=TRUE ,
dwCycle:= ,
dwOpt:= ,
tTimeout:= ,
bValid=> ,
systemTime=> ,
tzID=> );
dt_LocalTime:=SystemTime_TO_DT(FB_LocalSystemTime.systemTime);
nLocalTime:=SystemTime_TO_Filetime64(FB_LocalSystemTime.systemTime);
dt_nSysTime:=Filetime64_TO_DT(nSysTime); // Convert nSysTime to date & time
dt_nExtTime:=Filetime64_TO_DT(nExtTime); // Convert nExtTime to date & time
DiffSysTimeToPLCDCTime:=ULINT_TO_LINT(nPLC_DC_TASKTime-nSysTime); // Must be 0 because SysTime = Local DC Time
DiffLocalTimeToExtTime:=ULINT_TO_LINT(nExtTime-nPLC_DC_TASKTime); // Same diff like nSysToExtTimeOffset
// Ext NTP object as trigger for Outputs
nExtTime64:=FILETIME64_TO_DCTIME64(nExtTime);
FB_EcDcTimeCtrl64_1.A_GetMilli (in:=nExtTime64,get=>msec_1);
FB_EcDcTimeCtrl64_1.A_GetSecond (in:=nExtTime64,get=>sec_1);
FB_EcDcTimeCtrl64_1.A_GetMinute (in:=nExtTime64,get=>Min_1);
// Toggle Outpt every Sec
IF (sec_1 MOD 2) =0 THEN
gvl.bCX7028_Out_4:=TRUE;
ELSE
gvl.bCX7028_Out_4:=FALSE;
END_IF
// Set DO NTP Status
gvl.bCX7028_Out_1:=bIsConnected;
gvl.bCX7028_Out_2:=bIsSynchronized;
// WD LED from CX7000
// Red - no connection
// Green flashing - it is connected to NTP Server but it is not sync (that means that the filter is active and the synchonsation to the NTP Server is running - not with TC!)
// Green on - connection and synchonsation is running
FB_CX7000_LED_WD(
bEnable:=TRUE ,
eLED:= ,
tFlashingTimeP1:= ,
tFlashingTimeP2:= ,
bError=> ,
nErrorID=> );
IF bIsConnected AND NOT bIsSynchronized THEN
FB_CX7000_LED_WD.eLED :=Tc2_SystemCX.E_CX7000_LED.LED_flashing_GREEN_OFF;
ELSIF bIsConnected AND bIsSynchronized THEN
FB_CX7000_LED_WD.eLED :=Tc2_SystemCX.E_CX7000_LED.LED_GREEN ;
ELSE
FB_CX7000_LED_WD.eLED :=Tc2_SystemCX.E_CX7000_LED.LED_RED ;
END_IF