Matlab中fdatool结合STM32F4设计滤波器

数字滤波器的原理

1.从功能上分;低通、带通、高通、带阻。滤波器口诀:低通滤高频;高通滤低频;带通滤两边;带阻阻中间;

2.从实现方法上分:FIR、IIR

3.从设计方法上来分:Chebyshev(切比雪夫),Butterworth(巴特沃斯)

4.从处理信号分:经典滤波器、现代滤波器

经典滤波器从功能上分又可分为:

低通滤波器(LPAF/LPDF):Low pass analog filter

带通滤波器(BPAF/BPDF):Bandpass analog filter

高通滤波器(HPAF/HPDF):High pass analog filter

带阻滤波器(BSAF/BSDF):Bandstop analog filter

IIR滤波器和FIR滤波器

数字信号处理里面的滤波器分两种:一种是IIR滤波器,另一种是FIR滤波器,本质区别就是IIR滤波器的当前输出与以前的输出和输入有关,FIR滤波器只与输入有关,看一下差分方程就一目了然了。

更多对比参考:

细说IIR滤波器和FIR滤波器的区别_iir和fir的区别_Gordennizaicunzai的博客-CSDN博客

Matlab用指令实现滤波器

以下以IIR巴特沃斯带通滤波器设计为例。

fs=1000; %设置采样频率 1k

N=1024; %采样点数

n=0:N-1;

t=0:1/fs:1-1/fs; %时间序列

f=n*fs/N; %频率序列

x1=sin(2*pi*50*t); %噪声

x2=sin(2*pi*200*t); %信号

x=x1+x2; %信号混合

subplot(311);

plot(t,x); %绘制原始信号

xlabel('时间');

ylabel('幅值');

title('原始信号');

subplot(312);

y=fft(x,N); %绘制原始信号的幅频响应

plot(f,abs(y));

xlabel('频率/Hz');

ylabel('振幅');

title('原始信号 FFT');

subplot(313);

Wn=[125*2 300*2]/fs; %设置通带 125Hz 到 300Hz

[b,a]=butter(1,Wn); %注意第一个参数虽然是 1,但生成的却是 2 阶 IIR 滤波器系数

y2=filtfilt(b,a,x); %计算滤波后的波形 y2

y3=fft(y2,N); %滤波后波形的幅频响应

plot(f,abs(y3));

xlabel('频率/Hz');

ylabel('振幅');

title('滤波后信号 FFT');

Fdatool工具的使用

如果要对数据进行滤波,可以使用matlab提供的工具fdatool来进行滤波器的设计,我们可以设计出一系列的滤波器,并且可以实时看到滤波器的效果图,滤波器设计好之后,我们还可以对目标数据进行滤波,然后根据滤波的效果去调整滤波器的参数。

我们可以在matlab的命令行处输入fdatool命令来调出fdatool工具。

该界面内容较多,我们这里仅对较常使用的地方进行说明。

响应类型和设计方式

这里是滤波器的选择,从上到下依次是:

低通、高通、带通、带阻,接着是其他的一些特殊滤波器,这里面有个Notching陷波滤波器,常常用来滤除特定频率的信号比如工频干扰及其谐波。

再下方的就是IIR和FIR滤波器选择,这个根据需要去选择即可,具体滤波器的应用场景可以查阅相关资料。IIR里常用的就是巴特沃斯滤波器,FIR里常用的就是加窗方式window

后面还有一些参数,我们就分别在滤波器的类型设计中去讲解吧。

这里先说一下几个问题:

第一个就是,FIR的阶数和IIR的阶数选择,基于FIR和IIR滤波器的特点,同样的效果,FIR需要比IIR有更多的阶数。通常,FIR的阶数都是几十几十的,甚至几百的,比如50阶、60阶、100阶、150阶等等,具体根据滤波效果来设定,总之,不能小,一小就效果差;相反,IIR设定的阶数不能大,一般不会超过6阶,常用的就是2阶或者4阶,如果大了,反而会溢出产生漂移等问题,初学者很容易看到IIR低阶效果不好,就加大阶数,这会适得其反。

第二个就是,我们可以通过参数图看下各参数是啥意思,通过幅频图直观地看到滤波器的效果,就是这个:

参数图

幅频图

可以直观地看到滤波器的效果。

接下来,依次介绍几个有代表性的滤波器,其他滤波器都是类似的。

