My brain hurts: software Phase-Locked Loop design - Page 1
Forum section: electronics / projects

author: andyturk
author_rank: Frequent Contributor
timestamp: October 31, 2012, 06:00:00 am
content: Oy, my aching brain.I figured a software PLL would be just the thing to replace all the messy zero-crossing code I had to detect the period on a fairly slow moving sensor input (8Hz - 160Hz).Thisdiscussion of PLLs is pretty interesting, but the implementation is based on a frequency modulated oscillator, which doesn't quite fit what I'm doing (the monotonically increasing t will overflow quickly in fixed-point). Then there'sthisone, which looks good. It doesn't actually calculate the reference signal voltage (i.e., no need for trig), but the low-pass filter definition is a mystery. I spent the morning at the Berkeley engineering library looking at Roland Best's book on PLLs, but didn't come away sufficiently enlightened. b0 and b1 are defined in terms of T, tau1 and tau2. T is 1 over the sample rate, but what the heck are those tau values?Thisseems to be a very clever condensation of C.R. Bond's implementation of Roland Best's basic algorithm. The treatment of pi as a power of 2 is especially tricky. Unfortunately, when I throw a 100Hz signal at my implementation (with a 100Hz center frequency), it fails to lock, and I'm not sure why that is. How does one debug a software PLL?Questions for the EEVBlog graybeards:1) Will "any old" low pass filter work? Best says that the -3db point of the filter has to be 10x to 20x below the sample frequency. Is that the only requirement? If my samples arrive at 6KHz, can I slap in a low-pass biquad filter at 300Hz (Q=.707) and expect my PLL to work?2) The typical PLL definition involves two gain coefficients. Kd governs the gain of the phase detector and K0 is the gain of the low-pass filtered phase error. How does one come come up with reasonable values for Kd and K0?3) Are there other software PLL implementations that I should be looking at?

author: IanB
author_rank: Super Contributor
timestamp: October 31, 2012, 07:04:39 am
content: Do you need to lock into the actual phase to detect the zero crossing points in time for some other purpose, or are you just looking for the frequency?If it's only the frequency you want to measure, I think the software equivalent of a PLL would be a Fourier transform? This would let you extract the frequency components of your signal and then select the largest component in the frequency range of interest.

author: Kremmen
author_rank: Super Contributor
timestamp: October 31, 2012, 07:33:59 am
content: +1 to the FFT. The good thing about that is that it basically cannot fail. You didn't mention what hardware you are running but a quick fixed point FFT should be findable and should be good enough for your purposes.

author: Mechatrommer
author_rank: Super Contributor
timestamp: October 31, 2012, 08:39:05 am
content: the bad thing about FFT is frequency resolution is based (proportional to) on number of data available to the process, you may get the largest magnitude frequency, but not exactly the frequency that occurs in the real life, close but not exact, how close depends on the resolution.

author: HackedFridgeMagnet
author_rank: Super Contributor
timestamp: October 31, 2012, 11:20:20 am
content: QuoteHow do you get from the FFT to the zero crossing point? Surely it would be the long way.Why can't it fail?The PLL method seems more in tune with the problem.

author: nctnico
author_rank: Super Contributor
timestamp: October 31, 2012, 12:20:06 pm
content: I'd solve the problem with a steep high-pass filter (4th order elliptic) to remove anything below 8Hz and a similar steep low pass filter to get rid of anything over 160Hz. Zero crossing detection should work without a problem. You can average multiple periods by implementing a frequency counter in software.

author: jeroen74
author_rank: Frequent Contributor
timestamp: October 31, 2012, 01:05:19 pm
content: Why is the zero crossing code messy? What exactly do you want to achieve?I'd count the number of clock ticks between zero crossings, from that you can compute frequency.You can also timestamp the first zero crossing, then count the number of zero crossing for a period of, say, 1 second, then timestap the next zero crossing (this timestamp can also be used for the next 'first' zero crossing). Then compute frequency from that. Basically this is what every descent reciprocal frequency counter does.Depending on precision and response time requirements, maybe it's enough to just count the number of zero crossing over a fixed period.

author: andyturk
author_rank: Frequent Contributor
timestamp: October 31, 2012, 02:31:44 pm
content: Thanks for the responses guys!I think the FFT is out because this has to run inside the interrupt routine that collects sample data from the ADC. And besides, all I want is one number which says what "the" frequency is--the frequency with the most power.The intended use is to implement something like the auto button on an oscilloscope. I've got an input signal whose main frequency varies between 8Hz and 160Hz and I want to grab a complete cycle and display the waveform on a screen. It's not an actual sine wave, but definitely periodic.The main use of that frequency is to configure a sample buffer to collect enough points for display. The sample frequency is fixed and so is the depth of the buffer, so I'll need to average some data or discard points when the frequency is low. The input phase is useful too, for drawing each waveform in the same place on the screen.I thought the SPLL idea would be a reasonably easy-to-implement black-box where I could plug a stream of sample data in one side and get a single number for the frequency out the other. After trying a couple of times though, those implementations are a little more involved than I realized.So, going back to the drawing board, the first issue is figuring out where "zero" is. There's going to be a DC offset in the input signal, which needs to be removed. At that point, finding the zero-crossings should work.What's the best way of finding a DC offset? Maybe the output of a low-pass filter (in software) would work. I've also thought about calculating a running average of an under-sampled data stream (keeping all the samples around for an 8Hz signal will take too much memory).

author: jeroen74
author_rank: Frequent Contributor
timestamp: October 31, 2012, 02:42:54 pm
content: Low pass flter the input data. Subtract the filter output from the input values to get rid of the DC offset. Basically, that's just a high pass filter. A simple exponential filter works quite well and you only need to remember the previous sample.http://en.wikipedia.org/wiki/Exponential_smoothing