Varying S-Band frequency offsets

Hello space people,

I’m working on orbit determination (with rffit) for an S-Band mission. This is somewhat new territory for me, previously I’ve only done UHF.

I’ve noticed that we seem to have pretty big constant-frequency offsets between measured doppler shift and the TLE-based prediction. And this offset isn’t the same for every pass – it seems to vary quite a lot between passes (see below for examples of a big positive offset, small positive offset and even a small negative offset).



Can this be explained by an incorrect TLE? Or does it mean there’s some other issue somewhere? I imagine this could be caused by some frequency drift in the SDR (LO?), either on the satellite or ground station.

As a workaround, I’ve tried preprocessing the signals from each pass with the following process:

  • predict doppler shift with “seed” TLE
  • add a time & frequency offset to the measured signals
  • optimize the two offsets wrt. RMS error between measured signals & TLE prediction
  • discard time offset & write out signals with the frequency offset added

The results look a lot better (see below), but we still don’t get a solid link. And I would have expected that this preprocessing step makes the frequency fit in rffit redundant, but I still get improved RMS error when enabling frequency fit. So I don’t think my process is “correct”.



Does someone have an explanation for what is causing these offsets, or some tips for how to deal with them? Thank you!

Best,
Jasper

2 Likes

There are a few things to think of:

Wrong tle? Can it be mixed up with LPNTSAT-001? Norad 68408 vs 68409?

Is the location of the groundstation 0001 set correctly in sites.txt. And is it the only entry with that number? I have McCants as 0001.

How is the clock stability of the sdr? What sdr are you using? Do you use a gpsdo, like a Leo Bodnar. This can improve the frequency stability a lot!

Are other satellites spot on? If they have similar offsets, it is the sdr.

Can you add it (or both) to https://db.satnogs.org/ then we can easily take look. If the Artemis mission is finished, I can do some strf observations too, so we can compare.

3 Likes

Wrong tle?

Definitely possible. Could a wrong TLE cause this? On the LEO/SSO passes I’ve seen, the Doppler shift seems to be point-symmetric over (T_CA, 0Hz). The first pass I’ve shared is pretty clearly shifted upwards wrt. the 0Hz line. But I don’t exactly have a rigorous explanation for why it should be symmetric.

Can it be mixed up with LPNTSAT-001? Norad 68408 vs 68409?

We’re pretty certain it’s the correct object.

Is the location of the groundstation 0001 set correctly in sites.txt. And is it the only entry with that number? I have McCants as 0001.

Yes, I replaced 0001. The coordinates should be accurate to <250m.

How is the clock stability of the sdr? What sdr are you using? Do you use a gpsdo, like a Leo Bodnar. This can improve the frequency stability a lot!

Are other satellites spot on? If they have similar offsets, it is the sdr.

We don’t own the ground station, so I’m not sure. Is this behavior something you’d see with bad frequency stability in the SDR?

We don’t get IQ data, only Doppler shift measurements when there’s carrier lock. So unfortunately I don’t know about any other satellites.

Can you add it (or both) to https://db.satnogs.org/ then we can easily take look. If the Artemis mission is finished, I can do some strf observations too, so we can compare.

I’ll see if we can add it. Thank you!

Looking at the images shared, the offset is basically vertical that is indeed an indication that the frequency is drifting.

This can be the SDR LO (please share some details on the SDR and further RF chain) but could also be the satellites LO.

Based on the International Designator 2026-065B we are observing LPNTSAT-002 (IOD-2) is this correct?

Jan | PE0SAT

1 Like

Like I said it’s not our ground station, so I don’t know much about the RF chain. We just get a demodulated data stream and some metadata (e.g. the measured Doppler shift).

Yes.

I don’t know the TX frequency for LPNTSAT-001, but I’ve added LPNTSAT-002.

The beacon is currently activated every 10min, so it probably won’t be visible in most passes. But we can coordinate and schedule increased beacon frequencies for specific passes.

1 Like

I have been going over my STRF observation on 08-04-2026 and 09-04-2026 and haven’t found any signals on 2221.950 MHz.

We will keep an eye on them.

Jan | PE0SAT

1 Like

Thanks for checking. Your groundstation is in NL, correct? I think we can schedule some increased beacon intervals over NL next week.

