天天看点

第4章:载波同步与锁相环仿真(2)一、用二阶锁相环对有多普勒频偏和载波随机相位的psk信号进行相干解调二、总结

第4章(2)内容如下:

  • 一、用二阶锁相环对有多普勒频偏和载波随机相位的psk信号进行相干解调
  • 二、总结

上一讲《载波同步与数字锁相环仿真(1)》主要讲解了一下锁相环的基本原理及其MATLAB实现,观察锁相环是如何跟踪信号相位,并且最终可以和接收到的信号同频同相。

其中,二阶锁相环的核心代码需要你扎实学习与掌握。

理解了锁相环的基本原理后,仍然有一些问题需要我们去解决,比如:

1、如何用数字锁相环对有多普勒频偏的2psk信号进行相干解调?

2、锁相环进入同步状态的时间要多久呢?能否调整呢?锁相环会不会跟不上信号的相位变化呢?

3、如果接收到的信号包含噪声,锁相环能否正常工作呢?或者说锁相环正常工作条件是什么呢?

一、用二阶锁相环对有多普勒频偏和载波随机相位的psk信号进行相干解调

我刚开始好不容易搞懂了二阶锁相环的MATLAB实现,写在了《数字锁相环的MATLAB实现》,而如何将其运用到有多普勒频偏的2psk信号的相干解调,调试代码与整理思路又花了好些天时间。

在写有多普勒频偏的2psk信号的相干解调时,我便充分认识到自己对于锁相环理论知识的欠缺。检查很多遍代码后,发现代码框架没有大问题,但就是死活不出来正确结果,这样的心情真是很磨人。

于是我从图书馆借出来西电郑继禹的《锁相技术》和杜勇的《锁相环原理及FPGA实现》,进行学习。然而理论知识太多,我还未融会贯通。

回到有多普勒频偏的2psk信号的相干解调,上一讲《载波同步与数字锁相环仿真(1)》的代码中,进入锁相环的信号还没有乘以双极性序列,即没有对基带信号进行调制。

我在《BPSK调制解调器仿真》的第三点“如何保证仿真正确性”中讲过:测试每个模块的正确后,再加入到大程序仿真中。

即当我们写一个大的程序时,为了避免总程序出错不知道从什么地方开始找,我们在最开始写每个程序模块的时候,先对其进行测试,测试正确后,加入到大程序后,来减少程序调试的错误。

这次将双极性序列乘以有多普勒频偏的载波进行测试。

注意到,由于发送端乘以 cos ⁡ w t \cos wt coswt ,接收端乘以 cos ⁡ w t \cos wt coswt +低通滤波,会把2w的频率滤除,只剩下有多普勒频偏的基带频率。因此,直接乘 cos ⁡ ( 2 p i ⋅ f d o p ⋅ t + p h i 0 ) \cos \left( {2pi \cdot {f_{dop}} \cdot t + phi0} \right) cos(2pi⋅fdop​⋅t+phi0) ,验证程序正确后,之后再乘以 cos ⁡ ( 2 p i ⋅ ( f d o p + f c ) ⋅ t + p h i 0 ) \cos \left( {2pi \cdot \left( {{f_{dop}} + {f_c}} \right) \cdot t + phi0} \right) cos(2pi⋅(fdop​+fc​)⋅t+phi0) ,后面的程序将看到这个过程。

%%%%%%%%%%%%%%%%%%%%%     环路滤波器原理仿真文件    %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%      second_loopfilter_sim4.m   %%%%%%%%%%%%%
%%%%%%%%%%%%%%%%    data:2020年10月2日     author:飞蓬大将军 %%%%%%%%%%

%%%%%程序说明
%%%利用锁相环完成频率跟踪过程的原理仿真,采用一个频率固定的信号源
%无加噪声过程
%


%%%    sim系列说明
%sim3:未乘以1,-1序列
%sim4:%乘以1,-1序列



%%%%%%    仿真环境
%软件版本:MATLAB R2019a

clc;
clear all;
close all;

fdop = 30; %多普勒偏移50Hz
phi0 = pi/6;
fs = 1e4; %采样频率
T = 1/fs; 
n = 3000;
tend = n*T;
t1 = 0:T:tend - T; %1到3000
phase1= 2*pi*fdop.*t1 + pi/6;  %输入信号相位变化
phase2 = zeros(1,length(t1));

frame_length = 20;
frame = ones(1,frame_length);
data =[frame randi([0,1],1,n-frame_length)];
bipolar_data = 2*data-1;

I_signal = bipolar_data.*cos(2*pi*fdop.*t1 + phi0);
Q_signal = bipolar_data.*sin(2*pi*fdop.*t1 + phi0);


