Correcting Frequency Offset on ADALM PlutoSDR

Hello together,

I am experiencing a frequency offset on all of my UHF and S-Band observations using my two ADALM PlutoSDR’s. It seems like that the offset is variable, depending on bandwidth, modulation, temperature, …

S-Band 18 kHz Offset: SatNOGS Network - Observation 7883233
S-Band 30 kHz Offset: SatNOGS Network - Observation 7881708
S-Band 4 kHz Offset: SatNOGS Network - Observation 7881705
UHF 4 kHz Offset: SatNOGS Network - Observation 7872835
UHF 4 kHz Offset: SatNOGS Network - Observation 7782066

Since PPM error correction is not supported by the PlutoSDR, I am failing to correct the frequency offset. Also the troubleshooting section " Observations seem off-frequency?" wasn’t very helpful. Varying the SATNOGS_LO_OFFSET parameter (no input, 50, 100e3) only shifts the “spur”, but doesn’t effect the off center received signals.

Exists there another possibility within the SatNOGS Client to correct frequency offsets, despite the SATNOGS_PPM_ERROR setting?

If not, any expertise on how to frequency calibrate the PlutoSDR (e.g. with a GPS reference signal)?

Many thanks in advance!

Alex, oe3ala

1 Like

Additional comment about the “spur” / DC spike:

I also read through this post, dealing with the “spur” / DC spike of the PlutoSDR oscillator and SATNOGS_LO_OFFSET parameter.

It seems like, that some of my parameters are not set correctly. The standard value of the SATNOGS_LO_OFFSET is 100e3 and shall be well within the sample-rate. Currently, I am using a sample-rate of 2e6 and the standard lo-offset (100e3). Therefore, the DC spike is present on the wider waterfalls.

I will change for both setups (UHF, S-Band), running with a sample-rate of 2 MHz, the lo-offset to 5e5 (0.5 MHz), which should solve this issue - similar to sample-rate = 8e6 and lo-offset=2e6 as stated in the post.

Often the sample-rate and bandwidth are assigned with the same value, e.g. both 2e6. Do they need to by equal or can they be different?

Nevertheless, this will not fix the off-center frequency.

Alex, oe3ala

One possible solution could be the replacement of the PlutoSDR oscillator:

We have to look into that with our station as well…

1 Like

yes, I use this method, ssh into the pluto:

fw_setenv xo_correction 40000000
pluto_reboot reset

choose the 40MHz value based on your ppm calculations, try inverting the change if it went in the wrong direction.
documented here under examples and

1 Like

Thanks! We also have a third PlutoSDR for our QO-100 Setup. This Pluto calibrates the oscillator with an external GPS signal using a GPSDO. I will try to integrate this setup into my S-Band ground station and will report on how it worked out! :slight_smile:

I already calculated the PPM for my UHF ground station and will try modify the PlutoSDR using a SSH tunnel.

Unfortunately, I am getting variable offsets on S-Band (between 4 and 30 kHz). Therefore, the problem will not be fixed by a constant correction. Any ideas on why the offset is varying that strong? I need to mention, that my S-Band PlutoSDR is mounted into a rack on the roof and therefore experiences heavy temperature fluctuations. Nevertheless, that doesn’t explain the difference between two observations, which were performed within 30 minutes.

Yes, if it’s the original oscillator it will vary quite a bit depending on temperature. It is also located quite close to the ADC that is generating a bit of heat. So this comes both from board and environment.
I’m using the modded variant that has a 40MHz 0.5ppm tcxo located on a small board, this relieves it a bit from the board heat, but not environment.
Depending on TCXO, they can do the corrections in good and bad ways, I have seen some jump quite drastically to keep it inside the specs and others that seems to do this more smoothly.

1 Like

Ok, so you did the modification (replacing the original oscillator) as was stated by @raaptormet above. Thanks, I will look into it! :slight_smile:

I have calculated the PPM value using observations described here. The calculated PPM error is +9,7896. Since the standard xo_correction for the Pluto is 40 MHz, i need to add the PPM multiplied by 10^6 to get the correct value?

For example:
xo_correction = 40000000 + PPM * 10^6

Which gives me a xo_correction of 49789600 Hz. Is that correct? :slight_smile:

10 ppm at 40MHz is 400Hz, so it should be less than that, added or subtracted from 40MHz.

(in python)

>>> 40e6*9.7896e-6

don’t remember if this should be added or subtracted, but the two possibilities

>>> int(40e6-40e6*9.7896e-6)
>>> int(40e6+40e6*9.7896e-6)

fw_setenv xo_correction 39999608
fw_setenv xo_correction 40000391


thanks again for your input!

Unfortunately, our UHF antenna controller is currently being repaired. Therefore, I am not able to test if this approach works and if it is sufficient.

I will come back as soon as I am able to test it and have results!



For our S-Band ground station with very high frequency drifts due to high temperatures, I went for the approach with the LEO BODNAR GPSDO.

Therefore, I have implemented an additional SMA connector for an external reference clock signal using a Pigtail IPEX (U.FL) / SMA cable. Note that it isn’t using an SMA-Revers, which is normally used for WiFi applications! Further instructions can be found here.

We are using the bigger version of the LEO BODNAR GPSDO with two output signals, since we are currently working on 10 GHz RX using a LNB. We configured the GPSDO with 8 mA and an 27 MHz output signal (Output 1) for our LNB. Unfortunately, the Ouput 2 signal cannot be freely chossen, therefore we selected 40,5 MHz and connected it over the added SMA connector to the LEO BODNAR using an SMA socket / BNC plug adapter. It is not recommended to use a reference signal below 40 MHz for the PlutoSDR!

I configured the PlutoSDR using a SSH tunnel by running following commands:

fw_setenv xo_correction = 40500000 // Needed, if you are not using exactley 40 MHz as a reference signal!
fw_setenv refclk_source external // Tells the Pluto, that it gets an external reference signal.
fw_setenv qspiboot_extraenv true // To preserve the settings still after a power off.
fw_setenv ad936x_ext_refclk "<40500000>" // Tells the Pluto the frequency of the external reference signal.
pluto_reboot reset // Reseting and rebooting the PlutoSDR to apply chances.

Afterwards, you can check if the settings were applied correctly using following command:

cat /proc/device-tree/clocks/clock@0/clock-frequency | xxd

This gives you the set frequency, e.g.:

00000000: 0269 fb20                                .i.

Where 0269fb20 is the frequency in HEX format. Convert it to INT (in this case 40500000 Hz) and see if it was applied correctly. :slight_smile:

Now we have a frequency stable setup using the PlutoSDR together with a GPSDO.


1 Like