1
$\begingroup$

I have been trying to implement PLL in a STM32 microcontroller. Starting with the first step, I want to implement a phase detector. I tried to first simulate in Python so that I can later use in STM32. So far, I used a analog multiplier getting idea from this post. It worked kind of okayish for wide range of phase range, however, the calculated phase was deviating from the actual phase which I asked in this post. phase deviation The problem here lies with the number of sampling points which is a restriction in my case. Anyway, I'd have gone with it, but in STM32 the error is even higher, probably because of truncation. Also, it was mentioned in the answer in this post that I don't need to calculate the arccos, rather use a loop filter (Propotional integral filter) to try to lock the phase. I also tried another phase detector which is a simple phase difference comparator.[ref from Chatgpt]

import numpy as np
import matplotlib.pyplot as plt

# Set the sampling frequency and number of samples
Fs = 100e3 # Hz
N = 100

# Set the signal frequency and phase difference
f_sig = 3e3 # Hz
phi_diff = np.linspace(0, np.pi, 6) # degrees
for j in phi_diff:
    # Generate the reference and phase-shifted signals
    t = np.arange(N) / Fs
    ref = np.sin(2 * np.pi * f_sig * t)
    phase_shift = np.sin(2 * np.pi * f_sig * t + j)
    # Initialize the PLL parameters
    Kp = 0.1
    Ki = 0.01
    Kd = 0.001
    VCO_gain = 1.0
    phase_error = 0.0
    freq_error = 0.0
    prev_phase_error = 0.0

    # Loop over the samples and simulate the PLL
    vco_out = np.zeros(N)
    for i in range(1, N):
        # Compute the phase error
        phase_error = np.arcsin(np.sin(phase_shift[i] - vco_out[i-1]))
        # Compute the frequency error
        freq_error = Kp * phase_error + Ki * freq_error + Kd * (phase_error - prev_phase_error)

        # Update the VCO output
        vco_out[i] = vco_out[i-1] + VCO_gain * freq_error / Fs
    #     print(vco_out[i] - ref[i])
        # Update the previous phase error
        prev_phase_error = phase_error
    
    plt.plot(t, vco_out, label = 'phase'+str(round(np.degrees(j),2)))
plt.plot(t, ref*1e-5, label = 'ref')
plt.xlabel('time')
plt.ylabel('amplitude')
plt.title('phase deviation in PLL')
plt.legend()

The problem was that phase difference deviating from 90 degrees were not locked and were even worse for farther deviation. second Here no filter is used for phase comparator and the parameters for PID controller is some assumed values which needs to be optimised.

But my question is, is it possible to go with this second phase detector to be used in PLL for wide range of phase difference? Or can I use the first multiplier PD? How do I calculate the correct parameters for PLL?

I'd appreciate any help.

Edit: what I have done in STM32,

  1. generate LUT for both reference and phase shifted signals (later the phase shifted one would be taken from external analog detector converted by ADC to feed into microcontroller.)
  2. use Direct Digital Synthesizer (DDS) to generate a reference signals.
$\endgroup$
4
  • $\begingroup$ You mentioned using an analog multiplier, have you then considered using an analog Phase/Frequency Detector?-- In your final implementation what is the source of the sinusoids you are locking? Will you be controlling an external oscillator or creating the sinusoids with an NCO in the STM? $\endgroup$ Commented Apr 6, 2023 at 12:30
  • $\begingroup$ I assume the multipliers idea is the same even if I do it in the STM. I have used the only two methods mentioned above. Since the frequency would be same in my case, I need to consider only Phase. I also need to take into account the error that i'd get from the stm phase truncation. I will have a look into APD if that would help. Regarding the source, I will use STM to generate a reference wave to be sent to an actuator and the feedback wave from the actuator to the phase detector. $\endgroup$
    – Rima
    Commented Apr 6, 2023 at 13:14
  • $\begingroup$ It's not clear what problem you're trying to solve when you talk about "wide range of phase difference". Are you trying to phase-lock to a source with a variable phase lag as opposed to usual PLL practice where you just lock at 0 or 90 degrees phase difference? Or are you trying to lock over a wide range of frequencies, and having trouble getting the PLL to acquire? $\endgroup$
    – TimWescott
    Commented Apr 8, 2023 at 16:29
  • $\begingroup$ I want to compensate the phase shift of a signal that will acquire due to external disturbances wrt a reference signal and completely sync them together at 0. The external factor could lead the phase shift to be anything. So there is variable lag. If this explains more. $\endgroup$
    – Rima
    Commented Apr 10, 2023 at 8:18

1 Answer 1

1
$\begingroup$

The OP has clarified that the use case is to phase lock an external analog sine wave (as acquired with the STM32 ADC) that can be at any frequency from 100 Hz to 10 KHz.