%%%%加入噪声
signal = I_signal + 1j*Q_signal;

signal_temp =  awgn(signal,30,'measured');

%%%%%%%%%%%%环路滤波器参数设置
%%%%%2阶锁相环参数
Bn = 400; %噪声等效带宽
ts = 1/fs;%时间周期
damp = 0.707;%衰减系数
Kp = 1; %K0*K1相乘,下面公式默认了k0 = k1 =1
Wn = 2*Bn/(damp+1*(4*damp));
plus = 1; %环路滤波器增益
C1 = plus*8*damp*Wn*ts/(Kp*(4+4*damp*Wn*ts+(Wn*ts)^2));%环路参数1,C1 = alpha
C2 = plus*4*(Wn*ts)^2/(Kp*(4+4*damp*Wn*ts+(Wn*ts)^2)); %环路参数2  C2 = beta 

%%%%%采用等效变换积分器的2阶锁相环
A = zeros(1,n);
B = zeros(1,n);
error = zeros(1,n);



for k = 1:n
    rotate_sig = signal_temp(k)*exp(-1j*phase2(k));
    
    %%%分I、Q两路
    sig_I_pll(k) = real(rotate_sig);
    sig_Q_pll(k) = imag(rotate_sig);
    %%%-------松尾环鉴相算法
    u1(k) = sign(sig_I_pll(k));
    u2(k) = sign(sig_Q_pll(k));
    
    e(k) = sign(sig_I_pll(k))*sig_Q_pll(k)/sqrt(sig_I_pll(k)^2 + sig_Q_pll(k)^2);
    if (k>=2)
        %%%环路滤波器
       A(k) = A(k-1) + C2*e(k) ;
       B(k) = A(k) + C1*e(k);
       
       %%%相位累加
       phase2(k+1) = phase2(k)+ B(k);  
    end
    
    %%%%%%为了看到频差
    if(k>200) &&(k<n-200)
        freq(k-200) = (phase2(k)-phase2(k-100))/(2*pi)/100/ts;
    end
    
    
end

u1_temp = (u1+1)/2;
[err_number,bit_err_ratio]= biterr(data,u1_temp);


x = (1:n)/fs;
figure(1);
plot(x,e);
title('二阶锁相环,初始频差500Hz,噪声带宽300Hz');
xlabel('时间(s)');
ylabel('相差');
grid on ;


figure(2);
plot(freq);
title('二阶锁相环,初始频差50Hz,噪声带宽300Hz');
xlabel('时间(s)');
ylabel('频差');
    

%%%%%%%%%%%%%%% 实验结论
%%%%能够跟踪信号的频率
           
第4章:载波同步与锁相环仿真(2)一、用二阶锁相环对有多普勒频偏和载波随机相位的psk信号进行相干解调二、总结

图1 相差随时间变化图

第4章:载波同步与锁相环仿真(2)一、用二阶锁相环对有多普勒频偏和载波随机相位的psk信号进行相干解调二、总结

图2 频差随时间变化图

在上面的代码中,有极性鉴相器和松尾环鉴相器,这部分内容可以参考知网论文《卫星定时接收机的关键技术研究》,里面对捕获和跟踪有介绍,值得仔细阅读。

在《载波同步与数字锁相环仿真(1)》和《数字锁相环的MATLAB实现》的代码中,我们得出结论:噪声带宽值增加,捕获速度会加快,但是抖动会增加。

为了在一个符号内锁相环能迅速捕获并跟踪到信号,后续的抖动便会增加。对应到上面second_loopfilter_sim4.m 文件,读者可调整Bn也可进行验证。

有了多普勒频偏,怎么来设置相应的Bn?有没有什么规律呢?这个问题我还在思考中。

接下来,说一下噪声对锁相环路的影响。

详细内容可以看张厥盛的《锁相技术》第三章,本文不加证明的直接摘录书中一些重要结论,方便后续的代码实现。

锁相环的噪声与干扰主要是两个来源:一类是与信号一起进入环路的输入噪声与谐波干扰;另一类是环路部件产生的内部噪声与谐波干扰,以及压控振荡器控制端感应的寄生干扰等,其中压控振荡器内部噪声是主要的噪声源。

想一想,说这两类噪声与干扰有什么用呢?

在解决问题时,为了达到所有的优化目标往往是不可能的,常常需要trade-off。减小环路噪声等效带宽,可以有效滤除第一类噪声,但是压控振荡器的相位噪声主要集中在低频部分,所以这会使得压控振荡器的相位噪声大量通过。

就我个人认为,因为在仿真的过程中,我们不涉及压控振荡器的相位噪声仿真,所考虑的噪声只有第一类,也就是对信号加上的高斯白噪声。

