在本文中,我们将进行纯仿真实验,不使用任何硬件设备。但是,我们会考虑无线信号在实际信道传输过程中所面临的一些诸如信道衰落、时钟同步等影响信号传输的问题。我们会在信道仿真模块中,通过设置参数来模拟这些问题,然后一步一步的解决它们,最终实现信号的正确解调解码。
本文的实例只是实现PSK调制解调的一种方法,这里我们使用了GNU Radio自带的PSK信号解调模块。除了本文的方法之外,还有很多其他的PSK解调实现方法,这些不同方法的实现细节相差较大。
本文目标
(1)理解信号失真和信道对信号传输的影响作用
(2)了解信号还原操作所涉及的步骤,如时钟恢复、多径效应消除、相位和频率纠正、符号解码和比特排序重构。
需要具备的基础知识:
(1)Suggested Reading list:https://wiki.gnuradio.org/index.php/SuggestedReading
"The ARRL Handbook." A kind of hodge-podge of stuff. If you already know what you're looking for, you might be able to find it here. http://www.arrl.org(第11.5节)
(2)GNU Radio系列教程(二):初级篇之GNU Radio介绍
(3)GNU Radio系列教程(六):初级篇之GNU Radio GRC 硬件使用实例之信号频谱分析
目录
一、发射一个信号
二、加上信道仿真
三、时钟恢复Timing recovery
1、什么是码间干扰?如何消除码间干扰?
2、锁相环时钟同步模块
3、使用Polyphase Clock Sync模块
四、多径效应
1、什么是多径效应
2、CMA均衡器
3、LMS DD均衡器
五、相位矫正和频率微调
六、解码
七、有用链接和联系方式
一、发射一个信号
本实验的第一步是发射一个QPSK信号。首先,生成一串比特数据,然后将其调制成复数星座数据(这里更准确的说,最好别叫调制,叫映射更合适一些,即将比特数据映射到星座图中的星座点。)为了实现这步操作,我们使用GNU Radio中的Constellation Modulator block模块,该模块通过Constellation Rect. Object和其他参数的设定来实现QPSK调制功能。
“Constellation Rect. Object”参数可以用来决定符号的编码方式。“Constellation Modulator”模块可以基于“Constellation Rect. Object”参数来实现调制(或称为映射)。在“Constellation Modulator”模块中可以设定是否采用差分编码(即“Differential Encoding”参数设置为“Yes”或“No”)。由于“Constellation Modulator”模块需要的输入数据是字节类型的数据,因此,在本例子中,我们使用“Random Source”模块生成取值空间为0-255的字节流。
对于“Constellation Modulator”模块中的“Sample per symbol”参数的取值,一般的取值原则是尽可能小,其最小值为2。通常来说,当确定了硬件设备的采样率之后,这个“Sample per symbol”取值是可以和GRC流图中的“samp_rate”取值一起帮助我们达到要得到的比特速率。由于我们在本文中只是做的纯仿真实验,没有使用任何软件无线电开发板,本例子中的“Sample per symbol”取值只要能满足GRC流图中的数据速率即可。例如,在这里,我们选定了“Sample per symbol”为4,这个取值比实际需要的取值要大,但是有利于在时域或频域来观察信号。
最后,我们需要设定“Constellation Modulator”模块中的“Excess BW”(带外带宽)因子取值,即均方根升余弦脉冲成形滤波器中的roll-off因子“alpha”。下图(mpsk_rrc_rolloff.grc)流图中在五个“Constellation Modulator”中分别设置了五种不同的roll-off因子“alpha”取值,即0.1(100m)、0.22(220m)、0.35(350m)、0.5(500m)、1。
在下边的图形中,红色曲线表示“alpha”取值为0.2,绿色曲线表示“alpha”取值为0.35。
mpsk_stage1.grc生成了QPSK信号,并同时绘制了发射信号(transmitted signal)和接收信号(received signal)的时域图、频域图和星座图。注意,这里还没有加上信道模块,“Throttle”模块的输出信号就看作是QPSK发射信号,“Decimating FIR Filter”模块的输出信号就看作是QPSK接收信号。
在星座图中,我们可以直观的看到过采样(因为我们把Sample per symbol设置成了4,其实实际上我们并不需要这么大的sps,所以叫做过采样)和滤波操作的作用。例如,过采样的结果就是我们在一个符号中生成了4个采样值。在本例子中,均方根升余弦滤波器带来了自干扰,也就是符号间干扰或叫码间干扰(inter-symbol interference, ISI)。ISI对于信号接收和还原来说是一个不利因素。我们将在后续的时钟恢复环节重点解决这个问题。
此刻,我们先观察生成的QPSK信号。在频域图形中,一方面,滤波器可以使得频域信号的带外功率明显降低;另一方面,“Throttle”模块的输出信号被看作是QPSK发射信号,图形中的图标是“Tx”(蓝色曲线),“Decimating FIR Filter”模块的输出信号被看作是QPSK接收信号,图形中的图标是Rx(红色曲线),通过对比发现,经过了“Decimating FIR Filter”模块的作用,接收信号的带外功率明显减少了,即在有效带宽之外,红色曲线的带外功率明显要低于了蓝色曲线的带外功率。这主要是因为,两个均方根升余弦滤波器形成了一个升余弦滤波器(奈奎斯特滤波器),实现了匹配滤波器的效果。
二、加上信道仿真
上述例子只是生成了一个QPSK信号。接下来我们会研究分析生成的QPSK信号在经过信道传输发射和接收过程中会发生什么样的失真效果。首先第一步是在上述例子的基础上,添加上GNU Radio GRC的信道模块(“Channel Model”)。
GNU Radio GRC的信道模块(“Channel Model”)可以帮助我们来仿真信号在信道传输过程中遭受的一系列影响因素。接收机面临的第一个影响因素就是“噪声”。接收机中存在的热噪声(Thermal noise)一般为加性高斯白噪声( Additive White Gaussian Noise (AWGN))。通常,我们在GRC中设定噪声的大小,是通过设定噪声的电压,而不是设定噪声的功率。原因在于,信道模块并不知道输入信号的任何信息,但是在计算噪声的功率时,我们是需要知道信号的带宽之后才能计算得到功率的。因此,我们通常是基于仿真流图程序的其他参数,来推算噪声的电压值。
另外,在发射端和接收端之间,一个重要问题就是二者的本地时钟同步问题。如果二者时钟不同步,则会导致信号的频率发生偏差。例如,发射端本来是要在中心频率fc(例如,450MHz)发射信号,但是由于时钟精度问题,发射端的实际信号发射频率是fc+f_delta_1。与此同时,接收端存在一个时钟偏差f_delta_2,也就是接收端本来要在中心频率fc(例如,450MHz)接收信号,结果实际上却是在fc + f_delta_2处接收信号。这样一来,接收端与发射端相比,存在着f_delta_1+f_delta_2的偏差。(f_delta_1、f_delta_2可以是正数或负数。)
与发射端和接收端时钟相关的另一个问题,就是采样点问题。由于在生成QPSK信号的时候,我们进行了过采样和脉冲成形操作,那么在接收端的时候,我们就需要考虑如何确保在原始的采样点出进行采样,以此来尽可能降低码间干扰的影响,尽可能提升接收的有用信号功率。理想情况下,类似于mpsk_stage1.grc中的匹配滤波情形,我们可以在过采样后的4个采样点中找到一个合适的原始采样点。但是,当发射端和接收端的时钟不同步的情况下,理想采样点是很难找到的。
在下图的GRC流图程序中,我们针对加性噪声、频率偏移、时钟偏移进行了仿真,在“Channel Model”中的参数设置中,“Noise Voltage”=0.2(200m)、“Frequency Offset”=0.025(25m)、时钟偏移“Epslion”=1.0005。
上图中,我们发现星座点已经乱成了一团,接下来我们分别解决这些加性噪声、频率偏移、时钟偏移问题。
三、时钟恢复Timing recovery
为了实现时钟还原,我们将采用GNU Radio GRC中的锁相环时钟同步(Polyphase Clock Sync)模块,该模块具有几个功能:(1)实现时钟恢复;(2)在接收端提供一个匹配滤波器,消除码间干扰ISI;(3)实现降采样(降采样是相对于过采样来说的),将信号转换为1 sps(sample per second)。
在“Polyphase Clock Sync”模块内部,采用的是一种“polyphase filterbank ”技术。
https://wiki.gnuradio.org/index.php/Polyphase_Clock_Sync
该技术的大致原理为,该算法对输入信号进行差分计算,并在一系列的滤波器中设置不同的时间,只要滤波器的数量足够多,达到了时钟恢复所需的数量,其中的一个滤波器就可以输出正确的时间所对应的相位。
时钟恢复的最主要效果就是,可以找到输入信号的最佳采样时间,并在最大化每个采样的信噪比的同时,尽可能降低码间干扰。
1、什么是码间干扰?如何消除码间干扰?
在正式进行时钟恢复之前,我们先看看到底什么是码间干扰ISI。我们可以通过symbol_sampling.grc流图程序来观察什么是码间干扰。在symbol_sampling.grc流图程序中,我们用“Vector Source”模块生成了四组序列,每组都是100位0、1组成的序列。在该程序中,第一部分是通过使用“Interpolation FIR Filter”模块实现sps倍过采样(例如这里sps=4,Interpolation参数为4),并使用了一个均方根升余弦滤波器。第二部分是通过使用“Decimating FIR Filter”模块与第一部分的“Interpolation FIR Filter”组合起来形成了一个奈奎斯特升余弦滤波器(匹配滤波器)。下边的程序输出波形对比了均方根升余弦滤波器和升余弦滤波器的输出信号。均方根升余弦滤波器的输出信号图形中,在每个符号的理想采样点处,其他符号存在一些功率能量。这样一来,所有这些符号累加起来,就会导致理想采样点处的符号发生失真。然而,在奈奎斯特升余弦滤波器(匹配滤波器)的输出信号图形中,在每个符号的理想采样点处,其他符号的功率都是0,这也就意味着,只要我们的采样时刻把握准确,每个采样点处的某个符号与其他符号之间没有任何码间干扰,这就展示了如何通过使用匹配滤波器来完全消除ISI。
上述程序(symbol_sampling.grc)中,我们可以随便修改sps、带外带宽、滤波器的抽头数等数值,并对比观察这些数值对采样点的影响。
接下来,我们将利用symbol_sampling_diff.grc流图程序,分析发射端和接收端时钟差异到底会给信号采样带来多大的影响。发射端和接收端的时钟不可能做到百分之百的同步,这主要是因为:1)发射端和接收端的开始采样时间不一样;2)任何两个设备的时钟无法做到完全同步。为了模拟发射端和接收端之间的时钟差异,我们采用了“Polyphase Arbitrary Resampler”模块,并通过其参数“Resampling Rate”来调整了发射端和接收端的采样时间,即设置“Resampling Rate”=1.125。这个1.125数值是为了明显展示出时钟的差异性,实际上现实系统中这个时钟差异取值都在百万分之一的量级。但是,值得注意的是,本例中,我们连理想的采样周期也是不知道的,在这种情况下,即使是发射端和接收端的时钟做到了同步,那么任何采样操作仍然也是会带来码间干扰的。
在这里,我们接下来的主要任务就是如何在只知道接收信号采样值的情况下,实现发射端和接收端的时钟或采样时间同步,这叫做时钟恢复(或时间恢复)。
2、锁相环时钟同步模块
有许多中可以用来实现接收端时钟同步的方法,这些方法几乎都要用到一些反馈控制环的思想。一般来说,可以借助于前导码来实现同步。我们将利用polyphase filterbank时钟恢复技术来实现时钟同步。
通过计算第一个到达接收端信号的差分值(这个差分值域时钟偏差是相关的),锁相环时钟恢复模块实现了三个功能:1)实现时钟恢复;2)实现匹配滤波器,消除了ISI;3)降采样,将采样率调整为1sps。
我们使用symbol_differential_filter.grc流图程序来观察差分滤波是如何帮我们实现时钟同步的。首先,我们将观察当不存在发射端和接收端时钟差异时的接收信号,需要将“Polyphase Arbitrary Resampler”模块的“Resampling Rate”参数设置为“1”。观察输出的波形,发现“sym0”波形的最高点(拐点)出现在0.22ms处,表示我们需要的采样点在0.22ms。“Decimating FIR Filter”模块(抽头设置成了[-1, 0, 1])生成的“Symbol0”的差分(求导值),观察图形发现,该滤波器输出信号在0.22ms处的取值正好为0。这就表明,我们找到了最佳的采样点。
那么,当存在时钟偏移的时候,情况会是什么样的呢?即在“symbol0”曲线到达峰值(拐点处)的时间点处,其差分值(d(symbol0)/dt)不等于0。
接下来,我们将在symbol_differential_filter_phases.grc流图程序中,使用一些列的滤波器,滤波器有不同的相位。理论上,只要我们有足够多的滤波器,那么这些滤波器中就必然有一个滤波器可以帮我们得到正确的采样点时间。如下图所示,程序中使用了5个滤波器,对应着5个不同的相位。可以理解成这5个滤波器把0到2pi的相位平均分成了5份。这里,我们使用“fractional resampler”模块来实现从0到1之间的相位偏移。不过这样操作后会产生延迟,因此,我们在“Fractional resampler”模块的后边追加上了“Delay”模块。
在该程序输出波形中,我们看到标记为“d(sym0)/dt+phi3”的波形,在“sym0”最高峰(拐点)所对应的时间点处的采样值为0。这意味着,我们的理想采样点处于这个相位偏差值。虽然这个程序的时间精度不是特别精确,但是基本也展示出来了不同滤波器不同相位偏差的差异性。
上述结果只是纯仿真的结果,在实际发射接收过程中,所有滤波器的某时刻采样点不可能同时出现在同一个时间点上。我们不得不通过采取过采样来逼近这个效果,因为过采样可以为我们接下来深入分析提供帮助。我们可以将不同滤波器看作是一个过采样指数为M的复杂滤波器,例如本子中的M=5。在原始信号sym0的最高峰(拐点)对应的时刻,我们以5倍过采样来查找到底哪个滤波器的输出信号是0。这样做的后果是,可能会带来较大的计算开销。而且计算开销是与采样率成正比的。但是,如果我们通过调整不同滤波器的对原始信号相位的修改,我们就可以避免产生过大的计算开销。因此,在上述的例子中,我们将采样率偏移了1.2倍,并通过5个滤波器的相位偏移,找到了最佳采样点所对应的相位偏差。但是,我们仅仅有5个滤波器,如果在不同滤波器之间存在任何采样偏差,仍然会带来明显的ISI。为了避免此种情况发生,我们将在接下来的例子中使用32个滤波器,以此来尽可能保证ISI噪声低于16比特量化噪声。如果我们有更高的要求,我们还可以使用更多个滤波器。
到这里,我们知道了,原来我们可以通过使用多个滤波器来找到其中一个能够实现最佳采样的滤波器,实现时钟恢复。但是我们如果才能自动找到这个滤波器呢?为了解决这个问题,接下来我们将使用二阶控制回路(2nd order control loop)。差分滤波器的输出信号是存在错误的信号。控制环路开始工作于其中一个滤波器,计算输出信号作为错误信号(error signal)。接下来控制环路根据错误信号,等比例的增加或减少滤波器,直到找到错误信号最接近于0的滤波器,这就是我们要找的最佳滤波器。【这句话暂时还不是理解,后续继续琢磨。】
从github下载的GNU Radio源码中,在“gr-digital”文件夹下的“examples”文件夹下,找到“ example_timing.py”脚本,你可以运行该脚本,观察“Polyphase Clock Sync recovery”的“收敛”特性。
3、使用Polyphase Clock Sync模块
现在,我们将在仿真程序mpsk_stage3.grc中使用“Polyphase Clock Sync”模块。该程序中“Channel Model”模块的输出信号输入给“Polyphase Clock Sync”模块,该模块使用了32个滤波器,“Loop Bandwidth”为2pi/100,“Samples/Symbol”为4.004。这里,为什么要设置为4.004?只是我们为了将sps设置的与原本“Constellation Modulation”模块的sps稍微不同而已,以此来表示发射端和接收端的时钟偏差。在“Channel Model”模块中,“Epsilion”的数值为“time_ offset”参数,该参数的默认值为1.0。
当运行mpsk_stage3.grc程序时,我们会看到左边的星座图是没有实现时钟恢复的(星座点虽然能大致看出来是QPSK,但是比较凌乱),右边的星座图是实现了时钟恢复的(基本上算是一个可以接受的QPSK星座图),但是由于在“Channel Model”模块中设置了噪声的电压(即例如“Noise Voltage”=200m),所以即使是右边实现了时钟恢复的星座图,从星座点也能看出来存在一定的噪声。
我们可以调节“Timing Offset”的数值,在调节这个数值的过程中,你会发现,右边实现了时钟恢复的星座图保持不动,这说明确实实现了时钟恢复,不会受“Timing Offset”的影响。但是,当我们调节“Frequency Offset”数值时,会发现右边实现了时钟恢复的星座图会变成一个圆圈,但是星座点固定是在一个圆上。这说明,虽然存在频率偏移,但是星座图仍然保持了正确的时钟,但是由于mpsk_stage3.grc程序没有解决频率偏移的问题,所以我们需要在接下来的程序中,利用其它的模块来抵抗频率偏移问题。此外,“Channel Model”模块中的“Taps”参数可以用来仿真传输信道的多径效应,当增加了多径效应仿真(例如将Taps由1修改为其他的复数取值),时钟恢复操作对于多径效应具有一定的鲁棒性的,但是它无法完全消除多径效应的作用,星座点变得没有那么集中,这需要后续我们专门针对多径效应,采取均衡器来完全消除多径效应作用。
接下来,我们将先采用均衡器来解决多径效应,然后再采用科斯塔斯环来解决频率偏移问题。
四、多径效应
1、什么是多径效应
何为多径效应?多径效应(multipath effect)指电磁波经不同路径传播后,各分量场到达接收端时间不同,按各自相位相互叠加而造成干扰,使得原来的信号失真,或者产生错误。比如电磁波沿不同的两条路径传播,而两条路径的长度正好相差半个波长,那么两路信号到达终点时正好相互抵消了(波峰与波谷重合)。【摘自百度百科-多径效应】
在发射端和接收端之间,不仅仅存在一条传输路径,在发射端和接收端之间存在的物体会成为信号传输的反射物,导致生成新的传输路径,最终形成多条路径传播的效果。
多个路径信号到到接收端叠加在一起的作用可能会导致信号失真,当两个路径信号达到接收端的时间差小于符号周期的话,那么失真发生在一个符号周期内部,叫做符号内多径干扰。当两个路径信号达到接收端的时间差大于符号周期的话,信号失真作用与相邻的不同符号,这叫做符号间干扰(也经常叫做码间干扰)。multipath_sim.grc(GRC v3.7和v3.8,这个程序有了较大的变化,以下截图是v3.8的)程序给出了多径效应的作用结果。我们将在后续的程序中,使用均衡器来解决多径效应问题。类似于音响的立体均衡器,用于无线通信中的均衡器也是通过改变(加大或减小)特定频率的信号增益,来使得到达接收端的信号变得均衡。
该程序建立了一个拥有五个均衡器控制的信道模型,其中四个是可以由用户调节的,一个是固定不变的。用户可以在0-1之间来调节,当取值为1时,均衡器将允许信号无损失的“通过”,当取值为0时,则均衡器将完全阻止信号“通过”,注意这里的通过是打双引号的。
在实例multipath_sim.grc中,我们通过明确控制频域的仿真方式,来实现对接收信号频率响应的纠正和调节。最终目标是利用均衡器来对抗信道的衰落作用,使得接收信号在频域上看起来变得平坦。但是,与在实例multipath_sim.grc中手动修改taps不同的是,一般我们都是通过选用合适的均衡器并设定好均衡器的参数,由均衡器算法来自动实现均衡效果的。均衡器中的taps抽头越多,效果会约好,但是也会带来更多的计算开销。
2、CMA均衡器
GNU Radio中有两个经常用的均衡器,CMA均衡器和LMS DD均衡器。CMA(Constant Modulus Algorithm)均衡器是一种盲均衡器,只适用于信号幅度固定的场景。这也就意味着注入MPSK调制信号(幅度固定,相位变化)是非常适合用CMA均衡器的。
CMA算法的输入是均衡器的抽头数量,这个数量是基于对信道质量的预测和信道的实际观测值来决定的。我们需要在确保能够满足信道均衡要求的前提下,尽量让抽头数小一些,以此来避免产生过大的计算开销。
在mpsk_stage4.grc程序中,CMA算法使用了11个抽头。运行该程序,观察效果。
运行该程序后,我们会发现均衡器起到的作用。对比“CMA Equalizer”模块的输入和输出信号,在经过均衡处理之前的信号在不同的频率上,增益起伏变化较大。但是在经过了均衡处理后的信号则在不同频率上变得非常平坦。
3、LMS DD均衡器
与CMA是一个盲均衡器不一样,LMS DD均衡器是一个需要知道接收信号知识的均衡器。均衡器需要知道接收信号的星座点,以此来消除多径效应,并且通过观察均衡结果来动态更新抽头的参数。LMS DD均衡器可以用于CMA均衡器无法满足的场景,例如QAM调制信号场景(幅度是不固定的)。
如果接收信号质量太差(SNR太差),则LMS DD均衡器的已知信息则会误导其后续的均衡操作,进而影响后续的解调解码工作。当接收信号质量好的时候,则LMS DD均衡器则会发挥积极有效的作用。在实际系统中,一般是先用盲均衡器来得到足够好的信号,然后再用非盲均衡器来继续完成均衡操作。这里不再展示LMS DD均衡器,大家可以基于mpsk_stage4.grc来改造完成LMS DD均衡器程序。
五、相位矫正和频率微调
在实现了信号均衡操作后,我们还需要解决相位和频率偏移的问题。有两件事请需要做:第一,使用一个二阶环路来跟踪相位和频率(频率其实就是相位的求导结果),第二,这里我们做的恢复是微调恢复。因此,我们必须确定已经确定了理想频率。如果没有确定的话,那么我们使用二阶环路的结果也无法达到预期效果。接下来,我们将在mpsk_stage5.grc中使用科斯塔斯环(Costas Loop)。科斯塔斯环可以用于为BPSK、QPSK、8PSK实现相位和频率同步。
在“Costas Loop”模块中,需要确定两个参数,第一,“Loop bandwidth”参数,第二,调制阶数(例如BPSK是2,QPSK是4,8PSK是8)。下边左边图形表示经过“CMA Equalizer”处理的输出的时钟同步信号,但是由于存在噪声、时钟偏移、频率偏移等影响因素,星座点虽然在一个圆圈上,但是不是正常的QPSK星座图。下边右边图形是经过“Costas Loop”模块处理后的信号,已经变成了一个正常的QPSK星座图(尽管由于存在噪声,每个星座点不是一个点,而是一小簇)。
六、解码
到现在为止,前边已经将比较难啃的骨头都解决了。最后一步就是实现解码了。我们在mpsk_stage6.grc程序中,添加一个Constellation Decoder模块来实现解码。并使用“Map”模块来实现符号映射关系的转换。使用“Unpack K Bits”模块来分解bit,得到原始的bit流数据。
但是,我们如何才能判断我们解码的数据是否是正确的呢?由于我们是仿真程序,我们知道发送的原始bit数据,我们通过对比这两份数据来查看解码数据是否正确。但是由于前边做各种同步和均衡等操作,引入了延迟,所以我们需要将发送的原始数据进行延迟后,再跟解码后数据进行比对。
七、有用链接和联系方式
https://wiki.gnuradio.org/index.php/Guided_Tutorial_PSK_Demodulation
淘宝店铺、QQ技术交流群、CSDN联系方式如下:
微信公众号二维码: