Configure CompactRIO to Synchronize to NIST Servers with SNTP

Updated Aug 14, 2023



  • cRIO-9012
  • cRIO-9014
  • cRIO-9022
  • cRIO-9023
  • cRIO-9024
  • cRIO-9025
  • cRIO-9072
  • cRIO-9073
  • cRIO-9074
  • cRIO-9075
  • cRIO-9076
  • sbRIO-9601
  • sbRIO-9602
  • sbRIO-9605
  • sbRIO-9606
  • sbRIO-9611
  • sbRIO-9612
  • sbRIO-9623
  • sbRIO-9626
  • sbRIO-9631
  • sbRIO-9632
  • sbRIO-9633
  • sbRIO-9636
  • sbRIO-9642

How do I configure my CompactRIO Real-Time VxWorks controller to synchronize to SNTP servers?

PXI, Desktop ETS, FieldPoint, Industrial Controller, Smart Camera, and Linux Real-Time targets do not natively support SNTP synchronization. This process only applies to CompactRIO controllers running the VxWorks operating system (OS). To verify which OS is running on your controller, please reference Real-Time Controllers and Real-Time Operating System Compatibility.

As of LabVIEW Real-Time 8.6, CompactRIO real-time controllers using the VxWorks operating system can be configured to synchronize to SNTP servers.

To configure the controller to synchronize to an SNTP server, go through the following steps:

1. FTP the ni-rt.ini file from the controller to your Windows machine.

2. Add the following lines to the ni-rt.ini file of the controller in the time sync section at the bottom. 
3. FTP the modified ni-rt.ini file back to the controller. After updating the ni-rt.ini file and rebooting, the cRIO controller will automatically implement synchronization to the SNTP server.

The following table describes the .ini tokens:
source_prioritystringsntpREQUIREDLists the relative priority of installed time sync plug-ins. For cRIO, the possible options are rtc, dio, and sntp.
source.sntp.enableboolfalseREQUIREDSet to true to enable the SNTP time sync plug-in. Set to false to disable.
source.sntp.addressstring0.0.0.0REQUIREDSpecifies the IPv4 address of the SNTP time server.  Choose a server in your region from the NIST Internet Time Service Clock link below. Use "." delimited address. Using a named address, like does not work at this time.
source.sntp.intervalint60RecommendedBy default the SNTP client driver sleeps for an interval between successive time server polls. Set a new delay, specified in seconds, to adjust the interval.
source.sntp.portint123OptionalBy default SNTP uses a known port to contact the time server. Set a new port number if the time server is on a non-standard port.
source.sntp.verboseboolfalseOptionalBy default SNTP client driver errors are silently discarded. Set to true to enable display of verbose errors in the console out.
source.sntp.logboolfalseOptionalSet to true to log timestamps to a file. This should only be used for debugging purposes. When set to true, the log will be located under ni-rt\system\ts_sntp_log.txt

Additional Information

Example of the ts_sntp_log.txt (64-bit Hex):
currentLocalTimeNS, frequencyHz, t1_raw, t2_ns, t3_ns, t4_raw
30744de63d52117c: 98989929.000000, 000000004b7deac0, 30744e740a609a99, 30744e740a60ee36, 000000004b90fef7
currentLocalTimeNSLocal time on the cRIO
frequencyHzClock processor frequency
t1_rawOriginate timestamp, time request sent by client
t2_nsReceive timestamp, time request received by server
t3_nsTransmit timestamp, time reply sent by server
t4_rawDestination timestamp, time reply received by client

If we convert the timestamps from the above example to decimal, we get:

t1_raw = 1,266,543,296
t2_ns = 3,491,501,871,416,253,081
t3_ns = 3,491,501,871,416,274,486
t4_raw = 1,267,793,655

However, t1_raw and t4_raw aren't that useful to us. Instead, we need to convert each of them to a duration since the controller was last booted:

t1_raw = 0x4b7deac0 = 1,266,543,296 ticks
t1_duration_since_boot = (tick count * nanoseconds per second / frequency) = (1,266,543,296 * 1e9 / 98,989,929) = 12,794,668,192 nanoseconds (~12.7 seconds)
t4_duration = 12,807,299,366 ns (~12.8 seconds)

Now we can calculate a meaningful value for t when this exchange occurred:

t = ((t2 - t1) + (t3 - t4)) / 2
t = ((3491501871416253081-12794668192) + (3491501871416274486-12807299366)) / 2
t = 3,491,501,858,615,279,616 ns

This value gets saved in a variable in software. When our RT controller needs to know what time it is, it reads the current tick count, converts that into a duration (tick * 1e9 / freq), and then adds this t value. This value represents the difference between a local counter and the NTP server's counter, but it does not represent the amount of error in our local timestamps (our offset from reference).

Calculating our instantaneous offset from the NTP time reference with this data isn't really possible. What we can do, however, is look at how the t value changes over time. The difference between a new t value and the previous t value will tell us how much our local concept of time has drifted away from the NTP master during the previous sync interval. This can give us a rough idea of our offset from reference.

Additionally, the following two methods can be used to evaluate server performance:

1. Calculate the roundtrip delay d and local clock offset t:
d = (t4_raw - t1_raw) - (t2_ns - t3_ns) 
t = ((t2_ns - t1_raw) + (t3_ns - t4_raw)) / 2

2. Compare local time on the cRIO to the server time with the following equation: 
(t2_ns + t3_ns) / 2

The SNTP is a simplified subset of the Network Time Protocol (NTP). Additional options for other Time Servers can be found in the related links section below.

SNTP synchronization does a large correction of the date-time on boot. After boot, it adjusts the processor clock to account for drift.  The algorithm has an error tolerance but if you exceed that tolerance (i.e. if you are too far out of sync) it will stop trying to adjust the processor clock to synchronize. Calling the Set Date & Time VI typically causes the clock to move beyond the algorithm error tolerance.