如果这样的话,我们是不是可以使得环路噪声等效带宽设置尽可能小呢?

当然不行,因为等效噪声带宽又会影响捕获带和抖动情况。

有了上面的这段代码,我们怎么知道解调是否正确呢?

与理论的误码率曲线进行对比,是不错的方法,因此将实验所得的误码率与berawgn函数进行对比。

%%%%%%%%%%%%%%%%%%%%%     环路滤波器原理仿真文件    %%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%      second_loopfilter_sim6.m   %%%%%%%%%%%%%
%%%%%%%%%%%%%%%%    data:2020年10月2日     author:飞蓬大将军 %%%%%%%%%%

%%%%%程序说明
%%%利用锁相环完成频率跟踪过程的原理仿真,采用一个频率固定的信号源


%%%    sim系列说明
%sim3:未乘以1,-1序列
%sim4:乘以1,-1序列



%%%%%%    仿真环境
%软件版本:MATLAB R2019a

clc;
clear all;
close all;

%%%%%%%%%%%%%%%%%%%%%%% 程序主体 **************************


fdop = 20; %多普勒偏移20Hz
phi0 = pi/6;
fs = 1e4; %采样频率
T = 1/fs; 
% n = 3000;
n = 10000000;
tend = n*T;
t1 = 0:T:tend - T; %1到3000
phase1= 2*pi*fdop.*t1 + pi/6;  %输入信号相位变化
phase2 = zeros(1,length(t1));

frame_length = 20;
frame = ones(1,frame_length);
data =[frame randi([0,1],1,n-frame_length)];
bipolar_data = 2*data-1;

% I_signal = bipolar_data.*cos(2*pi*fdop.*t1 + phi0);
% Q_signal = bipolar_data.*sin(2*pi*fdop.*t1 + phi0);
% 
% 
% %%%%加入噪声
% signal = I_signal + 1j*Q_signal;
signal = bipolar_data.*exp(1j*(2*pi*fdop.*t1 + phi0));



signal_temp =  awgn(signal,9,'measured');

%%%%%%%%%%%%环路滤波器参数设置
%%%%%2阶锁相环参数
Bn = 200; %噪声等效带宽
ts = 1/fs;%时间周期
damp = 0.707;%衰减系数
Kp = 1; %K0*K1相乘,下面公式默认了k0 = k1 =1
Wn = 2*Bn/(damp+1*(4*damp));

plus = 1; %环路滤波器增益

C1 = plus*8*damp*Wn*ts/(Kp*(4+4*damp*Wn*ts+(Wn*ts)^2));%环路参数1,C1 = alpha
C2 = plus*4*(Wn*ts)^2/(Kp*(4+4*damp*Wn*ts+(Wn*ts)^2)); %环路参数2  C2 = beta 

%%%%%采用等效变换积分器的2阶锁相环
A = zeros(1,n);
B = zeros(1,n);
error = zeros(1,n);



for k = 1:n
    rotate_sig = signal_temp(k)*exp(-1j*phase2(k));
    
    %%%分I、Q两路
    sig_I_pll(k) = real(rotate_sig);
    sig_Q_pll(k) = imag(rotate_sig);
    %%%-------松尾环鉴相算法
    u1(k) = sign(sig_I_pll(k));
    u2(k) = sign(sig_Q_pll(k));
    
%   u3(iii) = sign(sig_I_pll(iii)+sig_Q_pll(iii));
%   u4(iii) = sign(sig_I_pll(iii)-sig_Q_pll(iii));
%   e(k) = sign(u1(iii)*u2(iii)*u3(iii)*u4(iii));
    
    %%%%%BPSK极性鉴相算法
    e(k) = sign(sig_I_pll(k))*sig_Q_pll(k)/sqrt(sig_I_pll(k)^2 + sig_Q_pll(k)^2);
    
    if (k>=2)
        %%%环路滤波器
       A(k) = A(k-1) + C2*e(k) ;
       B(k) = A(k) + C1*e(k);
       
       %%%相位累加
       phase2(k+1) = phase2(k)+ B(k);  
    end
    
    %%%%%%为了看到频差
    if(k>200) &&(k<n-200)
        freq(k-200) = (phase2(k)-phase2(k-100))/(2*pi)/100/ts;
    end
    
    
end

u1_temp = (u1+1)/2;
[err_number,bit_err_ratio]= biterr(data,u1_temp);


x = (1:n)/fs;
figure(1);
plot(x,e);
title('二阶锁相环,初始频差20Hz,噪声带宽300Hz');
xlabel('时间(s)');
ylabel('相差');
grid on ;