IIR巴特沃斯低通滤波器

都比较好理解。

这里展示了当前滤波器的信息

有个地方需要注意,那就是Minimum order,虽然说是最小的阶数,但选中之后其实阶数很大,不知道是不是bug。

一般,我们手动指定阶数即可。

FIR加窗window低通滤波器

高通滤波器同理,不再赘述。

IIR巴特沃斯带通滤波器

带阻滤波器同理

单频率陷波滤波器

多频率陷波滤波器

这种滤波器被称作梳状滤波器,像一把梳子,可以滤去某个频率及其谐波成分,也就是某频率的所有整数倍频率,最常见的就是滤掉50Hz的工频干扰及其谐波。

这里需要注意的是,这里的阶数不能随便设,是有固定的数值的,=Fs/目标频率,比如,要滤掉50Hz及其谐波部分,采样率2000,那么这里的阶数就要填2000/50=40。

其他滤波器的参数补充

另外,还有一些其他滤波器,可能有一些不一样的参数,比如FIR默认的低通滤波器,截止频率填入时就不只是填入截止频率,而是填入一个范围

这里表示从Fpass开始截止,然后到Fstop时衰减到最低,看上面的幅频图就很明白了。

Wpass/Wstop/Apass/Astop这些意思都是差不多,分别调节衰减开始处和衰减结束出的频率范围精度,比如目标频率是50,如果这些值比较小,可能从49.5才开始衰减,但是值太大了,可能从45就开始衰减,这样的话,本来只想滤掉50Hz的频率,结果把45—55的频率都滤掉了。

再通俗点,就跟带阻滤波器两侧的范围误差差不多。

以上,就是设计滤波器时需要知道的一些参数设置。

这里总结一下,如何调节滤波器的效果?一般可以通过调节以下这些参数达到最适合的效果:

1、调节阶数,fir增大阶数,iir适当增加阶数;

2、陷波滤波器时提高品质;

3、调节Wpass/Wstop/Apass/Astop这些参数;

4、如果以上调节没什么改进的话,那就直接更换滤波器类型,比如,如果用IIR滤波器做带通,怎么调节效果都不好,那就直接换成FIR滤波器,再比如,如果陷波滤波器效果不好的话,就直接换成带阻滤波器。

……

总之,虽然需要一些经验,但也需要多多调试。

注意:设计滤波器时,所使用的阶数 n 应为偶数。

matlab验证滤波器效果

我们使用fdatool设置好滤波器参数之后,点击最下方的按钮Design Filter

此时,滤波器就设计好了。

接着,可以将设计好的滤波器导出成一个matlab对象。

fdatool工具界面上面,点击File——Export

这里的意思就是,将当前滤波器导出到matlab的变量空间Workspace,导出为对象,并且命名为Hd_bp,如果变量名已存在则覆盖,然后确定导出。

此时,在matlab的工作空间就会出现这个滤波器对象

接下来,我们准备好原始数据,然后对原始数据进行滤波

Fs = 2000;
%带通滤波器,Fir滤波
sig1 = filter(Hd_bp, VarName1);
%带阻滤波器,iir滤波
sig2 = filter(Hd_bs_50, sig1);
sig3 = filter(Hd_bs_100, sig2);
sig4 = filter(Hd_bs_150, sig3);%奇次谐波
sig5 = filter(Hd_bs_200, sig4);
sig6 = filter(Hd_bs_250, sig5);%奇次谐波
sig7 = filter(Hd_bs_300, sig6);
sig8 = filter(Hd_bs_350, sig7);%奇次谐波
sig9 = filter(Hd_bs_400, sig8);
sig10 = filter(Hd_bs_450, sig9);%奇次谐波
sig11 = filter(Hd_bs_500, sig10);
%频谱图
Y = fft(sig11);
L = length(Y);
P2 = abs(Y/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(L/2))/L;
plot(f,P1);
%axis([0,Fs/2,0,2000]);
title('frequency-domain');
xlabel('f(Hz)');
ylabel('频率成分的幅值');

以上代码中,filter就是滤波函数,这里面放入两个参数,第一个就是刚才设计并导出的滤波器对象,第二个就是原始数据。

我们可以对滤波前后的数据分别绘制幅频图,以此来验证滤波效果。

