April 23, 2024

Set Up a TDOA System

This article describes how to setup a low-cost TDOA system based on RTL-SDR + Raspberrry PI receivers and how to connect them via ethernet.

Requirements for the low-cost TDOA system

Raspberry PI based receivers:

Master PC:

Set up a Raspberry PI RTL-SDR Receiver

Download the SD card image and write it to an SD card (recommended software: Win32DiskImager). Login with username alarm and the (default) password alarm. The command to start a reception at the receiver is:

/home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 filename.dat

where -f specifies the synchronization frequency and -h specifies the frequency of the signal to locate.

Establishing the SSH connections between the receivers and the master

In order to be able to start the reception of all receivers at least roughly at the same time (recommended is within 100 ms), it is required to configure SSH for key-based authentication instead of the default password-based login. For that purpose the user at the master (client) generates a pair of keys once. Then the public key is copied to the Rasperry PIs (server). Lots of good and detailed tutorials can be found in the web.

Establishing the SSH connections from the master to the receivers depends on the type of network connections your receivers have:

Scenario 1: Master PC and receiver in the same LAN (easy):

All receivers in the same LAN

If your receivers and the master PC are connected to the same LAN operation of the TDOA system is quite easy. The single generic command below (entered in the console of the master PC) successively logs into three remote systems and starts the specified remote linux command there:

ssh alarm@<ip-address1> <remote_linux_command> &
ssh alarm@<ip-address2> <remote_linux_command> &
ssh alarm@<ip-address3> <remote linux_command>

Example usage for three TDOA receivers:

ssh alarm@ /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 1_filename.dat  &
ssh alarm@ /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 2_filename.dat &
ssh alarm@ /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 3_filename.dat

Scenario 2: Master PC and receivers in different private LANs (quite easy):

One of the receivers in an other LAN

This is scenario is probably the most common setup: The receivers are located at different locations (e.g. your friends house) in private LANs. Establishing a ssh connection from master to a receiver is usually not straightforward, because the receiver is hidden behind a router and its firewall. So you need to provide access from the public internet to the Raspberry PI in the private LAN. Two things are required here

  • First, the master needs to know the public IP address of the receiver LAN’s router. Note, that usually the public IP address changes from time to time. For comfortable permanent operation a “dynamic DNS” service can be used, such that the router can be accessed by a fixed domain name (e.g. a_router.a_dns_service.org).
  • Second, the router of the receiver’s LAN needs to be configured with port forwarding to make the receiver accessible to the public internet. Port forwarding simply maps a network port at the router to a device (PC, Raspberry PI) behind the router. Example: Router address (public) is, receiver LAN address is:, port configured by port forwading: 1111, then the receiver is publicly accessible with Port forwarding needs to be configured in your router settings, the exact procedure is dependent on your router model.

The generic command for recording signals at the 3 receivers is the same as above, except that the forwarded ports need to be specified (the IP address is then the public router address):

ssh alarm@<ip-address1> [-p <port>] <remote_linux_command> &
ssh alarm@<ip-address2> [-p <port>] <remote_linux_command> &
ssh alarm@<ip-address3> [-p <port>] <remote linux_command>

Example for TDOA: RX1 & 2 are local, RX3 is located in other LAN behind router with the public IP address, port forwarding is configured to port 1111:

ssh alarm@ /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 1_filename.dat  &
ssh alarm@ /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 2_filename.dat &
ssh alarm@ -p 1111 /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f <freq_1_hz> -h <freq_2_hz> -n 1.2e6 3_filename.dat

Scenario 3: Master PC and receivers in other networks (advanced):

Receivers in LAN without possibility for port forwarding, external server required

If one of the receivers is located in a non-private network, such as in a company, mobile network (3G, LTE etc.) or in another network, for which you do not have any administration rights, establishing a SSH connection is more difficult. One possibility requires an external online server. The Raspberry PI connects itself to that server to open a SSH tunnel (reverse tunneling). Further action may be required, such as applying autossh to keep the connection open.

TDOA System Operation

Operation of the TDOA system requires the following steps:

  1. Record data at the 3 RPI receivers simultaneously
  2. Copy the received data from the RPI receivers to the “master”
  3. Run the Matlab/Octave script at the master to produce a map with positioning information (html)

The following linux script for the master is an example template for system operation (adaptation of IP addresses and folders required). This script can be run on the master PC to automatically trigger all 3 receiver and copy the data to the master.

#script for operating the TDOA system

echo "-------------------------------------"
if [ $# != 3 ]
   echo "parameters missing, call: <scriptname> frequency1 frequency2 num_samples_per_freq"
   exit 1


echo "Specified parameters: reference frequency:" $freq1 ", measure frequency:" $freq2 ", samples_per_freq:" $num_samples
echo "--------------------------------------"
echo "Login to PI Radios and capture data simultaneously"
ssh alarm@<rx1_ip_address> [-p <port>] /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f $freq1 -h $freq2 -n $num_samples 1_test.dat &\
ssh alarm@<rx2_ip_address> [-p <port>] /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f $freq1 -h $freq2 -n $num_samples 2_test.dat &\
ssh alarm@<rx3_ip_address> [-p <port>] /home/alarm/librtlsdr-2freq/build/src/rtl_sdr -f $freq1 -h $freq2 -n $num_samples 3_test.dat 

echo "Copy received data to the master"
scp [-P <port>] alarm@<rx1_ip_address>:/home/alarm/1_test.dat ~/<matlab_script_folder>/recorded_data/1_test.dat
scp [-P <port>] alarm@<rx2_ip_address>:/home/alarm/2_test.dat ~/<matlab_script_folder>/recorded_data/2_test.dat
scp [-P <port>] alarm@<rx3_ip_address>:/home/alarm/3_test.dat ~/<matlab_script_folder>/recorded_data/3_test.dat

After the data has been copied, the matlab/ocatve script can be executed.

Note, that it is required to tell the matlab script information like the positions of your receivers and the reference transmitter as well as processing parameters. This can be done by writing a simple configuration file (example config files are config.m and test/config_test.m).