Correct, I am in NL and monitoring with a RHCP Helix antenna pointing at Zenith.

Please let me know if you where able to increase the beacon frequency then I will make sure I am monitoring the correct frequency range.

At the moment I am using a 20msps rate and moving daily from 2210 to 2290 at 20MHz interval.

Jan | PE0SAT

Thanks @jazzpi for the explanations.

I have scheduled some observations. Let’s see if we get something:

How do you get these values? Is it a strf.dat file? Or did you assemble that file your self? Could anything go wrong there?

This could very well be the cause!

You could try to fit the data in rffit instead of your method of moving points in time and frequency. It has a lot of possibilities. If you need help with that, it is easiest to ask in the chat: https://app.element.io/#/room/#satnogs:matrix.org

Do your fitting results change with newer or older TLE’s. Can it be that the satellite is using its trusters? This will show up in the TLEs.

2 Likes

Maybe it is this fuzzy blib:

1 Like

Different format, I wrote a script to convert it. But I’ve checked the raw data and that also shows the same behavior.

You mean fitting with frequency enabled (8 → F)? There’s two reasons I didn’t use that:

  • the frequency offset is different for different passes. I guess I could fit it for each pass individually, but AFAIK rffit doesn’t store the result of the frequency fit anywhere.
  • we initially didn’t have great TLEs, so the predicted passes were earlier/later than the actual passes. So only fitting frequency couldn’t really work, and AFAIK rffit doesn’t have any “fit a time shift” feature.

Yes, but the constant offset is always there. Here’s the same pass with TLEs from Celestrak from 2026-04-04, 2026-04-08 and 2026-04-09:



No maneuvering during this time frame.

That looks like it! The beacon activates TX for ~7s. But a bit difficult to tell the center frequency :sweat_smile:

1 Like

@jazzpi can you share the .dat files and the sites.txt if possible?

I would be interested to experiment with them.

Is it different due to different frequency transmissions from the satellite or due to other orbital/station parameters?

I follow a process when fitting different passes from different stations from the SatNOGS Network that usually gives very decent results, maybe following this would give you a good fit.

1 Like

Sure, here’s some .dat files:
260408_leopnt1.dat (25.0 KB)
260408_leopnt2.dat (25.1 KB)
260408_leopnt3.dat (10.8 KB)
260408_leopnt4.dat (9.7 KB)
260408_leopnt5.dat (21.2 KB)
(the pictures I posted were from 3/4/5)

And this sites.txt entry:

0001 TS  -72.0103    2.5539   1359    TrollSat

I don’t know. Nothing intentional, but could be frequency drift on the satellite or ground station.

Can you share the process? Sounds interesting :smiley:

So far I’ve just concatenated the signals from multiple passes (/ground stations) into one .dat file:

cat 26040{6,7,8}*.dat > combined.dat

and then run rffit on combined.dat.

2 Likes

I’ve concat *3-5.dat files which contain the station 0001 in their points.

I’ve used space-track.org TLE with epoch the previous day (I assume from the file name that the points coming from 2026-04-08 day, so I get the TLE with epoch 26097):

0 LPNTSAT-001
1 68408U 26065A   26097.62895194  .00002905  00000-0  14459-3 0  9995
2 68408  97.4111 339.6065 0015466 248.0097 111.9495 15.18292519  1559

The points don’t fit well in this TLE, as you noticed, however for each of them if you fit Ascending Node (AN) and Mean Anomaly (MA), you get good fits (rms < 0.100KHz, for all of them it was around 0.050 KHz).

What I’ve noticed is that for each of the above fits, the frequency fit is quite different, from the more recent pass to the oldest one: 2221.950365 MHz (0.365 KHz from the center frequency), 2221.952246 MHz (2.246 KHz from the center frequency) and 2221.955099 MHz (5.099 KHz from the center frequency). If I get orbital mechanics right, this doesn’t necessarily means change in the frequency satellite transmits or station receives but it could be due to orbit change or time changes on the station, or a combination of all of the above. Unfortunately I can not help more on spotting what causes these differences.

My method to generate new TLE from observations, start with the above, fitting AN and MA together for each of the passes, then I proceed to bring everything to fit at the same frequency, preferably the center frequency of the satellite, which here I assume is 2221.950 MHz. So, I move points from each pass as much as the difference from the center frequency, in our example -0.365 KHz, -2.246 KHz and -5.099 KHz respectively.

