matlab由滤波的系数得到传输函数 设计带通滤波器 design fdatool设计IIR带通滤波器

写在前面的话:

由滤波器系数得到传输函数:

使用matlab fdatool设计滤波器,得到幅频响应,得到滤波器系数,由系数如何得到滤波器的参数?

我的方法是 使用:点击Filt-Export to simulink Model, simulink打开后,出现了简单的滤波器或者在 simulink中设计滤波器,双击设计好的滤波器,可以参看其框图,根据框图可以将传输函数写出,即可得到滤波器的参数。

看到一个带通滤波器的设计如下,开始研究是如何设计的

带通滤波器设计matlab代码:

band_low = 0.3;       
band_high = 1.2;       
fs_origin = 25; 
hd_band = design(fdesign.bandpass('N,F3dB1,F3dB2',4,band_low,band_high,fs_origin),'butter'); %带通滤波器
%fvtool(hd_band); % view
measure(hd_band) %Measure the frequency response characteristics of the filter 
%filtered = filter(hd_band,x);  % 滤波器的使用,输入数组x,输出数组filtered

查看官网MathWorks,找到关于滤波器的设计design,带通滤波器的设计fdesign.bandpass

The fdesign.bandpass function returns a bandpass filter design specification object that contains specifications for a filter such as passband frequency, stopband frequency, passband ripple, and filter order. Use the design function to design the filter from the filter design specifications object.

本处只解析此处滤波器的设计参数,若查看更多,移至官网MathWorks

  • N:Filter order for FIR filters. Or both the numerator and denominator orders for IIR filters when Na and Nb are not provided. Specified using FilterOrder. 关于滤波其的阶数
  • F3dB1:Frequency of the 3 dB point below the passband value for the first cutoff, specified in normalized frequency units. Applies to IIR filters.
  • F3dB2:Frequency of the 3 dB point below the passband value for the second cutoff, specified in normalized frequency units. Applies to IIR filters.
  • Fs bandpassSpecs = fdesign.bandpass(___,Fs) provides the sample rate in Hz of the signal to be filtered. Fs must be specified as a scalar trailing the other numerical values provided. In this case, all frequencies in the specifications are in Hz as well. 

上面这句话解释了传入采样频率的必要性。

'N,F3dB1,F3dB2'butter

以上参数的设置使用与IIR butter

fdesign.bandpass('N,F3dB1,F3dB2',4,band_low,band_high,fs_origin)
show:  
bandpass (具有属性):

               Response: 'Bandpass'
          Specification: 'N,F3dB1,F3dB2'
            Description: {3×1 cell}
    NormalizedFrequency: 0
                     Fs: 25
            FilterOrder: 4
                  F3dB1: 0.3000
                  F3dB2: 1.2000

fvtool(hd_band)% 查看幅频特性

measure(hd_band) %Measure the frequency response characteristics of the filter 

Sample Rate             : 25 Hz       
First Stopband Edge     : Unknown     
First 6-dB Point        : 250.7041 mHz
First 3-dB Point        : 300 mHz     
First Passband Edge     : Unknown     
Second Passband Edge    : Unknown     
Second 3-dB Point       : 1.2 Hz      
Second 6-dB Point       : 1.4315 Hz   
Second Stopband Edge    : Unknown     
First Stopband Atten.   : Unknown     
Passband Ripple         : Unknown     
Second Stopband Atten.  : Unknown     
First Transition Width  : Unknown     
Second Transition Width : Unknown  

使用fdatool同样实现此滤波器的设计

设计的滤波器通过File-Export导出到工作区;

也可以在analysis中查看器信息,比如系数、幅频、相频特性。比如查看analysis中点击Filter Information中可以看到fdesign使用的内容:'N,F3dB1,F3dB2'

完成了带通滤波器的设计,就在考虑如何转化为C语言代码,这里有个网站可以进行转化,设计滤波器转为C语言实现,但是结果并没有达到我想要的要求,我的目的是怎样将fdatool中设计的滤波器系数中得到其对应的传递函数H(Z),有了传递函数,就可以自己写C语言实现了

在上面fdatool设计的滤波器中,两种方法查看设计的滤波器,任意一种都可以;

  1. 点击Filt-Export to simulink Model, simulink打开后,出现了简单的滤波器,
  2. 或者采用如下图操作,从左到右三个按键

     

双击可以看到滤波器的内部结构,如图显示为两个二阶滤波器级联:

放大其中一个滤波器如下

简单作了标记如下

并给出其对应的C语言实现,此代码无法直接运行只是提取了一部分带通滤波器实现部分

/* IIR fourth-order filter coefficients */
typedef struct 
{
	float(*a)[3];
	float(*b)[3];
	float* gain;
} IIR_ORDER4_COEFF_T;

/* Save the in-process' data of the second-order filter */
typedef struct 
{
	float m1;
	float m2;
} FILTER_ORDER2_T;

/*三轴信号处理前的滤波:四阶带通(0.3-1.2)Hz)滤波,由两个二阶滤波级联起来*/
float a_raw[2][3] = {
	{ 1.00, (float)-1.9175958145710057, (float)0.9246554650412394 },    //第一级二阶滤波,分母
	{ 1.00, (float)-1.7227109782351659, (float)0.7854234338937474 }    //第二级二阶滤波,分母
};//分母
float b_raw[2][3] = {
	{ 1.00, (float)0.00, (float)-1.00 },    //第一级二阶滤波,分子
	{ 1.00, (float)0.00, (float)-1.00 }    //第二级二阶滤波,分子
};//分子
float gain_raw[2] = { (float)0.1048485643154691/*第一级增益*/, (float)0.1048485643154691/*第二级增益*/ };