figure(2);
plot(freq);
title('二阶锁相环,初始频差20Hz,噪声带宽300Hz');
xlabel('时间(s)');
ylabel('频差');
    
%%%%%%%%%%%%%%%%%%%%%%%%    理论值    %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%  EbN0(dB)     berawgn(EbN0,'psk',2,'nondiff')
 
%%%%            3                      0.022878407561085
%%%%            4                      0.012500818040738 
%%%%            5                      0.005953867147779  
%%%%            6                      0.002388290780933 
%%%%            7                      0.000772674815378 
%%%%            8                      0.000190907774076 
%%%%            9                      0.000033627228420 
%%%%           10                      0.000003872108216 


%%%%%%%%%%%%%%%%%%%%%%%%    实验结果    %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%  EbN0(dB)       bit_err_ratio
%%%%            6           0.002394300000000           
%%%%            7           7.739999999999999e-04          
%%%%            8           1.930000000000000e-04           
%%%%            9           3.390000000000000e-05           
%%%%           10           3.900000000000000e-06  


%%%%%%%%%%%%%%% 实验结论
%%%%能够跟踪信号的频率并正确解调出数据
           

通过上面的代码,已经验证过锁相环可以用于有多普勒频偏的2psk信号的相干解调。读者也可继续测试不同的 E b / N 0 {E_b}/{N_0} Eb​/N0​ 下,得到的误码率。

上面的代码,没有基带成型、匹配滤波、上载波、捕获、下载波、信道编解码等过程。结合《第1章:BPSK调制解调器仿真》和《第2章:线性分组码》,便可以把代码补充完整。

至此,用锁相环进行载波同步的过程已经介绍完毕。

那么多普勒频偏达到多少,锁相环便会跟不上呢?即锁相环无法进入锁定状态。

举个例子来说,假如多普勒频偏10Hz,锁相环可以快速跟上,但是几百Hz频偏,锁相环便不能快速跟上了,需要的时间可能会很长。

在卫星通信中,由于卫星相对地面终端的移动速度特别快,多普勒频偏便会很大。

那有没有办法,让进入锁相环的信号频偏比较小呢?

在进入锁相环之前,可对信号进行初步的频偏补偿。举个例子,假如频偏是220Hz,我们用0-100Hz,100-200Hz,200-300Hz这样一段一段的频率去扫描。然后惊奇发现,频偏范围是属于200-300区间的,于是先补偿200Hz给信号,再进入锁相环,对信号进行跟踪。

那怎么判断出来频偏范围是200-300Hz这个区间的呢?

就是看信号频率离谁越近,就认为是落在哪个区间。因此,本质是最大似然估计的思想。

以上的用0-100Hz,100-200Hz,200-300Hz这样一段一段的频率去扫描的过程,其实信号捕获中频偏粗估计的过程。

值得注意的是,信号捕获和锁相环里面的捕获不是一个概念,信号捕获是指接收端判断信号有没有来了,来了的话,就是捕获成功,没来的话,就是捕获失败。

二、总结

从我个人调试代码的过程中发现,锁相环虽然好用,但是参数设置比较麻烦,理论分析又需要非常非常非常扎实的理论功底,而我目前还没有这么强的扎实功底。

因此,我是结合上述书籍与材料中的理论分析,然后不断的调整参数,比如环路噪声等效带宽Bn,环路增益等,来使得锁相环满足跟踪频率和解调信号的要求。这也再一次体现“理论指导实践,实践印证理论”的过程。

锁相环的内容很丰富,但是本科一般都不学习,确实比较难。在自学这部分的内容时,我对阅读又有了两点体会:

1、读经典材料

我现在越来越明白为什么大家说要读经典书籍和论文了,经得起时间考验的东西就是不太一样。比如我在上面提到的张厥盛的《锁相技术》,这可能会比你随便找一本锁相理论的书阅读起来舒服。

2、相互印证

读书籍或者论文,也别只读一本。最好是相同的知识点,看不同的书籍怎么讲,谁讲的对,谁讲的好,高下立判。虽然多花了一些时间,好像在阅读相同的材料,但是不同的人讲解知识的角度、侧重点,这也会让我有所收获,学习便也扎实了些。

特别感谢微信公众号“通信工程师专辑”的蔡凡博士,本人虽学习兴趣浓厚,但能力有限,且缺少大型工程项目实践,不足甚至错误之处,真的在所难免,欢迎你批评指正。

也欢迎读者朋友就以上讲到的相关技术问题与我交流,一起学习,共同进步。请你也别忘了把这篇文章分享给你身边正在学习通信专业的同学们,也许能够帮到Ta。这是《陈老湿·通信MATLAB》仿真的第4章,期待下次更新见!

继续阅读