Remote Synchronization of Time Taggers

In high-precision applications such as distributed time monitoring, telecommunications, quantum communication, and quantum key distribution, synchronizing time-tagging devices across remote locations is crucial. When Time Taggers operate independently, their clocks run free, and even small differences in their frequencies accumulate over time, creating significant timing discrepancies across multi-device setups.

To overcome this challenge, a synchronization-agnostic and versatile approach is employed. This method supports any synchronization technology that provides a frequency reference signal (e.g., 10 MHz) and a 1PPS (Pulse Per Second) timing signal, as shown in the figure below. For example, the White Rabbit is a widely adopted technology that enables picosecond-level synchronization precision with sub-nanosecond accuracy across remote setups, as detailed in this application note. The synchronization process relies on the two timing signals combined with software-based solutions, including functionalities such as the ReferenceClock, to unify the time bases of the distributed Time Taggers. Users must ensure that their hardware infrastructure supports the required synchronization signals to enable this functionality. Moreover, when using the ReferenceClock with Time Tagger 20, an inherent timing error of approximately 200 ps needs to be considered. More details can be found in the setReferenceClock() documentation and the related in-depth guide (Software-Defined Reference Clock).

This tutorial demonstrates how to achieve remote synchronized operation of Time Taggers. It provides a step-by-step guide to synchronizing multiple Time Taggers across distributed locations, unifying their time bases, and merging time tag streams from remote network nodes for real-time processing using the TimeTaggerNetwork functionality, which supports simultaneous connections to multiple servers from version 2.18 onward.

../_images/Remote_Sync.svg

Establishing a common time base across distributed locations

A critical step in synchronizing Time Taggers across remote locations is establishing a unified time base. Within our approach, this is achieved by associating the 1PPS signal fed into the Time Tagger, which is generated at each location with an external clock locked to a Grand Master (GM), with the Coordinated Universal Time (UTC) provided by the host PC. To ensure accurate synchronization, the PC clocks at all locations must remain aligned to UTC with a time shift of less than 0.5 seconds. Synchronizing the PC clock is therefore essential because it allows the system to associate the 1PPS signal at each location with the correct UTC second, ensuring that all timing data is unified under a common temporal framework.

The PC clock alignment to UTC can be achieved using reliable synchronization protocols such as Network Time Protocol (NTP) or Precision Time Protocol (PTP). Standard operating system synchronization tools (e.g., Windows Time Service, Linux’s ntpd or chrony) configured to synchronize with either publicly available or internal time servers, are sufficient to maintain synchronization shift below 0.5 seconds. For enhanced robustness, ease of use, or advanced configuration options, dedicated synchronization software solutions such as the Meinberg NTP software package are recommended.

Starting a Time Tagger Server at each location

Once the PC clocks at all locations are aligned to UTC, the next step is to configure each Time Tagger to operate within a unified time base. By default, timestamps generated by a Time Tagger are relative to when the device was initialized in software. This means that if multiple Time Taggers start at different times, identical physical events occurring simultaneously at different locations receive different timestamps.

To synchronize the Time Taggers, enabling measurements across time tag streams generated at remote locations, the ReferenceClock must be activated. This ensures that all Time Taggers apply a UTC-based offset to their time base, allowing simultaneous events at remote locations to receive identical timestamps, regardless of when each Time Tagger was started. The ReferenceClock achieves this by locking the internal clock to an external distributed frequency reference (e.g., 10 MHz) and using the 1PPS signal to establish absolute time alignment.

To set up each Time Tagger, a connection to the device is first established in software. Hardware settings such as trigger levels and dead time should be configured according to the specific measurement requirements. Then, the ReferenceClock is enabled, aligning the internal time base with the external synchronization signals. Finally, a server is started on the host PC, making the Time Tagger accessible over the network for real-time data collection.

import TimeTagger

# Connect to the Time Tagger via USB
tagger = TimeTagger.createTimeTagger()

# Declare the channel names and corresponding physical connections
frequency_channel = 1
PPS_channel = 2

# Define the hardware settings here, such as trigger level or dead time.

# Enable the ReferenceClock
tagger.setReferenceClock(clock_channel=frequency_channel,
                         clock_frequency=10e6,
                         time_constant = 1e-4,
                         synchronization_channel=PPS_channel,
                         wait_until_locked=true)

# Start the Server.
# TimeTagger.AccessMode sets the access rights for clients.
# Port defines the network port to be used
tagger.startServer(access_mode=TimeTagger.AccessMode.Control,port=41101)

Warning

Activating the ReferenceClock shifts and rescales the internal time base of the Time Tagger. As a result, all ongoing measurements on every channel will be affected. Data recorded after activating the ReferenceClock will no longer be comparable with data acquired beforehand from the same Time Tagger instance.

Connecting to multiple Time Tagger Servers over the network

Once the Time Tagger servers are running at different locations, a client PC can connect to them to retrieve and process synchronized measurement data. The connection process relies on network communication, where the client searches for available Time Tagger servers and establishes a link to them.

To automatically discover servers on the local network, the function scanTimeTaggerServers() is used. This function sends multicast UDP messages to detect active Time Tagger servers and retrieve their IP addresses. However, its effectiveness depends on the network configuration. Since multicast messages typically remain within the same local subnet, their ability to reach servers across different subnets depends on whether the network routers forward multicast packets. If the function does not detect any servers, it is likely that multicast routing is either not enabled or unreliable in the network. In cases where scanTimeTaggerServers() fails to find a server, the user needs to know the IP addresses and network ports of the servers to connect to, when calling createTimeTaggerNetwork() on the client PC.