/******************************************************************************/
/** Start, initialize the parameters
* @param[in]
*
* @return
*
*//*
* History        :
* 1.Date         : 2020/8/28
*   Author       : 
*   Modification : Created function

*******************************************************************************/
void StartSwim(void) 
{
	/* signal filter parameter initialization */
	IIR_Raw.a = a_raw;
	IIR_Raw.b = b_raw;
	IIR_Raw.gain = gain_raw;
}

/*
x: input
m1:保存中间滤波器数据
m2:保存中间滤波器数据
a:滤波器系数
b:滤波器系数
gain:增益,对于只支持定点小数运算的,需要把增益分配到每个二阶IIR滤波器的系数中,使得每次中间的结果都不溢出,即使其频率响应的最大值最接近0dB
*/
float filterOrder2(float* x, float* m_1, float* m_2, float* a, float* b, float* gain){
	float y, m;
	//计算没有增益的滤波输出,存于y_
	m = *x - a[1] * *m_1 - a[2] * *m_2;    //求当前m,同时作为求y_的中间步骤
	y = m + b[1] * *m_1 + b[2] * *m_2;
	//更新*m_1和*m_2
	*m_2 = *m_1;
	*m_1 = m;
	//返回带增益的滤波输出
	return y* *gain;
}

/******************************************************************************/
/** filter: Fourth-order filter, direct type II
* @param[in]
* filter_state	:Store the middle state of the filter
* @return
*
*//*
* History        :
* 1.Date         : 2020/8/28
*   Author       : 
*   Modification : Created function

*******************************************************************************/
float FilterOrder4(float data, FILTER_ORDER4_T* filter_state, IIR_ORDER4_COEFF_T* IIR_coeffs)
{
	float data_filtered;

	filter_state->first_order2_out = filterOrder2(&data, &filter_state->first_order2.m1, &filter_state->first_order2.m2, IIR_coeffs->a[0], IIR_coeffs->b[0], IIR_coeffs->gain);  //第一级二阶滤波
	data_filtered = filterOrder2(&filter_state->first_order2_out, &filter_state->second_order2.m1, &filter_state->second_order2.m2, IIR_coeffs->a[1], IIR_coeffs->b[1], &IIR_coeffs->gain[1]);  //第二级二阶滤波
	
	return data_filtered;
}

/******************************************************************************/
/** Band-pass filtering for the norm data: 0.25-2Hz
* @param[in] x:norm data
*
* @return filtered data
*
*//*
* History        :
* 1.Date         : 2020/8/28
*   Author       : 
*   Modification : Created function

*******************************************************************************/
float BandFilter(float x)
{
	float y = FilterOrder4(x, &xyz_filter, &IIR_vec);

	return y;
}

关于fdatool设计的带通滤波器的系数使用

使用Matlab的FDAtool工具可以很方便地设计IIR滤波器。使用File菜单中的export选项可以把滤波器的参数输出到Matlab的工作空间中。若滤波器为IIR型,则输出的变量名为G和SOS。它把高阶的IIR滤波器转换为一系列二阶IIR滤波器的级联。SOS为二阶IIR滤波器的系数(b,a),G为各级的增益系数,可用来调节各级通带的衰减。计算IIR滤波器的输出的时候,先将输入数据乘以G, 然后一一通过SOS中的每个IIR滤波器,就得到最终的结果了。

SOS的每一行表示一级二阶IIR滤波器系[b0,b1,b2,a0,a1,a2],G的每个元素表示相应级的增益系数。也即将G乘上SOS的b0,b1,b2。得到一组新的滤波器系数SOS',可调用MATLAB滤波函数sosfilt对输入信号进行滤波。

但是如果二阶IIR滤波器的程序只支持定点小数运算的话,那么就需要调整一下系数了。因为设计出来的G有时候很小(不知道会不会很大),这样一旦把输入数据乘以G后,就会使得二阶IIR滤波器的输入过小,造成很大的误差。我们需要把G分配到每个二阶IIR滤波器的系数中,使得每次得到的中间结果都刚好不会溢出。若以IIRi表示第i个二阶IIR滤波器的话,则我们需要保证IIR1, IIR1 * IIR2, IIR1 * IIR2 * IIR3, … 的频率响应都不超过0dB,*号表示级联。为了使得输出的精度最好,我们还需要让上面这些滤波器的频率响应中的最大值最接近0dB。

级联型:将系统传递函数H(z)因式分解为多个二阶子系统,系统函数就可以表示为这些二阶子系统传递函数的乘积。实现时将每个二阶子系统用直接型实现,整个系统函数用二阶环节的级联实现。

高阶IIR滤波器的实现是采用二阶滤波器级联的方式来实现的。默认情况下,Filter Coefficients把结果分成多个2阶Section显示,其中还有增益。增益的目的是为了保证计算的精度和系统的稳定性。

 

简单介绍低通滤波器的使用,其函数参考fdesign官网

如下

简单设计了低通滤波

%% 低通滤波
function filtered = LowFilter(x)
fs_origin=1;
fc=0.03;
N=4;
hd_low = design(fdesign.lowpass('N,F3dB',N,fc, fs_origin),'butter');
filtered = filter(hd_low,x); 
end

..

 

  • 11
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚努力的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值