上面的代码做了20~500的带通和工频干扰的带阻滤波,效果如下:

效果还是可以的。

STM32F4实现滤波器

我们在matlab设计好滤波器之后,如果把这个滤波器用到STM32里呢?因为F4有FPU,所以最好在F4上使用,要不速度会是个大问题。

其实也比较简单

如果是FIR滤波器,在滤波器设计好之后,导出头文件

Targets——Generate C header

生成并保存后,我们可以到目标路径去找到头文件并打开查看

这里面关键的就是个系数,系数的个数是设定的阶数+1,这是算法要求,不用管太多,直接拿到C里面使用即可。

如果是IIR滤波器

默认生成的IIR滤波器是II型

导出之前,我们先将滤波器转换成直接1型

Edit——Convert Struct

选择第一项并确定

然后File——Export导出为系数

系数中的关键信息就是系数和缩放系数

因为是4阶,由两个二阶滤波器组成,所以二阶滤波器系数有两组。

这里,系数分别为b0 b1 b2 a0 a1 a2,其中a0这个系数是固定的,所以不必使用。

同时,要注意的是,在STM32F4中用DSP调用时,需要将每组的a1和a2取反,即正的改成负的,负的改成正的。

这个看公式就知道了。

比如 matlab 就是使用上面的公式实现的,所以在使用 fdatool 工具箱生成的 a 系数需要取反才能用于直接 I 型 IIR 滤波器的函数中。
其实,各类滤波器本质上就是计算公式不同,各有各的系数,各有各的算法。
我们得到系数之后,在F4中初始化,写滤波函数,然后调用即可。
附上代码:
#include "IIR.h"
#include "arm_const_structs.h"
#include "stm32f4xx.h"#define NUM_PER_CALL                1               //调用一次滤波函数所处理的采样点个数//FIR带通滤波器
#define FIR_EFFICIENT_NUM           151             //fir滤波器系数个数arm_fir_instance_f32 S_BP;                          //fir滤波器实例
static float32_t firStateF32[NUM_PER_CALL + FIR_EFFICIENT_NUM - 1]; //FIR状态缓存,大小FIR_EFFICIENT_NUM + NUM_PER_CALL - 1
const float32_t firCoeffs32BP[FIR_EFFICIENT_NUM] =  //fir滤波器系数数组
{0,6.783468507e-07,5.500670341e-06,6.206928447e-06,-3.594570046e-07,1.734129728e-05,5.174893886e-05,3.377356188e-05,-6.174600458e-06,5.468466406e-05,0.0001484536479,7.860602636e-05,-3.384135198e-05,0.0001032602231,0.0002951264905,0.0001253946684,-0.0001162498447,0.0001406262745,0.0004820130707,0.0001433174912,-0.0003082125622,0.0001265054452,0.0006859251298,8.190450171e-05,-0.0006903739995,-5.077828102e-19,0.0008687517256,-0.0001297538547,-0.001369225443,-0.0003186257964,0.000981297344,-0.000578189909, -0.00247148145,-0.0009198086918,0.0009743300034,-0.001354034874,-0.004132688046,-0.001889958396,0.0008173419628, -0.00253453129,-0.006482330617,-0.003291910049,0.0005241415929,-0.004162855446,-0.009630653076,-0.005144232418,0.0001840474579,-0.006228647195, -0.01366603095, -0.00740425894,-1.092867096e-18,-0.008654787205,  -0.0186777208,-0.009959736839,0.0003446365299,-0.01129483711, -0.02483416907, -0.01263269503,  0.00187640998,   -0.013943634,-0.03260042891, -0.01519669406, 0.005871396046, -0.01636073925, -0.04341268912,-0.01740563288,  0.01548426691, -0.01830341667, -0.06258355826, -0.01902942732,0.04320411757, -0.01956332289,  -0.1251707077, -0.01988991722,   0.2981061041,0.4799961746,   0.2981061041, -0.01988991722,  -0.1251707077, -0.01956332289,0.04320411757, -0.01902942732, -0.06258355826, -0.01830341667,  0.01548426691,-0.01740563288, -0.04341268912, -0.01636073925, 0.005871396046, -0.01519669406,-0.03260042891,   -0.013943634,  0.00187640998, -0.01263269503, -0.02483416907,-0.01129483711,0.0003446365299,-0.009959736839,  -0.0186777208,-0.008654787205,-1.092867096e-18, -0.00740425894, -0.01366603095,-0.006228647195,0.0001840474579,-0.005144232418,-0.009630653076,-0.004162855446,0.0005241415929,-0.003291910049,-0.006482330617, -0.00253453129,0.0008173419628,-0.001889958396,-0.004132688046,-0.001354034874,0.0009743300034,-0.0009198086918, -0.00247148145,-0.000578189909,0.000981297344,-0.0003186257964,-0.001369225443,-0.0001297538547,0.0008687517256,-5.077828102e-19,-0.0006903739995,8.190450171e-05,0.0006859251298,0.0001265054452,-0.0003082125622,0.0001433174912,0.0004820130707,0.0001406262745,-0.0001162498447,0.0001253946684,0.0002951264905,0.0001032602231,-3.384135198e-05,7.860602636e-05,0.0001484536479,5.468466406e-05,-6.174600458e-06,3.377356188e-05,5.174893886e-05,1.734129728e-05,-3.594570046e-07,6.206928447e-06,5.500670341e-06,6.783468507e-07,0
};//IIR带阻滤波器-50Hz
#define numStages_50Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_50Hz;
static float32_t IIRStateF32_50Hz[4*numStages_50Hz];
static float32_t ScaleValue_50Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数const float32_t IIRCoeffs32BP_50Hz[5*numStages_50Hz] =
{1,-1.9754644172762135,1,1.9596811054397389,-0.98620549853243988,1,-1.9754644172762135,1,1.9649189860762641,-0.98731438166310681
};//IIR带阻滤波器-100Hz
#define numStages_100Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_100Hz;
static float32_t IIRStateF32_100Hz[4*numStages_100Hz];
static float32_t ScaleValue_100Hz = 0.99335783101529107 * 0.99335783101529107;//放缩系数const float32_t IIRCoeffs32BP_100Hz[5*numStages_100Hz] =
{1,-1.9021975146812826,1,1.8851730633310202,-0.98648991967768052,1,-1.9021975146812826,1,1.8938697151225545,-0.98702972281202106
};//IIR带阻滤波器-150Hz
#define numStages_150Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_150Hz;
static float32_t IIRStateF32_150Hz[4*numStages_150Hz];
static float32_t ScaleValue_150Hz = 0.99335783101529107 * 0.99335783101529107;//放缩系数const float32_t IIRCoeffs32BP_150Hz[5*numStages_150Hz] =
{1,-1.782092196243289,1,1.7640519295652939,-0.98658772855718069,1,-1.782092196243289,1,1.7763809606964005,-0.98693187011384975
};//IIR带阻滤波器-200Hz
#define numStages_200Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_200Hz;
static float32_t IIRStateF32_200Hz[4*numStages_200Hz];
static float32_t ScaleValue_200Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数const float32_t IIRCoeffs32BP_200Hz[5*numStages_200Hz] =
{1,-1.6181058535088741,1,1.5994425294189876,-0.98663912868667558,1,-1.6181058535088741,1,1.6152032648694865,-0.98688045473364316
};//IIR带阻滤波器-250Hz
#define numStages_250Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_250Hz;
static float32_t IIRStateF32_250Hz[4*numStages_250Hz];
static float32_t ScaleValue_250Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数const float32_t IIRCoeffs32BP_250Hz[5*numStages_250Hz] =
{1,-1.4142763744756295,1,1.3954270755132026,-0.98667212489138056,1,-1.4142763744756295,1,1.4142763745489406,-0.98684745156199472
};//IIR带阻滤波器-300Hz
#define numStages_300Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_300Hz;
static float32_t IIRStateF32_300Hz[4*numStages_300Hz];
static float32_t ScaleValue_300Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数const float32_t IIRCoeffs32BP_300Hz[5*numStages_300Hz] =
{1,-1.17562271738861,1,1.1570389697979899,-0.98669609658241275,1,-1.17562271738861,1,1.1785379122261563,-0.98682347619380328
};//IIR带阻滤波器-350Hz
#define numStages_350Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_350Hz;
static float32_t IIRStateF32_350Hz[4*numStages_350Hz];
static float32_t ScaleValue_350Hz = 0.99335783101529118 * 0.99335783101529118;//放缩系数const float32_t IIRCoeffs32BP_350Hz[5*numStages_350Hz] =
{1,-0.90802132733137575,1,0.91378825004392716,-0.98680445057512212,1,-0.90802132733137575,1,0.8901524097715261,-0.98671512011202733
};//IIR带阻滤波器-400Hz
#define numStages_400Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_400Hz;
static float32_t IIRStateF32_400Hz[4*numStages_400Hz];
static float32_t ScaleValue_400Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数const float32_t IIRCoeffs32BP_400Hz[5*numStages_400Hz] =
{1,-0.61806143864523178,1,0.62654427006115254,-0.98678826715653045,1,-0.61806143864523178,1,0.60134116156514272,-0.98673130233100281
};//IIR带阻滤波器-450Hz
#define numStages_450Hz          2    //2阶IIR滤波的个数static arm_biquad_casd_df1_inst_f32 S_450Hz;
static float32_t IIRStateF32_450Hz[4*numStages_450Hz];
static float32_t ScaleValue_450Hz = 0.99335783101529096 * 0.99335783101529096;//放缩系数const float32_t IIRCoeffs32BP_450Hz[5*numStages_450Hz] =
{1,-0.31288282611132939,1,0.32387775390876944,-0.98677366833749702,1,-0.31288282611132939,1,0.29771783508361671,-0.98674590052325395
};//滤波后剩余的直流分量
#define DC_AFTER_FILTER     3088//所有滤波器的初始化
void arm_emg_f32_filter_init()
{//带通滤波器初始化arm_fir_init_f32(&S_BP, FIR_EFFICIENT_NUM, (float32_t *)&firCoeffs32BP[0], &firStateF32[0], NUM_PER_CALL);//IIR带阻滤波器-50Hz初始化arm_biquad_cascade_df1_init_f32(&S_50Hz, numStages_50Hz, (float32_t *)&IIRCoeffs32BP_50Hz[0], (float32_t *)&IIRStateF32_50Hz[0]);//IIR带阻滤波器-100Hz初始化arm_biquad_cascade_df1_init_f32(&S_100Hz, numStages_100Hz, (float32_t *)&IIRCoeffs32BP_100Hz[0], (float32_t *)&IIRStateF32_100Hz[0]);//IIR带阻滤波器-150Hz初始化arm_biquad_cascade_df1_init_f32(&S_150Hz, numStages_150Hz, (float32_t *)&IIRCoeffs32BP_150Hz[0], (float32_t *)&IIRStateF32_150Hz[0]);//IIR带阻滤波器-200Hz初始化arm_biquad_cascade_df1_init_f32(&S_200Hz, numStages_200Hz, (float32_t *)&IIRCoeffs32BP_200Hz[0], (float32_t *)&IIRStateF32_200Hz[0]);//IIR带阻滤波器-250Hz初始化arm_biquad_cascade_df1_init_f32(&S_250Hz, numStages_250Hz, (float32_t *)&IIRCoeffs32BP_250Hz[0], (float32_t *)&IIRStateF32_250Hz[0]);//IIR带阻滤波器-300Hz初始化arm_biquad_cascade_df1_init_f32(&S_300Hz, numStages_300Hz, (float32_t *)&IIRCoeffs32BP_300Hz[0], (float32_t *)&IIRStateF32_300Hz[0]);//IIR带阻滤波器-350Hz初始化arm_biquad_cascade_df1_init_f32(&S_350Hz, numStages_350Hz, (float32_t *)&IIRCoeffs32BP_350Hz[0], (float32_t *)&IIRStateF32_350Hz[0]);//IIR带阻滤波器-400Hz初始化arm_biquad_cascade_df1_init_f32(&S_400Hz, numStages_400Hz, (float32_t *)&IIRCoeffs32BP_400Hz[0], (float32_t *)&IIRStateF32_400Hz[0]);//IIR带阻滤波器-450Hz初始化arm_biquad_cascade_df1_init_f32(&S_450Hz, numStages_450Hz, (float32_t *)&IIRCoeffs32BP_450Hz[0], (float32_t *)&IIRStateF32_450Hz[0]);
}//带通滤波和带阻滤波
void arm_emg_f32_filter(float32_t *dataInput, float32_t *dataOutput)
{float32_t dataOutputAfterFirbp = 0;float32_t dataOutputAfterIIRbs_50Hz = 0;float32_t dataOutputAfterIIRbs_100Hz = 0;float32_t dataOutputAfterIIRbs_150Hz = 0;float32_t dataOutputAfterIIRbs_200Hz = 0;float32_t dataOutputAfterIIRbs_250Hz = 0;float32_t dataOutputAfterIIRbs_300Hz = 0;float32_t dataOutputAfterIIRbs_350Hz = 0;float32_t dataOutputAfterIIRbs_400Hz = 0;float32_t dataOutputAfterIIRbs_450Hz = 0;//带通滤波arm_fir_f32(&S_BP, dataInput, &dataOutputAfterFirbp, NUM_PER_CALL);//50Hz带阻arm_biquad_cascade_df1_f32(&S_50Hz, &dataOutputAfterFirbp, &dataOutputAfterIIRbs_50Hz, NUM_PER_CALL);dataOutputAfterIIRbs_50Hz *= ScaleValue_50Hz;//100Hz带阻arm_biquad_cascade_df1_f32(&S_100Hz, &dataOutputAfterIIRbs_50Hz, &dataOutputAfterIIRbs_100Hz, NUM_PER_CALL);dataOutputAfterIIRbs_100Hz *= ScaleValue_100Hz;//150Hz带阻arm_biquad_cascade_df1_f32(&S_150Hz, &dataOutputAfterIIRbs_100Hz, &dataOutputAfterIIRbs_150Hz, NUM_PER_CALL);dataOutputAfterIIRbs_150Hz *= ScaleValue_150Hz;//200Hz带阻arm_biquad_cascade_df1_f32(&S_200Hz, &dataOutputAfterIIRbs_150Hz, &dataOutputAfterIIRbs_200Hz, NUM_PER_CALL);dataOutputAfterIIRbs_200Hz *= ScaleValue_200Hz;//250Hz带阻arm_biquad_cascade_df1_f32(&S_250Hz, &dataOutputAfterIIRbs_200Hz, &dataOutputAfterIIRbs_250Hz, NUM_PER_CALL);dataOutputAfterIIRbs_250Hz *= ScaleValue_250Hz;//300Hz带阻arm_biquad_cascade_df1_f32(&S_300Hz, &dataOutputAfterIIRbs_250Hz, &dataOutputAfterIIRbs_300Hz, NUM_PER_CALL);dataOutputAfterIIRbs_300Hz *= ScaleValue_300Hz;//350Hz带阻arm_biquad_cascade_df1_f32(&S_350Hz, &dataOutputAfterIIRbs_300Hz, &dataOutputAfterIIRbs_350Hz, NUM_PER_CALL);dataOutputAfterIIRbs_350Hz *= ScaleValue_350Hz;//400Hz带阻arm_biquad_cascade_df1_f32(&S_400Hz, &dataOutputAfterIIRbs_350Hz, &dataOutputAfterIIRbs_400Hz, NUM_PER_CALL);dataOutputAfterIIRbs_400Hz *= ScaleValue_400Hz;//450Hz带阻arm_biquad_cascade_df1_f32(&S_450Hz, &dataOutputAfterIIRbs_400Hz, &dataOutputAfterIIRbs_450Hz, NUM_PER_CALL);  dataOutputAfterIIRbs_450Hz *= ScaleValue_450Hz;//返回正数值以计算均方根if(dataOutputAfterIIRbs_450Hz >= DC_AFTER_FILTER){*dataOutput = dataOutputAfterIIRbs_450Hz - DC_AFTER_FILTER;}else{*dataOutput = DC_AFTER_FILTER - dataOutputAfterIIRbs_450Hz;}
}

