GNU Radio 入门培训
1. GNU Radio介绍
1.1 什么是GNU Radio
GNU Radio是一个完全开源的软件无线电结构平台,它可以用来设计和仿真,也可以用来连接真实的无线电系统。GNU Radio是一个高度模块化,采用流图类形式的软件架构平台,它本身提供了许多模块库,使用者可以很快速的使用这些模块来建立关于信号处理的流程。
1.2 为什么要用GNU Radio?
从前,在开发无线通信设备时,工程师必须开发一种特定的信号级检测电路,设计一个特定的集成电路,该芯片将能够解码或编码。软件无线电(SDR)采用模块化处理,处理无线电信号的算法在计算机上实现。
你当然可以用你的电脑连接无线设备在一个程序中你从头开始编写算法。但这就变得很麻烦:为什么你要重新执行一个标准的滤波器?为什么你要关心如何在不同的处理模块之间移动数据?用高度优化的方法,而不用自己写不是最好的吗?你如何让你的程序在多核架构上很好地扩展,而且在嵌入式设备上运行得很好?
进入GNU Radio:框架致力于编写计算机信号处理中的应用。GNU Radio包易于使用且可重用的模块功能,提供良好的可扩展性,还提供了一个广泛的标准算法库,适用于各种不同的通用平台。平台本身提供了大量的实例,供使用者参考。
1.3 信号处理流程
关于信号的一些原理
首先设备接收到的是模拟信号,电脑不能识别和处理,我们必须转化成数字信号。经过ADC转化成数字信号后,我们的电脑就能识别,可以对数据进行处理,比如数字滤波,调制解调,信号识别等。
模块化流程化的数字信号处理
为了对数字信号进行处理,我们必须首先考虑信号处理的步骤(滤波、调制解调、分析、检测),然后我们调用相关的模块,用流程图的方式连接起来就组成了一个无线通信系统。最简单的一个实例如下:
当一个应用被创建时,一个完整的模块化的流程图就建立起来了。这个在GNU Radio就叫流程图。下面是一个多个模块组成的流程图:
GNU Radio是一个利用这些信号处理模块创建流程图的软件架构平台,这些组成了GNU Radio各种应用。
作为一个GNU Radio的使用者,你可以使用这些GNU Radio提供的信号处理模块,也可以把它们嵌入到你自己的更加复杂的信号处理流程图中,而不用关心这些数据如何在这些模块之间流动,一旦你的程序连接好,它们会自动进行。
GNU Radio包括了大量的常用模块,这里列出了一些仅供参考:
信号产生模块:
Constant Source
Noise Source
Signal Source
...
调制解调模块:
AM Demod
Continuous Phase Modulation
PSK Mod / Demod
...
仪器模块:
Constellation Sink
Frequency Sink
Time Sink
...
信道模块:
Channel Model
Fading Model
Dynamic Channel Model
...
滤波器模块:
Band Pass / Reject Filter
Low / High Pass Filter
IIR Filter
...
信号分析模块
FFT
Log Power FFT
Goertzel {{collapse(Resamplers)
...
使用这些模块,许多标准的任务,如同步,测量和可视化,可以通过只连接适当的模块到您的信号处理流程图就可以实现。此外,你可以自己写信号处理模块,把现有的块与一些提供新的智能功能,连同一些逻辑实现。或您可以开发自己的模块,对输入数据和输出数据进行控制。因此,GNU Radio是一个信号处理块和开发者互动的发展框架。它有一个广泛的标准库的块,并且有很多系统可供开发人员参考。
2. 第一次使用USRP
请根据你购买的设备在 1,2,3,4 点中选择相应的方法配置你的计算机和设备。然后再根据 5,6 项测试软件环境和设备。
2.1 USRP 网络接口系列(USRP N200, USRP N210, USRP2)
主机网络设置:USRP 网络接口系列初始 IP 地址为 192.168.10.2 。需要把 PC 机的 IP 设置为与 USRP 在同一网络。
1.1 左键单击桌面右上角的网络连接图标,然后选择下拉菜单的“编辑连接..”选项打开“网络连接”窗口。
1.2 在“有线”选项卡中点击“添加”,设置网络连接名称为任意名称(以 usrp为例),并在“设备 MAC 地址”下拉菜单中选择将用于连接 USRP 的网卡:
1.3 点击“IPv4 设置”选项卡,点击添加按钮,输入 IP 地址: 192.168.10.2,子网掩码:255.255.255.0。完成后保存设置。
1.4 给 USRP 供电,并用网线连接 USRP 和 PC。在 PC 机桌面右上角左键单击网络连接图标,在下拉菜单中选择 usrp 连接。
1.5 在终端运行:uhd_find_devices,看 PC 机是否已经连接上 USRP:
1.6 给 USRP 烧写固件(一般在第一次使用或更新 UHD 时需要做这一步):sudo usrp_n2xx_simple_net_burner
到此,整个 UHD+GNU Radio 平台就算搭建好了。
2.2 USRP B100 和 B110
给 USRP 供电,并用配套的 USB 连接线连接 USRP 和 PC 机。由于每次运行程序,UHD 会自动给 USRP 装载固件和 FPGA 镜像,该系列不需要进行特别设置。
2.3 USRP B210 和 B200
提示:
1)B200 不需要额外供电,所以 Ettus 没有提供电源适配器;
2) B210 在 1 收 1 发情况下, 也不需要电源, 双收双发情况下才需要外接电源适配器。为了方便烧写固件和 FPGA 镜像, 先不使用电源适配器, 等烧写完成后, 在有需要的情况下再接上电源。
用配套的 USB 连接线连接 USRP 和计算机。在终端运行:(可能需要sudo权限)
uhd_usrp_probe
烧写完 firmwa 后,很可能没继续烧写 FPGA 镜像, 显示 Empty devices found。
这时候将 USRP 的 USB 连接线从计算机上拔出来,再马上插回去,重新运行 uhd_usrp_probe
这时可以正常烧写固件和 FPGA 镜像了。
3. GNU Radio流程图编程
3.1 开始了解GRC
我们已经知道GNU Radio是一个各种信号处理模块的“容器”。在这里,我们将从一个简单的例子讲起,展示如何使用GNU Radio Companion(GRC).我们需要清楚的是,GRC是允许我们创建Python文件图形的,不过流程图的方式更加简化了GNU Radio的使用。
首先我们来看一下GNU Radio Companion的界面。它包括4个区域:模块库、工具栏、函数输出窗口和工作区域。
学会一个东西最好的方法就是亲自尝试,想到一个问题,然后自己找出答案。大家可以首先在界面摸索,打开GRC的方式,在终端输入命令:
gnuradio-companion
3.2 找到自己需要的模块
在右边的模块库里面有各种不同类型的信号处理模块,包括了GNU Radio的标准模块和我们初始化的模块。怎样快速的找到我们自己需要的模块呢?假设我们需要一个产生信号的模块,我们可以看到有一个叫做Waveform Generator的类型,打开就可以看到各种产生信号的模块了。那么假设我们需要一个展示波形图,但是又不确定哪种模块是效果最好的,又怎么办呢?我们在上一章节知道,有一个叫sink的类型,但是右边并没有发现sink的类型。这个时候我们就需要使用搜索的功能了,按Ctrl+f,或者点击搜索按钮,然后输入模块的关键字sink,我们可以看到很多关于sink的模块了:
现在让我们添加一个叫QT GUI Time Sink的模块。我们可以通过双击或拖动的方式。
3.3 修改模块的参数
工作区域里面包含各种信号处理模块和变量。我们双击打开模块,设置它的参数属性。如下图:
在不同的应用系统中,我们可能需要修改这些默认的参数。我们把原来的名字去掉,可以看到ID字样编程蓝色。这种颜色表明信息已经被修改,但是还没有保存。我们再尝试一下修改windows size为300,300,单击OK。然后我们可以看到尺寸的改变。然后,我们看到documentation:
看用颜色标记的字段,我们知道ID用来确定python文件名字和相关类的名字。
然后,我们删除掉ID里面的字符串,看到最底下出现了红色的报错信息,同时,ID也变成了红色,这样我们能够很方便的确定错误的所在。
为了方便,我们取ID的名字为”tutorial_two_1”,同时将Generate Options改成”QT GUI”,因为我们采用的是QT GUI sink,而不是WX GUI sink,在最新版的GNU Radio,默认的是QT GUI.GRC是一个图形化的界面,它是基于python环境的。所以当我们执行一个流程图时,实际上我们真的运行的是一个python程序。ID是用来命名python文件名,与GRC文件保存在同样的路径下。默认情况下,ID是top_block,所以它创建一个为top_block.py的文件。更改ID使我们可以更改保存的文件名,以更好进行文件管理。
这个GRC-Python连接另一个结果是,Python可以控制GRC的参数属性。事实上,所有的输入框属性或变量,我们使用时被解释为Python。这意味着我们可以使用Python调用设置属性,如调用NumPy或其他GNU Radio功能。这方面的一个常见用途是称为filter.firdes滤波器设计工具从GNU Radio建立我们的滤波器抽头。
注意的另一个关键是接口不同的颜色。这些实际上对应于不同的数据类型,我们将在本教程后面稍后覆盖。
3.4 第一个信号流程图
现在我们了解如何找到块,如何将它们添加到工作区,以及如何编辑块属性,我们尝试建立一个将信号输出到示波器的流程图,注意模块之间的数据类型的匹配:
注意到有一个叫throttle block的模块:在本教程后面的更详细的解释是什么。现在,可以了解的是这个模块确保流程图不消耗100%的CPU周期,不然你的电脑可能反应不过来。
在此之前,我们先来看一下工具栏。
这里主要是一些流程图软件执行的一些命令,如新建,打开,保存等。让我们开始我们的流程图,我们给它取名叫做tutorial_two。这里有几个重要的工具,Generate flowgraph, excute flowgraph,分别是产生GRC(生成.py),和运行GRC。在help里面的type,我们可以看到每种数据类型对应的颜色。
3.5 关于Generate Options设置
有两种常用的设置QT GUI和WX GUI。最常见的错误就是设置的Generate Options与实际我们用的不匹配。具体来讲,就是我们Generate Options设置的是QT GUI,但是我们构造的流程图却是WX GUI我们会的到如下的报错信息:
反过来的话,也会得到类似的报错信息。所以,我们必须首先确定自己选用的是QT GUI还是WX GUI。
3.6 查看输出
让我们点击Execute按钮启动程序,我们可以看到如下的波形:
这是一个复数类型的波形。我们简单化一些,选用别的数据类型。关掉程序,我们打开Help-Type,可以看到如下的数据类型的代表颜色:
在这里,我们基本上可以找到所有的数据类型。我们看到我们的流程图的接口是蓝色的,很明显这是32位浮点型组成复数形式,现在我们可以解释刚才输出有两个波形的情况了,Time Sink输入一个复数,然后输出它的实部和虚部。现在,我们尝试修改以下信号源的数据类型,将其改为浮点型,然后我们看到它的接口编程橘黄色的,当我们把它和Throttle Block连接时,看到有红色的报错,我们点击工具栏的红色的横杆,可以看到具体的报错信息:
报错信息显示,数据长度不匹配。这是由于我们的数据类型不匹配的原因。GNU Radio不允许不同的数据类型之间直接连接。我们把所有的模块都改成浮点型的,然后再次运行,可以看到如下的波形:
现在我们可以看到,只有一个波形输出了,我们可以尝试用鼠标放大或者缩小。
3.7 使用GNU Radio Companion
现在我们已经能够创建自己的流图了,我们进一步的来学习一些GNU Radio Companion有关知识。
1. 关于Throttle Block
首先,我们来讨论下Throttle Block,之前在我们的流图有用到过。下图是添加Throttle 模块和不添加Throttle 模块的CPU的使用率对比:
我们可以看到,当流图没有连接硬件也没有连接Throttle 的时候,CPU基本是满负载运行的。在一个流图中我们只需要一个Throttle 就可以了,不管它是有几个输入输出。我们可以认为Throttle 起到限速的作用,设置高的速率,流图执行快,设置低的速率流图执行慢。打个比方,比如我们设置Throttle 为1e6,另一个设置1e3,我们可以看到CPU在1e6的情况下比1e3占用更多的资源。当有硬件连接的时候,我们不需要Throttle 模块,因为硬件本身已经对速率有了限制。
2. 关于采样率
我们已经知道硬件需要设定特定的采样率来实现某些特定的功能,现在我们来自己创建一个GRC,来看看不同的采样率之间有什么区别:
根据上图配置好参数:
QT GUI Chooser模块设置3个采样速率,ID改为samp_rate
所有的source模块的Sampling Rate改为samp_rate
音频模块改为48e3
所有的sink模块的sampling rate改为audio_rate
在这里,我们可以看到没有Throttle 模块,这是因为这里有音频硬件。点击运行,设置sample rate为48e3,可以听到熟悉的电话的拨号音,再看一下fft,确实有两个分别为440Hz和350Hz的频段。
尝试下,当改变sampling rate比audio sampling低的时候,看能否还能听到拨号音。再尝试下,当改变sampling rate比audio sampling高的时候,看能否还能听到拨号音。正常的话,应该听不到拨号音,因为声卡的速率和我们采样的速率不匹配。所以,任何时候,都应该设置正确的采样率。
3. 瀑布图
现在来看一个由probe,soundcard以及QT Sink模块组成的正弦信号瀑布图:
请参考上图设置好参数,另外,必须注意的是Audio Sink的Sample Rate。设置好后,点击运行,可以看到:
3.8 总结
现在我们应该知道流图的基本原理,能有找到自己需要的信号处理模块,正确的设置采样率。如何发现并定位错误,怎样设置相应的数据类型,用户可以自己动手,多多尝试,这样就能够比较快的上手GRC了。
4. GNU Radio与硬件
4.1 使用UHD Blocks
这里我们采用的是Ettus USRP B200,使用的驱动是UHD,所以我们可以在gr-uhd找到我们需要的source和sink模块。为了使用UHD Blocks,首先的必须装好UHD。安装成功后,在GNU Radio Companion中会发现UHD的相关模块。
4.2 发射一个QPSK信号
首先我们利用现有的模块建立一个流图。然后,通过移掉相关模块来实现QPSK的发射。流图如下:
运行结果如下:
然后,我们移除一些和添加一些模块,来连接发射一个真实的信号。由于是真实的无线信道,所以移除noise和add模块。因为有硬件限制速率,所以也不再需要Throttle block。转变成真实的无线系统是很容易的,我们在UHD Sink里找到UHD USRP Sink模块,然后添加到刚才的流图的最后的输出当中,当做流图的信号发射模块。
4.3 配置UHD Sink参数
GNU Radio支持变量模块,用户可以通过修改变量模块的值,来改变整个流图的值,而不用去依次修改,这是非常方便的。复制和粘贴你的samp_rate变量模块两次,分别来控制中心频率和增益。我们设置的中心频率和增益必须是你所使用的硬件设备支持的,不同的设备支持的频段可能是不同的。这里,我们设置中心频率为2.421GHz,增益设置为30dB,这是这个设备支持的发射增益的1/3。
现在,可以利用新的变量模块来调整UHD里面的参数了。打开UHD USRP Sink,你会看到一个参数列表,这里有许多的参数我们需要调整。向下滚动到列表的底部,相应地设置以下属性:
Samp Rate (Sps): samp_rate
Ch0: Center Freq (Hz: freq
Ch0: Gain (dB): gain
Antenna: "TX/RX"
Ch0: Bandwidth (Hz): samp_rate
需要特别注意的一点是任何大于1的值都会引起削波,这意味着振幅被“截断”在1。总的来说,必须设置幅度小于1。在这个例子中,我们将添加乘0.5乘法器的输出,以确保处于正确的幅度。现在,流图如下:
如果你执行你的图,你会看到通常的初始化和GUI启动,而不是一切都被模拟,你实际上是发送你的QPSK信号。如果我们看一下分析仪上的频谱,你应该能够清楚地看到你选择的频率的信号。如果你看不到,仔细检查一下你的参数,也试着修改下增益。
可以看到,跟我们设置是符合的,这说明我们已经成功的发射了QPSK信号。
4.4 创建一个FM接收机
在这一节中,我们将建立一个工作调频收音机接收器,你可以使用它收听你当地调频广播电台。
1. 创建一个软件频谱分析仪
一个基本的但是却非常有用的是你可以利用GNU Radio创建一个实时的频谱分析的fft,这是一个用软件实现的无线电频谱分析仪,利用它用户能够验证你的硬件是否工作正常,在这里,我们可以利用它来确定我们所在地区的广播电台的频段,以便我们可以调谐到相应的频段。
现在我们来创建一个流图。找到UHD USRP Source和QT GUI Sink模块。之前我们用固定的中心频率和增益,现在来把它变成实时可调的。找到QT GUI Range模块,添加两个这样的模块到流图中。设置相应的参数,这里使用的是USRP B200:
QT GUI Range 1:
ID: freqLabel:
freqDefault Value: 1e9
Start: 70e6
Stop: 6e9
Step: 10e6
QT GUI Range 2:
ID: gainLabel:
gainDefault Value: 0
Start: 0
Stop: 74
Step: 1
尝试修改你的samp_rate,会发现一些有意思的东西。这里设置的是32MSps.现在来设置UHD USRP Source的参数:
Samp Rate (Sps): samp_rate
Ch0: Center Freq (Hz): freq
Ch0: Gain (dB): gain
Ch0: Antenna: "TX/RX"
Ch0: Bandwidth (Hz): samp_rate
现在,我们的流图应该是这样的:
检查下你的设置是否正确。
2. 使用软件进行频谱分析
现在运行你的流图,你应该会看到你真实的信号。滑动相关按钮,注意图形的变化。默认的GNU Radio QT FFT sink内有许多有用的特性,例如均值和保峰值,尽量花一些时间去熟悉它们。
3. 创建FM广播接收
现在,有一个基本的接收器应用程序实时显示接收数据,让我们建立一个有用的应用程序!我们将添加更多的功能到流程,模块和数量如下:
1x Rational Resampler
1x WBFM Receiver
1x Audio Sink
2x Variable
我们数据的流向是:USRP Source->Rational Resampler->WBFM Receiver->Audio Sink. 按照这个顺序连接好这些模块,期间可能会有报错,现在我么就来修改相应的参数,来解决这些报错。
首先,添加两个variable blocks,设置相应的参数:
Variable:
ID: audio_interp
Value: 4
Variable:
ID: audio_rate
Value: 48e3
现在让我们把之前的sample rate改为250e3(250kHz).
Variable: samp_rate
ID: samp_rate
Value: 250e3
然后,我们配置其余的3个模块。
Audio Sink
这是一个比较简单的模块。它需要信号流的输入并通过扬声器播放它们。这个模块在GR的音频库初始化,这个音频库是包含在GNU Radio配置里面的。这里面有一些常见的速率设置,最常见的就是48kHz,现在我们使用的就是这个速率的。
设置Audio Sink参数:
Sample Rate: audio_rate
OK to Block: "No"
现在你只需要把你的速率设置为你的声卡支持的速率就可以了。
Rational Resampler
我们设置的USRP Source的速率为samp_rate,数值为250e3。设置的Audio Sink的速率为audio rate,数值为48e3。这里有一个问题,我们的源数据的采样率不是音频速率的整数倍:250000/48000=5.208。为了解决这个问题,我们必须进行重采样,这就需要用到Rational Resampler模块,将输入的速率转化为输出的速率。
Rational Resampler允许我们调整数据流的速度,通过插值或者抽取实现的。因为进来的数据的采样率为250k,我们就设定抽取的数值为250k,但是采样率是一个浮点型数据,所以设置抽取数值的时候注意需要将其转换为整型。然后,我们插值,所以再来设置插入的数据。由于WBFM进行了一个4次插值,所以我们可以利用audio_interp和audio_rate设置插入的速率。这样,设置的参数如下:
Type: Complex->Complex (Complex Taps)
Interpolation: audio_rate * audio_interp
Decimation: int(samp_rate)
其余的参数,默认就可以了。
WBFM Receiver
现在来配置最后的解调模块。这里仅仅需要设置两个参数:输入的速率以及抽取值。通过之前的例子,我们知道,输入的速率就是Rational Resampler的输入速率,抽取的就是audio_rate.
Quadrature Rate: audio_rate * audo_interp
Audio Decimation: audio_interp
注意这里的插入和抽取速率是可以自己设定,我们使用参数,是为了保证得到的结果一定是整数。
4. 调试FM广播
现在参数调整已经好了,应该看不到红色的报错信息了。整个流图如下:
运行流图,应该可以看到如下的界面,不同的版本可能会有所差异。改变freq,调谐到本地的FM频段,通过电脑的扬声器就可以听到广播了。
4.5 总结:
现在我们已经利用GNU Radio成功的搭建了无线电的收发平台。这些应用相对来说是比较简单的,他们利用GNU Radio提供的模块直接连接硬件组成无线系统。也说明了,将仿真带入真实的无线电系统在GNU Radio平台下是一件比较容易的事情。
参考链接:
1. http://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorials
2. http://www.ettus.com.cn/peixun/Default.aspx?pid=27