time-nuts@lists.febo.com

Discussion of precise time and frequency measurement

View all threads

How to recognize a PLL...

PK
Poul-Henning Kamp
Tue, Mar 15, 2005 9:50 PM

OK, I decided to go into lecture mode :-)

Imagine two 1Hz signals which differ in frequency and consequently
in phase.  We want to steer on to the other.

Every second we measure the phase difference 'x'.

Our first attempt is to multiply 'x' by some suitable constant 'a'
and use the output to steer our signal.

What we observe now is that the phase difference 'x' converges
on a non-zero constant.

This means that we have managed to eliminate the frequency difference
but not the phase difference.

Next we integrate the phase difference, in practice that means
"calculate a running average of", for instance like this:

y += (x - y) * t

for some timeconstant 't', and steering our signal with

a * x + b * y

The phase will now converge on zero and we have reached our goal.

The value b will now be the frequency offset of the steered oscillator.

If we notice that 'b' changes over time in a linear fashion, we
can add yet another term to our PLL: Integrate the phase difference
with a longer timeconstant:

z += (x - z) * s

Because the frequency changes, the offset not be zero because our
estimate assumes a constant frequency so it is always just not
quite enough.

'z' becomes the estimate of frequency change over time [1/s^2] and
we use it to adjust y in addition to the integral of the phase:

y += (x - y) * t + z * c

and we steer the oscillator as before:

a * x + b * y

All there is left is to find good values for a, b, c, t & s.

It is very simple to write a simulator of a PLL and very interesting
to experiment with different values for the constants:  In one
end the PLL gets unstable and starts oscillating, in the other
end it never converges.

Finally:  If you ever implement PLLs, remember to start it in stages
if you can:  First apply the x * a term and keep y and z  clamped
to zero.  When that has "caught" unclamp 'y' and let that grab hold,
finally when stabilty is again reached, unclamp 'z'.

--
Poul-Henning Kamp      | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG        | TCP/IP since RFC 956
FreeBSD committer      | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

OK, I decided to go into lecture mode :-) Imagine two 1Hz signals which differ in frequency and consequently in phase. We want to steer on to the other. Every second we measure the phase difference 'x'. Our first attempt is to multiply 'x' by some suitable constant 'a' and use the output to steer our signal. What we observe now is that the phase difference 'x' converges on a non-zero constant. This means that we have managed to eliminate the frequency difference but not the phase difference. Next we integrate the phase difference, in practice that means "calculate a running average of", for instance like this: y += (x - y) * t for some timeconstant 't', and steering our signal with a * x + b * y The phase will now converge on zero and we have reached our goal. The value b will now be the frequency offset of the steered oscillator. If we notice that 'b' changes over time in a linear fashion, we can add yet another term to our PLL: Integrate the phase difference with a longer timeconstant: z += (x - z) * s Because the frequency changes, the offset not be zero because our estimate assumes a constant frequency so it is always just not quite enough. 'z' becomes the estimate of frequency change over time [1/s^2] and we use it to adjust y in addition to the integral of the phase: y += (x - y) * t + z * c and we steer the oscillator as before: a * x + b * y All there is left is to find good values for a, b, c, t & s. It is very simple to write a simulator of a PLL and very interesting to experiment with different values for the constants: In one end the PLL gets unstable and starts oscillating, in the other end it never converges. Finally: If you ever implement PLLs, remember to start it in stages if you can: First apply the x * a term and keep y and z clamped to zero. When that has "caught" unclamp 'y' and let that grab hold, finally when stabilty is again reached, unclamp 'z'. -- Poul-Henning Kamp | UNIX since Zilog Zeus 3.20 phk@FreeBSD.ORG | TCP/IP since RFC 956 FreeBSD committer | BSD since 4.3-tahoe Never attribute to malice what can adequately be explained by incompetence.