自适应滤波器

这个东西是2017年全国电子设计大赛E题,题目要求如下:
自适应滤波器_第1张图片
自适应滤波器_第2张图片
自适应滤波器_第3张图片
  题目要求做一个自适应滤波器,开始看了一个星期的自适应滤波器,,无奈有点晕头晕脑,,没看太明白,仿真结果也不太理想,于是决定用模拟方案(最后还是用数字方案完整的实现了所有功能),输入为混有噪声信号的D与纯噪声信号B,输出为有用信号,其中D中的噪声与纯噪声信号B频谱相同,噪声信号被限定为正弦波、三角波、或者方波,但相位差未知,因为过了一个移相器,所以单纯用减法器减掉噪声是不行的,既然相位差未知,所以我们第一个想法是测出相位差,于是有了下面的方案:
自适应滤波器_第4张图片 图1:利用乘法器检测相位

  信号D中除了噪声,还包含有用信号,所以通过比较器然后测相位差是行不通的,所以我们打算用模拟乘法器,将信号B不断移相得到信号F,然后与D相乘,再过低通滤波器(同频信号相乘会得到直流和和频,不同频信号相乘得到差频和和频,低通是为了滤掉除直流以外的信号),当低通滤波器输出直流电压最大时,此时F的相位与D中噪声信号相位相同,从而根据移相器移相的角度得到相位差,然后用另外一路移相器移到该相位得到信号G,再用减法器相减,得到有用信号E。
理想很丰满,现实确总让人失望,这个方案里有几个不好弄的问题。

  1. 第一个遇到的就是移相器怎么弄。。自适应滤波器里面要有两个程控移相器,开始打算是用DAC8811(乘法、电流输出型DAC)做程控电阻,然后用模电书里面的全通滤波器做移相,结果发现那个全通滤波器控制相移的电阻两端没一个是虚地或者地,然后DAC8811就弄不了了,遂作罢。然后由想着用程控电位器,于是赶紧申请了几颗TI的程控电位器,,结果申请回来正打算开始做,发现程控电位器的带宽太低了,不够用,并且TI也没有合适的程控电位计,,遂作罢,最后用FPGA弄了个FIFO,加上A/D、D/A才弄好。
  2. 然后就是利用乘法器检测相位这个方案也不太好做精确,当噪声是正弦波,并且相位差很小的时候,测相精度就很差,实际做出来只能精确到±5°以内。。
  3. 还有减法器,,实测即使相位已知,当噪声信号是正弦波还好,但如果是方波,,相减后会有很大的毛刺,,
  4. 另外就是这个方案从一开始就由一个问题,,题目要求系统反应时间小于1秒,但相位从0-180°扫描过去,几乎不可能在1秒内完成,,经过不断优化,,1°的步进时,最快要10秒左右才能扫一次。

   对于问题1,FPGA+FIFO+A/D+D/A解决了

   对于问题2,我们换了种思路,如图2,我们先对噪声信号B移相,得到信号F,然后先用信号D减去信号F,由于噪声信号频率可以测出来,我们用FPGA产生两路与由于信号噪声同频,但两路信号间相位差为90°的正交方波信号,做一个锁定放大器,检测信号相减后剩余的噪声信号,当剩余噪声信号最小时,记录相位,然后控制另外一路移相器以到那个相位与信号D相减得到有用信号E,这样做之后效果好很多,相位误差±1°左右,噪声信号为正弦波和三角波时,基本可以满足题目要求,但方波还是不行。。

  对于问题3,可能把运放换成高速运放,或者限制输入信号带宽应该会好一点吧,由于时间有限和有了更好的方案,就没管这个问题了。。

  对于问题4,,放弃了这个要求了,,不过我们又做了个数字方案,这个要求也满足了。

自适应滤波器_第5张图片
图2:利用锁定放大器检测相位

自适应滤波器_第6张图片
图3:哗啦啦的线。。大三的阴影


