原创 数字滤波器matlab辅助设计

2022-6-5 07:38 2671 18 11 分类: MCU/ 嵌入式 文集: matlab

仍然使用FDATOOL设计滤波器,当前设计一个数字带通滤波器。至于用的是冲击响应不变法,还是其它的方法。暂时不考虑。FIR 需要的阶数太多,也不考虑。使用IIR滤波,线性相位就不要想了。可以选巴特沃兹(最大平整度),或切比雪夫(最大陡降特性。)发现在相同的性能下切比雪夫需要的阶数少。

生成的传递函数是按照多个二阶单元级联。系统提供 SOSSecond Order Section)也可以称为“救命”矩阵。其思路是将高阶传递函数分解为多个稳定的二阶函数级联,保持系统稳定。因为使用的是IIR (无限冲击响应)构成,注定其是非线性相位。会导致滤波后的信号波形畸变。导出滤波器参数文件.

  1. % Generated by MATLAB(R) 8.4 and the Signal Processing Toolbox 6.22.
  2. % Generated on: 04-Jun-2022 20:49:14
  3. % Coefficient Format: Decimal
  4. % Discrete-Time IIR Filter (real)
  5. % -------------------------------
  6. % Filter Structure : Direct-Form II, Second-Order Sections
  7. % Number of Sections : 2
  8. % Stable : Yes
  9. % Linear Phase : No
  10. SOS Matrix:
  11. 1 0 -1 1 -1.9528158412163148 0.95399450820943588
  12. 1 0 -1 1 -0.92310027138083539 0.34076352170725532
  13. Scale Values:
  14. 0.31856548677578983
  15. 0.31856548677578983

每个SOS参数可以使用直接II型,实现如下:

编写一段代码测试一下。

  1. clear
  2. close all
  3. Fs = 30000; % Sampling Frequency
  4. % 20-500 30000sps butter 4 order
  5. sec = 2;
  6. SOS = [1 0 -1 1 -1.9941159332576488 0.99413480892694572;1 0 -1 1 -1.8630805194585167 0.87259004111123051];
  7. G = [0.048551094455762382 0.048551094455762382 1];
  8. len = Fs/10; % Êý¾Ý³¤¶ÈΪ 100mS
  9. t = 1:len;
  10. n = 300*sin(2*pi*15*t/Fs + pi/6); % 50hz noise
  11. s = 3000*sin(2*pi*200*t/Fs + pi/5); % original square wave signal
  12. ng = 500*randn(1,len);
  13. x = s + n + + ng + 1000;
  14. fftx = abs(fft(x,len));
  15. f = 0:Fs/len:(len-1)*(Fs/len);
  16. figure(1)
  17. plot(f(1:len/20),fftx(1:len/20))
  18. title('sinc fuction spectrum')
  19. w = zeros(sec,3);
  20. ym = zeros(1,sec+1);
  21. for i = 1:len
  22. ym(1) = x(i);
  23. for k = 1:sec
  24. w(k,1) = ym(k) * G(k) - w(k,2) * SOS(k,5) - w(k,3) * SOS(k,6)
  25. ym(k+1) = w(k,1)*SOS(k,1)+w(k,2)*SOS(k,2)+w(k,3)*SOS(k,3);
  26. w(k,3) = w(k,2);
  27. w(k,2) = w(k,1);
  28. end
  29. y(i) = ym(sec+1)*G(sec+1);
  30. end
  31. figure(2)
  32. plot(t,s,'r',t,x,'c',t,y,'.b')
  33. legend('signal','org','bandpass');

待滤波信号的频谱特性

可以看到org 信号上有噪声,有直流偏置和低频交流干扰。经过带通滤波后,去除了直流,去除了噪声,基本还原原始信号signal。刚开始时并不稳定需要等一段时间才能达到稳定。

可见,此段代码可以将一个输入序列x 转换为一个输出序列 y,完成对x序列的滤波。 

按照生成的结构图,编写m文件的解释:

  1. sec = 2; % 定义级数
  2. SOS = [1 0 -1 1 -1.9941159332576488 0.99413480892694572;1 0 -1 1 -1.8630805194585167 0.87259004111123051];
  3. G = [0.048551094455762382 0.048551094455762382 1];
  4. w = zeros(sec,3); %中间w 变量
  5. ym = zeros(1,sec+1); %每一级的输出
  6. for i = 1:len % 对每一个输入 x
  7. ym(1) = x(i);
  8. for k = 1:sec % 分极计算
  9. w(k,1) = ym(k) * G(k) - w(k,2) * SOS(k,5) - w(k,3) * SOS(k,6)
  10. ym(k+1) = w(k,1)*SOS(k,1)+w(k,2)*SOS(k,2)+w(k,3)*SOS(k,3);
  11. w(k,3) = w(k,2);
  12. w(k,2) = w(k,1);
  13. end
  14. y(i) = ym(sec+1)*G(sec+1); %得到输出
  15. end
  16. 翻译成C语言
  17. // 20-500hz butterworth 4 order 2 section 3750sps
  18. #define SEC 2
  19. const float SOS1[SEC][6] = {
  20. {1, 0, -1, 1, -1.9528158412163148, 0.95399450820943588},
  21. {1, 0, -1, 1, -0.92310027138083539, 0.34076352170725532}};
  22. const float G1[SEC+1] = {0.31856548677578983,0.31856548677578983,1};
  23. float BandPassFilter(const float SOS[SEC][6],const float G[SEC+1],float x){
  24. static float w[SEC][6];
  25. uint8_t k;
  26. static float ym[SEC+1];
  27. ym[0] = x;
  28. for(k = 0;k < SEC;k++){
  29. w[k][0] = ym[k] * G[k] - w[k][1]*SOS[k][4] - w[k][2]*SOS[k][5];
  30. ym[k+1] = w[k][0]*SOS[k][0]+w[k][1]*SOS[k][1]+w[k][2]*SOS[k][2];
  31. w[k][2] = w[k][1];
  32. w[k][1] = w[k][0];
  33. }
  34. return ym[SEC]*G[SEC];
  35. }

每采集到一个数据时,以输入数据作为参数,调用BandPassFilter(),得到一个滤波输出。相当于实时处理。

经过滤波后的信号

经过滤波+陷波后的信号




作者: southcreek, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-408807.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /2 下一条