这里有个需要注意的问题,就是每次调用函数处理的数据个数,可以一个一个地处理,也可以一次处理多个,我这里是一个一个地处理的。其实,各滤波器就是个算法,也就是有个对应的公式,将数据输入进去,再输出即可,具体设计到傅里叶变换的知识,可自行查阅资料。

另外,这个FIR系数里有些是用科学计数法来表示的,不用特别处理,C能识别。在C语言中,我们可以使用科学计数法来表示数字。具体方法是在数字后面加上一个大写或小写的字母E,再加上一个指数。

我的一点想法:时域数据通过fft转成频域,删除特定频率的数据,再ifft转成时域,不就可以删除特定频率的数据了?

这样的话:

低通:就相当于我把高频率的数据删除,只留低频率的数据;

高通:就相当于我把低频率的数据删除,只留高频率的数据;

带通:就相当于我把两侧的数据都删了;

带阻:就相当于我把中间的数据删掉了

补充

直流分量信号的频率是0,高通,带通都会被过滤掉,只有低通可以通过。

更多内容可参考以下系列课程:NO.1 基于matlab中的fdatool进行电生理信号预处理实战演练,以肌电信号为例去除噪声_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/107154.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

react处理跨域

如果是新建的react项目,没有将webpack的配置文件释放出来的话,请先运行 npm run eject 根目录会出现config文件夹,找到path.js就可以看到proxy的配置,默认读取的是src/setupProxy.js 那么我们可以在src目录下新建setupProxy.js…