With this process I kind of fixing/mitigate the errors in time and frequency, so the next step is to choose the parameters to fit. Usually from experience there are three parameters that need fixing/fitting AN, MA and Mean Motion (MM), the last one needs at least two different passes. So, I fit first AN and MA for the points of most recent pass, then choose additionally the points from the oldest one and fit AN, MA and MM. Then either choose all the in-between passes or from the oldest to the newest continuing fitting after adding new points in the selection.

When everything is chosen and fit we have a new TLE, however this is at the same epoch with the one we started from, so we need to move it. This can be done by hitting e key which changes the epoch to the one of the most recent pass (note that points of this pass should be at the top of the .dat file, you can verify it by where Tca vertical line shows up). Now we have moved the epoch, points will be again outside the expected orbit, here is where I re-do the same process.

Fitting AN and MA for each pass and moving points in center frequency, when I’m done then I fit again AN and MA for the more recent, then additionally select the points of the oldest and fitting AN, MA and MM and then as previously continuing with the in-between passes. Note here that this time the difference from the center frequency should be around 0-10 Hz for S-band fitting, this is an indicator that the fit before changing the epoch was a good one. In our case I moved them -0.004 KHz, -0.007 KHz and -0.006 KHz respectively.

After that you have a new TLE that it should be good enough (rms < 0.100 KHz), in our case I got the TLE below:

LPNTSAT-001
1 68408U 26065A   26098.53717203  .00000000  00000-0  14476-3 0    06
2 68408  97.4111 340.5163 0015466 248.0097  33.1152 15.18541788    08
# 20260408.40-20260408.54, 1015 measurements, 0.050 kHz rms

The above compared with the closest in epoch TLE from space-track.org:

1 68408U 26065A   26098.61753319  .00002729  00000-0  13600-3 0  9998
2 68408  97.4110 340.5749 0015506 244.1688 115.7947 15.18298060  1704

gives very good results near (±24 hours) the epoch time.

From the above, my guess is that the satellite hasn’t any significant or abnormal change in its orbit, so it is probably something either with the satellite’s expected (2221.950 MHz) frequency or with the station time that resulting to such difference in frequency-time pair in each pass. If I had to choose I would say something is off with the station (time?) than the satellite, but this is just a speculation as I don’t know how both of them work.

Disclaimer: the above process is coming from experience and its successful results, however I haven’t found time to examine it, prove that/how it works or find how vulnerable in errors is, so use with caution! :slight_smile:

2 Likes

Thanks for sharing the data! Interesting station location! It is in Antarctica, near the south pole! I see 3 domes there, so maybe they used 3 different stations. But for these stations in that location, we should expect professional grade data. The frequency should be GPS referenced or even better. I agree with the analysis of @fredy. Only thing I did differently was that I fitted every pass using MA, MM and Ascending Node. This gives a very low rms value of around 15 Hz. This gives an indication of the best possible fit rms error and also indicates how accurate the Doppler measurement was. The goal is to get all 3 curves to fit a TLE with a similar low rms error. Fredy already showed how to do this.

If I let rffit search on each pass for the best matching object I get twice 68408, and once 68409. Use the i option for this.

Still can’t explain the large frequency offsets. Could it be ground locked for some passes?

2 Likes

Thank you both! So the process is:

  1. Fit MA/AN(/MM) and frequency for each pass individually
  2. Modify each pass’s signals.dat file to compensate the frequency fit
  3. Fit MA/AN/MM using multiple corrected passes
  4. Repeat with an updated epoch

Did I summarize that correctly?

My process is pretty similar, only in step 1 I fit a time shift instead of MA/AN/MM. Fitting orbital parameters is probably the better idea.

Do you do this manually? I think this is scriptable with some Python. (Un)fortunately we are now getting regular TLE updates from Celestrak, so this is less of a priority for me at the moment. But hopefully I can find some time soon™ to write the script.


It is not ground locked.

Yes, so they must demodulate the signal or use some other technique, to extract the Doppler. Question is how they do it, and if they can explain it. And what can go wrong!

You have understood the method correct. Normally it is used if you have signal from multiple stations. Each has its own frequency offset. Your signal looks similar.

Good, the original goal was to improve the TLE?