# Use the scanTimeTaggerServers() function to search for Time Tagger servers in the local network
servers = TimeTagger.scanTimeTaggerServers()
print("{} servers found.".format(len(servers)))
print(servers)

# Create a TimeTaggerNetwork instance and connect to the desired servers
server_addresses = ["192.168.1.100:41101", "192.168.1.101:41101"]  # Replace with the IPs of the servers to connect to
ttn = TimeTagger.createTimeTaggerNetwork(server_addresses)

Warning

When a TimeTaggerNetwork object is created and connected to multiple servers, the time tag streams from different locations are merged into a unified data stream for measurements. This merging process relies on a sorting algorithm and requires that all incoming time tag streams have similar timestamps, meaning the Time Taggers must be properly synchronized. If the time bases are not aligned, stream merging fails.

Accessing individual servers

When using a TimeTaggerNetwork object to connect to multiple Time Tagger servers, it is possible to access and control each individual server separately. This is particularly useful when extracting detailed device-specific information that is not channel-dependent, such as checking overflow states using methods like getOverflows().

The getServers() method of the TimeTaggerNetwork class returns a list of TimeTaggerServer objects, each representing one of the connected servers. These server objects act as proxies, providing access to all relevant control functions available in TimeTaggerBase and TimeTaggerHardware, as long as the servers were created with AccessMode::Control privileges. Unlike the TimeTaggerNetwork object, a TimeTaggerServer object cannot be used to perform measurements directly. Namely, it is not possible to pass the TimeTaggerServer object on to any measurement creator.

For example, to retrieve overflow information from a specific server:

# Retrieve the list of connected Time Tagger servers
servers = ttn.getServers()

# Access a specific server
server_A = servers[0]

# Retrieve overflow information from the server
overflows = server_A.getOverflows()

It is also possible to adjust hardware settings using either the TimeTaggerServer object or the globally mapped channels via the TimeTaggerNetwork object. Both approaches yield the same result:

# Adjust dead time via the server object
server_A.setDeadtime(1, 1000)

# Equivalent operation using TimeTaggerNetwork global channel mapping
ttn.setDeadtime(1001, 1000)

With the current Software, using TimeTaggerServer objects for configuration is primarily a convenience, as they serve as proxies for direct interaction with specific servers. However, TimeTaggerServer provides four specific functions that are not available in TimeTaggerNetwork: getAddress(), getAccessMode(), getClientChannel(), getReferenceClockState().

Verification of the synchronization technology using a single Time Tagger

To evaluate the precision of the synchronization technology, a single Time Tagger can be used before considering a multi-device setup. The proposed verification consists of enabling the ReferenceClock on one external reference, typically the master if there is a hierarchy, and using a second external reference as an input to the FrequencyStability measurement class. This allows direct analysis of the synchronization precision using built-in measurement tools.

The measurement provides stability metrics such as Allan Deviation (ADEV), Modified Allan Deviation (MDEV), and Time Deviation (TDEV), which quantify timing fluctuations over different timescales. These results characterize the synchronization performance and provide a reference before working with multiple Time Taggers.

The first external reference is connected to an input channel and used to enable the ReferenceClock. Since all analyses are performed on the same hardware, there is no need for a PPS signal for time synchronization. The second and additional external references are fed into other input channels and analyzed using the FrequencyStability measurement. The measurement runs over a range of averaging times to extract stability metrics.

import numpy as np
import time

# Define synchronization channels
ch_master = 1
ch_slave = 2

# Enable the ReferenceClock using the first external reference
tt.setReferenceClock(clock_channel=ch_master,
                     clock_frequency=10e6,
                     synchronization_channel=None,
                     wait_until_locked=True)

# Define measurement steps (logarithmically spaced averaging times)
steps = np.unique(np.logspace(0, 7, 100, dtype=np.int64))

# Initialize Frequency Stability measurement on the second reference
fs = TT.FrequencyStability(tt, ch_slave, steps, average=1)

# Allow the measurement to collect data
time.sleep(100)  # Adjust as needed

# Retrieve frequency stability results
obj = fs.getDataObject()
tau = obj.getTau()
ADEV = obj.getADEV()
TDEV = obj.getTDEV()
MDEV = obj.getMDEV()

Measuring synchronization precision across multiple Time Taggers

Before starting experiments where Time Taggers are deployed in remote locations, it is useful to verify the synchronization precision while the units are still physically close to each other. This ensures that the synchronization setup is working correctly before the Time Taggers are separated.

The verification follows the method described in Swabian Instruments’ application note on remote synchronization. A common test signal is split using a power splitter or any other method that guarantees that identical copies of the signal are fed into both Time Taggers. The signal is then connected to an input channel of each device. The Correlation measurement class is used to analyze the arrival times of events recorded by both Time Taggers, providing a direct measure of synchronization precision.

The measurement is performed using the TimeTaggerNetwork in a dual-server setup, as discussed in the previous sections.

import matplotlib.pyplot as plt

# Define the correlation measurement between input channels on both Time Taggers
# We assume the test signal is fed into the third input of each Time Tagger
corr = TimeTagger.Correlation(ttn, 1003, 2003, binwidth=1, n_bins=1000)

# Start the measurement and run it for a given time
corr.startFor(10e12)
corr.waitUntilFinished()

# Retrieve the correlation data
index = corr.getIndex()
counts = corr.getData()

# Plot the correlation result
plt.plot(index, counts)
plt.xlabel("Time Difference (ps)")
plt.ylabel("Counts")
plt.title("Correlation of Synchronized Time Taggers")
plt.grid()
plt.show()