图4:最后滤出来的波形,忘记拍滤之前的了,,,大致就是两个不同频率、1Vpp的正弦波叠加。

  做了两个多星期,,总算出了点结果,,好在还没有结束

  在书上看到了自适应陷波器,相当于一个窄带陷波器,可以做成多路构成多路窄带滤波器,,然后matlab仿真,,效果不错,C语言仿真,效果不过,Verilog写完modelsim仿真,效果不错,,signTab仿真,,效果不错,,然后上A/D,D/A,完美。。。
迭代公式很简单,,怎么推到出来的,,迷迷糊糊看了个大概,,,这里面印象最深的是第一次在FPGA里面用到了流水线,,以前一直是状态机模拟C语言的,,这次用流水线大大提高了时间效率,一环扣一环,,一点多余都没有。
最后系统大致结构为:首先FPGA测量噪声频率,然后单片机算出噪声基波及各次谐波所对应的频率控制字,然后写入到FPGA,控制FPGA内部DDS产生不同频率的参考信号,从而滤除掉噪声的基波和各次谐波,,本来打算再做一路AD采样,通过频谱检测当前是否为正弦波,如果是正弦波,就只抑制基波,避免伤及无辜,但由于时间有限,,还是没有做。。
自适应滤波器_第7张图片
图5:自适应陷波器结果图。。网上截图的,,这里只有一路陷波,实际上我们做了16路。

自适应滤波器_第8张图片
图6:状态机流水
自适应滤波器_第9张图片
图7:流水线代码截图,一环扣一环,,没有任何多余。。。
自适应滤波器_第10张图片图8:matlab仿真

自适应滤波器_第11张图片
图9:modelsim仿真

自适应滤波器_第12张图片
图10:滤出来干干净净的波形

  最后实测的图忘记拍了,,效果不错,,完全满足题目所有要求。

  这个题做了快一个月,做了一个模拟方案,一个数字方案,也算是收获不少吧。

  最后附matlab仿真代码:

clear;clc;
close all;
%采样信息
fs=1e6;
t=0:1/fs:1;
%噪声信息
noiseInfo=[
    10.01e3 pi/2;
    39.99e3 pi/2;
    99.99e3 pi/2;
    69.99e3 pi/2;
    29.99e3 pi/2;
];
%有用信号信息
sourceInfo=[
    10e3 0;
    30e3 0;
];noise=zeros(16,length(t));
source=zeros(16,length(t));
ref_s=zeros(16,length(t));
ref_c=zeros(16,length(t));dn=zeros(1,length(t));
wn=zeros(16,2);
en=zeros(1,length(t));%生成噪声
for i=1:1:length(noiseInfo(1:end,1))
    noise(i,:)=sin(2*pi*t*noiseInfo(i,1)+noiseInfo(i,2))*10;
    ref_s(i,:)=sin(2*pi*t*(noiseInfo(i,1)+0.000));
    ref_c(i,:)=cos(2*pi*t*(noiseInfo(i,1)+0.000));
end
%生成有用信号
for i=1:1:length(sourceInfo(1:end,1))
    source(i,:)=sin(2*pi*t*sourceInfo(i,1)+sourceInfo(i,2))*10;
end
%将噪声累加
for i=1:1:length(noiseInfo(1:end,1))
    dn=dn+noise(i,:);
end
%将有用信号累加
for i=1:1:length(sourceInfo(1:end,1))
    dn=dn+source(i,:);
end
%滤波
for i=1:1:length(t)
    sum=0;
    for j=1:1:length(noiseInfo(1:end,1))
        sum=sum+wn(j,1)*ref_s(j,i)+wn(j,2)*ref_c(j,i);
    end
    en(i)=dn(i)-sum;
    for j=1:1:length(noiseInfo(1:end,1))
        wn(j,1)=wn(j,1)+2*0.00002*en(i)*ref_s(j,i);
        wn(j,2)=wn(j,2)+2*0.00002*en(i)*ref_c(j,i);
    end
end
figure;
plot(dn);
figure;
plot(en);
figure;
plot(abs(fft(dn(6e5:1e6))));
figure;
plot(abs(fft(en(6e5:1e6))));

你可能感兴趣的:(项目训练)