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. 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.
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,
- 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.)
- use Direct Digital Synthesizer (DDS) to generate a reference signals.