Reply by Tim Wescott February 6, 20062006-02-06
Noway2 wrote:
> Tim, > > That was a very nice explanation. I have always considered software > PLLs to be a bit of an enigma, though a future project goal of mine is > going to require one. In my case, the reference and the incoming > signal will both be aprox 50 or 60hz sine waves. For the PFD, I was > planning on multiplying them and filtering the result which would be > used to drive the NCO. > > I was wondering if you would you please elaborate a little more on the > concept of using the inphase and quadriture outputs and their phase > rotation and what this does / how / why it works? >
I always consider software PLLs to be very straightforward -- until I get caught up in actually making them work. Then I try to act casual while I'm struggling with them so that when I finally stumble onto the right combination I look clever... On using inphase and quadrature outputs: First, see my opening paragraph -- I missed a detail in that recommendation, it isn't as powerful as I had thought (d'oh). I'll explain as I go. Let's say that you're keeping track of the NCO phase and calling it 'theta', and you're phase locking to a signal -- I'll call it 'line' in honor of your 50 or 60Hz signal. A multiplying phase detector can be made by finding phaseError = sin(theta) * line; You take this phase error and run it through a loop filter: frequency = loopFilter.Update(phaseError); // pretend this is C++ Then you calculate the NCO phase: theta += frequency; And you're done. The cool thing is that the variable phaseError will have an average value that's proportional to the phase, so if your loop settles at all it will do so at zero average error. The problem is that if all you know is phaseError then it's average could be zero for other reasons -- either the NCO frequency is significantly different from the line frequency, or you're hovering on a phase error of 180 degrees. Usually the 180 degrees out of phase issue isn't a big one because it's inherently unstable and eventually your loop will lock. A large frequency difference can be a bigger problem. If you do the quadrature thing, then you may calculate phaseErrorI = sin(theta) * line; phaseErrorQ = cos(theta) * line; Now, when you are at 0 degrees phase error phaseErrorI will average to 0 and phaseErrorQ will average to a positive number. With 180 degrees phase error phaseErrorI will average to 0 and phaseErrorQ will average to a _negative_ number, so you will be able to distinguish the 180 degree out of phase condition and deal with it. In addition, if there is a frequency difference between the line frequency and your NCO frequency then the average values of phaseErrorI and phaseErrorQ will rotate around each other -- so first phaseErrorI will be high, then phaseErrorQ, then phaseErrorI will be negative, etc. You can use the averages of these two phase errors like the output of a quadrature encoder to track the phase error and determine if it is rising or falling, which will let you determine if your frequency error is positive or negative -- which in turn will let you bring your loop into lock quicker. Unfortunately (and hence the d'oh), if the frequency error is large then the average values will both be quite small, and this method won't give great success. So for this sort of thing you may be better to have a coarse frequency loop that just counts zero crossings or something to bring the loop into approximate lock, then allow a simple multiplying phase detector to take over. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com