幅度调制¶
幅度调制,简称调幅,也就是Amplitude-shift keying (ASK),是通过为信号设置不同的幅度来实现调制的调制方法。最简单的幅度调制是ON-OFF Keying (OOK),它是大家经常听到的一种数据调制和发送的形式,例如RFID的数据调制方法就是OOK。简单来说,OOK使用固定频率的信号代表“1”,没有信号代表“0”。这种用来表示一个二进制数的信号我们称为**码元**,每种调制方式都有自己设定的一组码元,其中的每个码元都是一段互不相同的信号,代表不同的二进制数。在OOK中,共有2种码元,每个码元代表1位二进制数。在其他的调制方式中,码元也可以代表多位二进制数。OOK的两种码元的长度相同。下面是使用OOK调制的示意图:
从图上可以看出来,发送数据“1”的时候是有信号的,发送数据“0”的时候是没有信号的,这样在接收端可以通过收到的信号来判断数据“0”和“1”。
思考:在接收端如何判断数据“0”和“1”。
如果要进一步提高幅度调制的效率,可以通过设置不同的振幅级别来实现,使得每个码元代表更多位数的二进制数,从而携带的信息更多:
采用不同的幅度后,会带来其他的影响。在幅度调制中,需要考虑的问题是要使得不同码元的幅度有足够大的区分度,否则解码时无法区分不同的幅度,在有噪声的情况下,不同的信号幅度可能变得更加难以区分。因此理论上来说,针对不同的噪声,我们应该设置不同的幅度。这也是为什么在不同的信噪比下有不同的最优发送速率。另外一点需要考虑的就是信道的特性。信道是否稳定,如果信道状态发生变化,那么很可能使得本来幅度较高的信号在减弱,导致解码错误。
声音信道就是一种比较容易变化的信道,周围反射环境的变化会使得信道出现明显变化。这种情况下可以通过缩短数据包的长度来折中处理。当数据包的长度足够短的情况下,在这个数据包发送的过程中,声音信道的变化是比较小的。
思考: 信号经过信道传输之后,会发生强度的衰减。当接收端接收到信号时,信号幅度的绝对值已经发生了很大的改变。如何才能保证正确解码出信号中的数据?
使用声波信号实现OOK¶
先来看发送端的代码实现。前面我们展示过了如何生成、发送和接收声波信号,现在我们来看一下如何利用声波信号来传输数据。在我们的这个教程中,数据传输基本都以声波为基础,而不是无线电磁波信号,因为声波信号处理起来更加直观,而且利用大家自己的手头设备例如手机等就可以。
首先我们生成两个symbol,分别编码1和0。
% symbol 1
fm=100; %信号频率
fs=fm*100; %采样频率
Am=1;
symbol_len=512; %一个symbol的长度
t=(0:1/fs:(symbol_len-1)/fs);
% symbol 1
smb1=Am*cos(2*pi*fm*t);
% symbol 0
smb0 = zeros(1, symbol_len);
接下来我们根据OOK编码的方法生成基带信号(一般这个信号的频率较低),基带信号这个名词大家在看论文和看其他专业技术书籍的时候都经常会听到。一般来说基带信号是针对没有上变频的信号的,通俗一点来理解,目前为止大家看到的编码解码的方法都还是在基带上,还没有上到载波上。 在我们学习调制解调过程的时候,我们主要先理解基带调制就可以了,我们看到的大部分论文也主要是在讲基带调制的过程,上载波的过程是后续的步骤。所以大家可能会听到基带芯片,那也就是在做这个事情,主要做在上载波之前数据需要编码调制的事情。 在真正发送的时候,信号会调制到载波上,这个时候信号就不在是在基带上的信号了。
datas = [0, 1, 0, 0, 1, 0, 1, 1];
sig = [];
for data = datas
if data == 0
sig = [sig, smb0];
else
sig = [sig, smb1];
end
end
将这个基带信号加到载波上得到频带信号(频率很高),就可以发送出去了。这一步是上载波的过程。
思考:理论上来说,有了前面的基带调制,信号中就已经有数据了,为什么还需要上载波?
% 载波
fc=1000; %载波频率
t = 0:1/fs:(length(sig)-1)/fs;
carrier_wave = cos(2*pi*fc*t);
% 将基带信号加到载波上
sig_carrier=sig.*carrier_wave;
信号由发送端经过信道到达接收端。比如手机播放的声音,经过空气传输,墙面反射等等,最终到达接收端,信号从发送端到达接收端经过的整个过程都被抽象为信道。这里我们使用Matlab来仿真信号通过信道的过程,我们通常给信号加上白噪声来模拟。(注意,这里还没有添加多径等其他影响)
%% 信道传输 加入噪声
sig_carrier = awgn(sig_carrier, 5);
注: 可在Matlab下面命令行中输入
help awgn
查看awgn
函数使用说明,其他函数同理。
接下来是接收端的代码实现。 为了解码这个数据,首先请注意,接收到的数据是上载波后的信号,通常这个信号的频率是非常高的(例如WiFi下是2.4GHz),我们一般不直接解调这么高频率的信号。 我们的第一步是先将信号下变频,即先将信号转移到基带上来。
思考:如何将载波上的信号转移到基带上来?
为了将载波上的信号转移下来,首先将整个信号乘上同频同相的参考信号,然后逐symbol的经过低通滤波(滤波的代码见实验附件)即可恢复出基带信号。
sig_rec=sig_carrier.*carrier_wave; %乘以载波
% 低通滤波
base_sig = [];
for i = 1:symbol_len:length(sig_rec)
smb = sig_rec(i:i+symbol_len-1);
%低通滤掉高频
sig_baseband = BPassFilter(smb, 100, 10, fs);
base_sig = [base_sig, sig_baseband];
end
最后通过设定一个阈值,根据幅值大小来解出symbol。
decode_datas = [];
thresh = 1;
for i = 1:symbol_len:length(base_sig)
smb = base_sig(i:i+symbol_len-1);
A = sum(abs(smb));
if A > thresh
decode_datas = [decode_datas, 1];
else
decode_datas = [decode_datas, 0];
end
end