python机器人编程——用python实现一个写字机器人

目录 一、前言二、整体框架2.1 系统构成2.2 硬件介绍2.2.1主要组成部分2.2.2机械结构2.2.3驱动及控制主板PS电机驱动原理简介: 2.2.4其余部分 2.3 机器人python程序框架2.3.1通信服务模块2.3.2消息处理模块2.3.3轨迹解析模块2.3.4机械臂逆解模块2.3.5写字板模块 三、机械臂的建…

【性能测试】Jmeter —— jmeter计数器

jmeter计数器 如果需要引用的数据量较大,且要求不能重复或者需要递增,那么可以使用计数器来实现 如:新增功能,要求名称不能重复 1,新增计数器 计数器:允许用户创建一个在线程组之内都可以被引用的计数器…

【数据结构-二叉树】二叉树

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

Python爬虫-IP隐藏技术与代理爬取

前言 在进行爬虫程序开发和运行时,常常会遇到目标网站的反爬虫机制,最常见的就是IP封禁,这时需要使用IP隐藏技术和代理爬取。 一、IP隐藏技术 IP隐藏技术,即伪装IP地址,使得爬虫请求的IP地址不被目标网站识别为爬虫。…

【STM32】常用存储器

常用存储器 RAM 存储器 RAM 是“Random Access Memory”的缩写,被译为随机存储器。所谓“随机存取”,指的是当存储器中的消息被读取或写入时,所需要的时间与这段信息所在的位置无关。而RAM可随读取其内部任意地址的数据,时间都是…

