上期介绍了Plutosdr的基本知识,以及单个Plutosdr和两个plutosdr进行无线系统收发的区别,文章发出后受到了很多小伙伴的点赞和支持。
今天给大家进行代码实战的讲解,今天带来的是一个图片收发无线系统的搭建,通过Plutosdr进行图片的无线传输。废话不多说,下面上干货。
首先设计了一个无线图传系统的UI界面,UI界面的主要作用是清晰的展示系统的名称,以及一些想要调节的参数,根据图中的UI可以看到,要传输的文件是一个图片支持下拉框可选,另外接收端的增益、载波的频率也是可调的。UI中包含了一个“开始传输”按钮,再参数调节完毕之后,点击开始传输按钮之后,系统开始启动,完成数据的传输。点击代码中GUI.m该UI界面直接加载出来。
下面展示主程序的代码:
fprintf('正在准备传输,请稍后....\n');
deviceNameSDR = 'Pluto'; % Set SDR Device
Fs=500e3; %采样速率
zc1_len=500; %ZC序列长度
zc_seq1 = creat_cazac(zc1_len);
sdrTransmitter = sdrtx(deviceNameSDR); % Transmitter properties
sdrTransmitter.RadioID = 'usb:0';
sdrTransmitter.BasebandSampleRate = Fs;
sdrTransmitter.CenterFrequency = sim_options.carrier*1e9; % Channel 5
sdrTransmitter.ShowAdvancedProperties = true;
sdrTransmitter.Gain = 0;
sdrReceiver = sdrrx(deviceNameSDR);
sdrReceiver.RadioID = 'usb:0';
sdrReceiver.BasebandSampleRate = sdrTransmitter.BasebandSampleRate;
sdrReceiver.CenterFrequency = sdrTransmitter.CenterFrequency;
sdrReceiver.GainSource = 'Manual';
sdrReceiver.Gain = sim_options.gain;
sdrReceiver.OutputDataType = 'double';
sdrReceiver.SamplesPerFrame =200000;
首先是基本的参数配置,设置收发两端的Pluto的基本参数,需要设置发送端和接收端的设备名称,载波的中心频率无需设置可以从UI界面直接读取,发送端的增益设置成固定增益,接收端的增益读取UI界面设置的大小输出类型则选择固定的double类型,Frame的采样点数则需要根据自己的系统进行调整。
发送端程序:
%数据比特的生成
temp_bits=tx_bits((1:tx_len)+(nn-1)*tx_len);
%QPSK调制
mod_syms = tx_modulate(temp_bits);
%脉冲成型滤波
mod_syms1=usercos(mod_syms,8,21);
symbol_len=length(mod_syms1);
%添加前导序列
signal = [zc_seq1 zc_seq1 mod_syms1];%
首先,取出加载图片的比特数据,进行QPSK调制,这里只是选择QPSK调制方式作为例程讲解,也可以选择其他高阶调制方式进行实验,博主尝试过单个Pluto通信可以支持到128QAM调制,还可以在UI前端界面进行调制方式的配置,可以做成可选的方式,这里就不进行过多的介绍。
调制后的信号变成了一个复数信号,对于QPSK信号,其相位的变化代表了信息比特数据。
调制后的信号经过脉冲成型滤波器,这里采用根升余弦滤波器,经过根升余弦滤波器后的信号能够减少符号间干扰,成型滤波器的时域波形图如下:
经过成型滤波器后的信号添加前导序列,这里前导序列采用的恒幅零自相关序列,该序列具有很好的自相关特性和互相关特性。这里补充说明一下,为什么需要前导序列,无线信号在接收端进行AD采样转化为数字信号后,信号的起始位置接收端并不知道。接收端并不能区分噪声和信号,所以如何确定信号的起始位置成为了关键,该序列由于具有很好的自相关特性,所以很适合用来进行数据帧的起始位置查找。将加入前导序列的信号进行发送,可以得到发送后的信号为:
信号发送出去后,需要在接收端进行信号处理,接收端的程序:
data=sdrReceiver();
rx_signal=data;
%功率归一化
rx_signal=rx_s./sqrt(mean(abs(rx_s).^2));
%信号同步
data1=sync_signal(rx_signal,search_len,zc_seq1,zc1_len,thread,symbol_len);
%频率偏移和估计
rx_equ=freq_equ(data1,zc1_len,Fs);
rx_data_pre=usercos_de(rx_equ(2*length(zc_seq1)+1:end),8,21);
%载波同步
rx_data_pre=carrier_sync(rx_data_pre);
%QPSK解调
rx_demodulate_bit = rx_demodulate(rx_data_pre);
de_bits=rx_demodulate_bit(1:tx_len);
得到模块的接收信号后进行信号功率的归一化,然后根据信号添加的前导序列进行信号的同步,即根据信号的前导序列找到信号的起始位置,将有效的信号提取出来。接收端的时域信号如下:
通过前导序列同步找到信号的起始点:
如上图所示,在接收端同步后得到的一个较大的相关值,该最大点对应的就是信号的起始点,找到信号的有效起始点后,进行频偏的估计和补偿,然后接收端进行匹配滤波得到滤波后的信号,对滤波后的信号进行载波同步,得到接收端的QPSK信号:
解调后的QPSK信号得到了接收的信号,然后对接收端的信号进行还原得到接收端的图片:
最后程序运行完毕出弹出一个图片显示的窗口,来展示程序运行过程中生成的图片:
图片中每个按钮都对应展示了运行过程中生成的波形图,点击按钮对应的信号波形图即可展示。通过这些过程的图片能够帮助你更好的理解程序的过程。 同时,信号传输完成之后也会弹出传输成功窗口:
这个程序的整个流程至此也就结束了,整个程序的流程介绍也基本结束,我整理了这个程序的整个工程文件和相关的流程说明都放在了下面的链接中,欢迎大家进行下载尝试运行,运行过程中对程序原理或者流程有什么问题欢迎私信我讨论。原创不易,还望大家尊重知识产权,侵权必究!!!
源码链接:
通过网盘分享的文件:链接: https://pan.baidu.com/s/1ej2QPOfbFo1ct9iD1gDPNw?pwd=jv5h 提取码: jv5h
https://m.tb.cn/h.6i0xQgP?tk=sDfwVY09KK1https://m.tb.cn/h.6i0xQgP?tk=sDfwVY09KK1
本期就到这里,大家有任何问题欢迎进行讨论,下期再见!!!!
下一篇: