[time-nuts] I've designed a GPSDO, but how "good" is it?

Nick Sayer nsayer at kfu.com
Mon Aug 17 15:49:37 EDT 2015

> On Aug 17, 2015, at 12:07 PM, Attila Kinali <attila at kinali.ch> wrote:
> On Mon, 17 Aug 2015 07:14:34 -0700
> Nick Sayer via time-nuts <time-nuts at febo.com> wrote:
>>> Without having had a look at your code (sorry, i currently don't have
>>> the time for this), if you trully implemented just an FLL, then this
>>> is where you should start from. The way to get a PLL is to let the counter
>>> of the capture unit run freely. Don't reset it, just let it wrap around.
>> I do that. It’s a 32 bit counter (the 16 bit counter has an overflow
>> interrupt that increments the high 16 bytes in software). The counter
>> free-runs. 32 bits at 10 MHz takes around 400 seconds to wrap.
> So that works right. Good.
>>> The PPS pulse will now be wandering in each period, so you have to track
>>> where you would expect the PPS next (unless you set the counter such,
>>> that its wrap around divides a second evenly). Doing this, you will
>>> integrate over the frequency difference and thus get a phase comparator.
>> I don’t quite get it.
>> What I do is every time there’s a capture interrupt, I subtract the counter 
>> value of the last capture from this one. That gives me how many clock cycles 
>> there were between PPS rising edges. But there’s no way for me to know the 
>> phase relationship between the two rising edges (the PPS and 10 MHz). I can 
>> only assume that the capture takes place within one cycle. Fortunately, I 
>> don’t have to be concerned with software latency, as the capture interrupt 
>> occurs immediately after, well before anything else gets in the way.
> By taking the difference of "current pulse time" minus "previous pulse time"
> and using this as the input into your control loop, you are making an FLL.
> Instead you should use "time the pps is expected to arrive" minus "when
> the pulse actually arrived".
> You have a nominal frequency of 10MHz and a 16bit counter. That means
> a second is 152 overflows plus 38528 counts long. Assuming you start with
> 0, the expected arrival of the next pulse is at count 38528. When it comes
> earlier, your TCXO frequency was too low, when it comes later your TCXO
> frequency was too high. The third pulse is exected to arrive at
> count = (38528*2) % 2^16 = 11520. Again, feed the difference between that
> value and when the pulse actually arrived into your control loop. The forth
> pulse is expected at, (38528*3) % 2^16 = 50048,... etc pp
> By not taking the difference to the previous pulse, but to the expected
> time of the pulse, any fractional error in the calculation/frequency
> will accumulate until it reaches the point where it actually becomes
> visible as an offset between expected pulse time and pulse time.
> And hence, forms a PLL.

That’s not different than simply tracking cumulative rather than immediate error, isn’t it? 

I’m doing that with a rolling ten-sample (1000 second) window to report lock quality to the user (0.1ppb granularity).

I’m also doing that for a 100 second sample time to derive the error for the feedback loop (1.0 ppb granularity, but with 375 ppt “nudges” when the absolute value is small).

I’m sorry if I seem obtuse, but I don’t see how the arithmetic results in a different answer.

> If the timer of the ATtiny allows that, you can set it to overflow
> at 62500. This divides 10e6 evenly, which gives you a constant count
> number when you expect the pulse, which you then can set into mid range,
> ie. at 31250. (makes the software easier)
>> When the error delta over 100 seconds is non-zero and less than 5, I 
>> increment or decrement the DAC value, thus adjusting the trim by an expected 
>> ~370 ppt. When the error is more than 5, I double the error and add/subtract 
>> that to the DAC value. It’s not a PID, but it generally reaches steady-state 
>> quickly enough. I don’t make any LOCK LED indications at all until the 1000 
>> second sample window is full, and by then the 100 second deltas are under 5 
>> (usually at or under 1).
> You really should read the wikipedia article on the PID loop and implement
> a simple PI loop (no need for the D part). That's not more effort than what
> you already did, but gives you better stability.

I’ve done PID before (for a reflow oven controller), but thought that the current code was easier to understand. I’m going to try the GPSDO simulator and see how it matches up. It’s entirely possible that an improvement could be made in the time-to-lock, but the steady state performance appears to my eyes to be as close to optimal as I could envision. But I’m new at this, so it’s entirely possible that I’m not looking at it correctly.

> 			Attila Kinali
> -- 
> I must not become metastable. 
> Metastability is the mind-killer.
> Metastability is the little-death that brings total obliteration.
> I will face my metastability. 
> I will permit it to pass over me and through me. 
> And when it has gone past I will turn the inner eye to see its path. 
> Where the metastability has gone there will be nothing. Only I will remain.
> _______________________________________________
> time-nuts mailing list -- time-nuts at febo.com
> To unsubscribe, go to https://www.febo.com/cgi-bin/mailman/listinfo/time-nuts
> and follow the instructions there.

More information about the time-nuts mailing list