性能测试 —— Jmeter定时器

固定定时器 如果你需要让每个线程在请求之前按相同的指定时间停顿,那么可以使用这个定时器;需要注意的是,固定定时器的延时不会计入单个sampler的响应时间,但会计入事务控制器的时间 1、使用固定定时器位置在http请求中&#xf…

神经网络 07(正则化)

一、正则化 在设计机器学习算法时不仅要求在训练集上误差小,而且希望在新样本上的泛化能力强。许多机器学习算法都采用相关的策略来减小测试误差,这些策略被统称为正则化。因为神经网络的强大的表示能力经常遇到过拟合,所以需要使用不同形式的…

每天40min,我们一起用70天稳扎稳打学完《JavaEE初阶》——33/70 第三十三天【JavaScript(webapi)】

JavaScript WebAPI WebAPI 背景知识DOM 基本概念获取元素事件初识操作元素输入密码的 显示 和隐藏点击计数器勾选复选框获取/修改 样式 属性开关灯WebAPI 背景知识 DOM 基本概念 获取元素 事件初识

敏捷开发:适应变化的核心能力

​在当今高度变化的时代,软件开发的环境和要求也在不断变化。传统的开发方法往往难以适应这种快速变化,因此,一种新的软件开发方法——敏捷开发逐渐得到了广泛的关注和应用。 本文将介绍敏捷开发的概念、优势、实践经验、敏捷开发工具以及注…

python实现adb辅助点击屏幕工具

#!/usr/bin/env python # -*- coding: utf-8 -*-import re import os import time import subprocess import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk# 设置ADB路径(根据你的系统和安装路径进行调整) ADB_PATH C…

强化历程7-排序算法(2023.9.12)

此笔记学习图片来自于如下网址 1https://www.west999.com/info/html/chengxusheji/Javajishu/20190217/4612849.html 文章目录 强化历程7-排序算法1 冒泡排序(交换排序)2 选择排序3 直接插入排序4 希尔排序5 归并排序6 快速排序7 堆排序8 计数排序 强化历程7-排序算法 1 冒泡排…