# Matlab digital phase locked loop script

I am trying to extract carrier signal from amplitude modulated signal. The amplitude modulated signal is stored in a CSV file. I tried to calculate calculate carrier frequency by calculating the zero crossings. But the carrier frequency is not exactly same through out the period. it has minor deviation because of which exact carrier extraction is not possible. So I would like to write a PLL script and feed the amplitude modulated signal to extract the carrier. I found below code which would work as PLL.

% cosine output
c = 1;
% delayed cosine by one timestep
c_delay = 0;
% sine output
s = 0;
% delayed sine by one timestep
s_delay = 0;

% vectors storing the results by adding the samples one by one
sine = [];
cosine = [];
vco = [];
input_signal = [];

% PLL loop filter
b = fir1(100, 0.1);
% filter state because we just feed one value at a time in it and
% then come back to it every timestep so we need to save the state
zf = zeros(numel(b)-1,1);

v = 0;

% main loop: reading data one by one
for i=1:4000

% test signal, will be replaced by the input signal
% the PLL needs to lock on it, let's assume our
% frequency is 1% off. Should be f=0.1 but is f=0.099
% and we have some random phase angle.
y = cos(2*pi*0.0099999*i+pi/2.345543);

%"voltage" controlled oscillator with f=0.1 +/- v input
w0 = 2*pi*(0.01+v*0.002);
c_delay = c;
s_delay = s;
c = c_delay * cos(w0) - s_delay * sin(w0);
s = s_delay * cos(w0) + c_delay * sin(w0);

% phase detector
p = y*(-s);

% filtering out the 2f term
[v,zf] = filter(b,1,p,zf);

% let's save everything in handy vectors for plotting
input_signal = [input_signal y];
sine = [sine s];
cosine = [cosine c];
vco = [vco v];
end
subplot(2,1,1)
plot(input_signal);
subplot(2,1,2)
plot(cosine);


This code works fine for the smaller frequency of 0.1 Hz. But in my case the carrier frequency is close to 10kHz. If I change the center frequency to 10000 instead of 0.01 the code does not work. Can someone please help me to correct this code? Any new idea to extract carrier will also be very helpful.

Thanks!

• I am trying to extract carrier signal from amplitude modulated signal. Do you mean, you want to know the carrier's frequency precisely? A "PLL" solution sounds (too) complex to me, I would try an FFT so that you get frequency information, then find the peak. You have to tweak the FFT's settings to get a high enough frequency resolution. Commented Mar 16, 2021 at 13:34
• Another approach could be to shift the complete signal in frequency. For example by 9.9 kHz (10 kHz - 100 Hz), then a 10 kHz carrier will shift to 100 Hz. You do this as it is done in RF receivers: by multiplying the signal with a 9.9 kHz sinewave. Do an FFT on the shifted signal and there should be a peak at (or close to) 100 Hz. Commented Mar 16, 2021 at 13:38
• How was the filter designed ? Filter which works for 0.1 Hz may not work for 10 kHz.
– AJN
Commented Mar 16, 2021 at 15:42
• @Bimpelrekkie: In short, I am trying to demodulate amplitude modulated signal. For this, I need to multiply amplitude modulated signal with the carrier. So I counted the zeros crossings in the amplitude modulated signal and found the frequency of the carrier. Then I created a carrier signal and found that the carrier frequency in the amplitude modulated signal is not constant and by counting zeros crossing I have found mean frequency. By using this mean frequency I can not demodulate. So I decided to design a PLL to obtain the carrier signal from amplitude modulated signals. Commented Mar 17, 2021 at 13:07
• @AJN: At the moment I am facing problems with tuning VCO to 10KHz in the code. Currently in the above code VCO is tuned to 0.01Hz. When I change this value to 10KHz, I am not getting pure sine and cosine at the output of VCO. Once this is sorted, I will redesign the filter. Commented Mar 17, 2021 at 13:09

This is actually an answer to this comment. It may solve your original problem also.

At the moment I am facing problems with tuning VCO to 10KHz in the code. Currently in the above code VCO is tuned to 0.01Hz. When I change this value to 10KHz, I am not getting pure sine and cosine at the output of VCO. Once this is sorted, I will redesign the filter.

for i=1:4000
y = cos(2*pi*0.0099999*i+pi/2.345543);


i seems to be the time variable. Guessing the units from the above code $$\\sin(\omega_{rad/s}\cdot t_{second})\$$, the units of the time variable i is seconds. The system is effectively being simulated with a sampling period of 1 second since i=1,2,3,4,.... By sampling theorem, the above sampling frequency is too low. The time variable should increment by a value (much) smaller than $$\\frac{1}{2*10k}=50\mu s\$$.

Try modifying your code to look something like

ts = 1e-6; % ts has units of seconds
t = 0 : ts : 10  % t has units of seconds
n = length(t);

for sample_number = 1 : n
current_time = t(sample_number);

• Once your simulation starts using a proper sampling-period / step-size, be careful designing digital filters since a proper digital filter design requires the sampling-period to be considered while selecting the frequency. functions such as fir1 which design digital filters may take frequency values as inputs with specific units. the units may be either hertz (0 to fs/2) or radian-per-second (0 to $\pi$) or normalized (0 to 1).