If the frequency is known beforehand, then the phase detector is a simple multiplier with the two inputs to the multiplier normalized to a constant sinusoidal peak amplitude (as the result will be sensitive to both phase and amplitude). Hard limiting can be done if the input signal is of high enough SNR, which has the added benefit of removing all AM noise and linearizing the phase response. The output of the multiplier will have a component at twice the input frequency and another that is proportional to the cosine of the phase. Let the loop filter remove the higher frequency component as any other filter in the loop will add delay and effect stability. Such a loop will lock to a 90 degree offset as that is where the phase error goes through zero. The 90 degree phase offset is inconsequential as it is a known offset (if an in phase local signal must be created then a quadrature NCO can be created as the local reference signal). This is depicted in the block diagram below:

PLL

If the frequency is not known beforehand, I suggest using a multiplier as a phase detector and including an additional frequency discriminator providing a frequency error to be summed at the input to the Proportional Integral loop filter used when the frequency error exceeds a certain threshold (all implemented as a digital PLL). Assuming the sine-waves of interest have been normalized to a constant magnitude (as we would need for the phase detector), a simple wide range frequency discriminator can be formed from the difference between the absolute value of 2 sample moving avg filters as sum and difference filters, with the sample rate set to 40 KHz (the low pass / high pass structure is essentially a 2 point DFT):

Simple wide range digital frequency discriminator: Frequency Discriminator

Freq Discriminator

The averaging detector can be simply a removal of the sign bit followed by a CIC filter (which is a simple moving average implementation), with the averaging time much lower than the time constant of the loop but sufficient to remove the sinusoidal variation in the detected magnitude. Other discriminators could be formed using the skirts of other filter topologies, anything that has a magnitude that is proportional to frequency.

The approach would be to monitor the frequency of the external sine wave that is an input, and the frequency of the internal sine wave would be known (as generated with an NCO). An error can then be determined which can then be scaled appropriately and summed with the phase detector error as input to the loop filter. I suggest the threshold approach and not sum anything when the frequency discriminator error is smaller than the acquisition range of the DPLL (so as to minimize noise during normal tracking).

As an alternate and rather simple solution if a APLL is possible, consider using a separate phase frequency detector as described in this post with the image copied below:

Phase Frequency Detector

Within a phase error of $\pm \pi$ this will provide a linear differential output error voltage (on average) vs phase error. For a frequency offset, the output will be railed to one side or the other and thus will be a 2 level frequency discriminator.

This is often combined with a charge pump to be a current source output, and with that the Proportional Integral Loop filter is simplified to a few resistors and capacitors. Such a device is available as the Analog Devices ADF4002 which can be controlled / configures with the STM32. This off loads a bulk of the processing from the STM32 with the cost of an additional $6.07 for the ADF4002 chip in single piece quantities.

A third consideration would be to implement the Phase Frequency Detector operation digitally, oversampled to provide the same functionality as the block diagram shown above (within the precision of one cycle of the master clock, which will limit the phase stability of the solution but may be sufficient for the application.

A fourth consideration is to implement quadrature tracking (Hilbert transform of single tone), and use the cross product phase detector for both instantaneous phase and phase from sample to sample (frequency) detection.

A fifth consideration would be to implement a time to digital converter (TDC) which is a practical solution when the SNR of the sine wave is high enough (to operate on the zero crossings alone) and the precision of the counter used is sufficient for the desired tracking accuracy (requiring the use of a high clock rate). With this solution, phase is determined via a counter from zero crossing events; between the zero crossing of the external sine wave and the roll-over of an internal accumulator whose count rate is set by an internally generated frequency control word (basically an NCO without the lookup table).

$\endgroup$
13
  • $\begingroup$ i forgot to mention that I am trying to implement a digital phase locked loop(DPLL). So I am supposed to use a STM microcontroller and my supervisor said everything can be done here. Could you maybe suggest me some ideas for phase detector to be implemented inside the microcontroller? $\endgroup$
    – Rima
    Commented Apr 6, 2023 at 13:31
  • $\begingroup$ @Rima Sure I'll add that option as to what I would do if it all had to be in a microcontroller- is it true you need a square wave out and will be comparing that to a square wave in? And the frequency is outside of the capture range of a standard multiplier based phase detector? What is the maximum frequency range of the signal you are trying to lock to, what is the loop BW you need, and what is your master clock rate? I'm not providing the full design, but this will inform feasibility of certain suggestions. $\endgroup$ Commented Apr 6, 2023 at 13:44
  • $\begingroup$ I want to lock frequency up to 10KHz. clock rate = 64MHz, I couldn't go further than 100KHz as sampling frequency. I am generating analog waves. I don't understand the capture range of standard multiplier based phase detector. $\endgroup$
    – Rima
    Commented Apr 6, 2023 at 13:51
  • $\begingroup$ @Rima What is the maximum to minimum frequency for the signal you are trying to track? What could it be worst case when you are first trying to acquire? $\endgroup$ Commented Apr 6, 2023 at 14:29
  • $\begingroup$ Max frequency would be for my case 10 KHz and there is no minimum frequency I have thought of, but it should be more than 100 Hz, i would say. As I have read from other literature, the phase slip starts to be more noticeable after 3-4 KHz and I have set the target for now to work till 10 KHz. I don't understand exactly the second question. My project is to phase lock a tip tilt mirror attached to an actuator. $\endgroup$
    – Rima
    Commented Apr 6, 2023 at 15:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.