一阶数字低通滤波器的实现

 

1.1 计算公式推导

       一阶惯性滤波算法起源于一阶低通滤波电路。在电路设计中,用于吸收和消除叠加在低频信号源上的高频干扰成份十分有效。如图1所示,激励源 ,通过一个由电阻R和电容器C组成充、放电回路,并以电容两端的电压作为输出,构成了基本的一阶低通滤波系统。由于电容器具有通交流阻直流的特性,因而当信号以较低频率通过该系统时,输出端没有(或几乎没有)削减,从而能够很好地通过;当信号频率较高时,输出端将会受到很大的衰减.当输入信号频率高到一定程序时,电容器相当于短路,高频会完全被滤除掉,在软件方面通过编制数字滤波程序来剔除和削弱信号中存在的高频干扰分量,这是一种重要和有效的常用手段。

 

        

图1-1一阶低通滤波电路

根据基尔霍夫定律可得出一阶滤波电路动态输入输出模型为:

                     (1-1)

式中,T=RC。

阶跃电压Ui下的时域表达式:

                                  (1-2)

在频域中的分析,频域中的表达式:

令(1-3)式中s=jw,一阶后向差分法中从S域到Z域变换, 其中T是采样周期,表达式如下:

 

z反变换求差分方程后可得:

 

         

 

A为滤波系数,滤波系数的大小与采样周期 和滤波器的截止频率有关。(1-5)

式可以进一步简写成(1-6)式:

 

                     

有公式可知一阶滤波器与当前的输入值和上一次的输出值有关;滤波系数越小,滤波结果越平稳,但是灵敏度越低;滤波系数越大,灵敏度越高,但是滤波结果越不稳定。

 

采用双线性变换法推导公式如下:

                  

令(1-3)式中s=jw,将(1-7)代入得:

                        

1.2 算法实现及仿真

1.2.1 一阶向后差分法

一.利用python实现的代码如下:

import numpy as np
import matplotlib.pyplot as plt

Ts=0.003                     #采样时间
Fl=5                        #截止频率
a=1/(1+1/(2*np.pi*Ts*Fl))    #滤波系数

print(a)                         #打印滤波计算出的值
x=np.linspace(-np.pi,np.pi,2000) #在[-pi,pi]区间上分割正2000个点
                                 # 可以理解为信号采样时间为 2*pi/2000s
data1=np.zeros_like(x)           #输入信号
data=np.zeros_like(x)            #输入信号
y1=np.zeros_like(x)              #一阶滤波输出
for i in range(len(x)):
    #幅值为1 频率为 1Hz的信号  + 幅值为0.5 频率为30Hz的干扰信号+ 幅值为0.2 频率为6Hz的干扰信号
    data =np.sin( 2 * np.pi * x)+0.2*np.sin(6* 2 * np.pi * x)\
             +0.5*np.sin(100* 2 * np.pi * x)
    data1[i]=np.sin( 2 * np.pi * x[i])
    if(i>0):
        y1[i] = a * data[i] + (1 - a) * y1[i - 1]
    else:
        y1[0] = data[0]

#绘制被干扰的信号  + 一阶滤波后的信号

plt.subplot(2, 1, 1)
plt.plot(x,data ,label='sig+noise')
plt.plot(x,y1,   'r',label='first order')
plt.title("Lowpass Filter Frequency Response")
plt.xlabel('Time [sec]')
plt.grid()
plt.legend()
#原信号  + 一阶滤波后的信号
plt.subplot(2, 1, 2)
plt.plot(x,data1 ,label='sig')
plt.plot(x,y1,   'r',label='first order')
plt.xlabel('Time [sec]')
plt.grid()
plt.legend()

plt.show()

 

二.python仿真波形图:

输入信号为幅值为1 频率为 1Hz的信号  + 幅值为0.5 频率为30Hz的干扰信号+ 幅值为0.2 频率为6Hz的干扰信号,不同频率下的仿真图如下所示:

 

 

        从几次的仿真结果可以看出,在采样频率一定下,滤波效果与期望滤除的干扰的频率有关,即截止频率fc;fc频率越小,滤波系数也越小。滤波也越明显,滞后就更大,也即惯性就更大。所以在在选取滤波系数时,应该合理的选取fc的值。

1.2.1 双线性变换差分法

一.利用python实现的代码如下(双线性变换):

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter, freqz

Ts=0.003                    #采样时间
Fl=12                      #截止频率
a=1/(1+1/(2*np.pi*Ts*Fl))    #滤波系数
b0=1/(1+(1/(np.pi*Fl*Ts)))
b1=b0
a0=-(1-(1/(np.pi*Fl*Ts)))/(1+(1/(np.pi*Fl*Ts)))

print(b0)                         #打印滤波计算出的值
print(a0)
print(2*b0+a0)


x=np.linspace(-np.pi,np.pi,2000) #在[-pi,pi]区间上分割正2000个点
                                 # 可以理解为信号采样时间为 2*pi/2000s
data1=np.zeros_like(x)           #输入信号
data=np.zeros_like(x)            #输入信号
y1=np.zeros_like(x)              #一阶滤波输出
for i in range(len(x)):
    #幅值为1 频率为 1Hz的信号  + 幅值为0.5 频率为150Hz的干扰信号+ 幅值为0.2 频率为6Hz的干扰信号
    data =np.sin( 2 * np.pi * x)\
             +0.5*np.sin(150* 2 * np.pi * x)
    data1[i]=np.sin( 2 * np.pi * x[i])
    if(i>0):
        y1[i] = b0 * data[i] +b1 * data[i-1] +a0 * y1[i - 1]
    else:
        y1[0] = data[0]

#绘制被干扰的信号  + 一阶滤波后的信号



plt.subplot(2, 1, 1)
plt.plot(x,data ,label='sig+noise')
plt.plot(x,y1,   'r',label='first order')

plt.xlabel('Time [sec]')
plt.grid()
plt.legend()
#原信号  + 一阶滤波后的信号
plt.subplot(2, 1, 2)
plt.plot(x,data1 ,label='sig')
plt.plot(x,y1,   'r',label='first order')
plt.xlabel('Time [sec]')
plt.grid()
plt.legend()

plt.show()

 

 

 

1.2 利用C语言实现的代码如下:

#ifndef _ORDER_1_LP_FILTER_H_
#define _ORDER_1_LP_FILTER_H_

#include <stdint.h>
struct Order1LpFilter
{
    //初始化
    struct
    {
        void (*Set)(struct Order1LpFilter *self, float cutFreq, float runFreq); //设置截止和采样频率
        void (*VaryCutFreq)(struct Order1LpFilter *self, float cutFreq);           //改变截止频率
        float cutFreq;                                                             //截止频率
        float samFreq;                                                             //采样频率
    } Init;
    //采样计算
    struct
    {
        float (*In)(struct Order1LpFilter *self, float x);
        float out_y;                                                              //输出值
    } Prd;
    //变量 中间变量  系数等,由初始参数 初始化计算得出
    struct
    {
        float Ts;                                                                //采样周期
        float a0, b0, b1;                                                        //差分系数
        float Xn_1, Yn_1;
    } pri;
};
void Order1LpFilter_Create(struct Order1LpFilter *self);
#endif
//创建方式
// struct Order1LpFilter mlp;
// Order1LpFilter_Create(&mlp);
// mlp.Init.Set(&mlp,12, 1000);
#include "Order1LpFilter.h"
#include <string.h>
#include "math.h"
#define MID(a, min, max) (a = (a < min) ? min : (a < max) ? a : max)
static const float PI = 3.1415926535897932384626f;
#define my self->pri
//一阶级惯性滤波
/*******************************************************************************
 * 函 数 名         : _Update
 * 函数功能         : 各系数计算
 * 输入参数         : 无
 * 返 回 值         : 无
 *******************************************************************************/
static void _Update(struct Order1LpFilter *self)
{
    float temp;
    float halfdigiW, tgAnaWT;
    halfdigiW = PI * self->Init.cutFreq * self->pri.Ts;
    tgAnaWT = tan(halfdigiW); //ignore the 1/T
    self->pri.b0 = 1.0f/(1.0f +1/tgAnaWT);
    self->pri.b1 = self->pri.b0;
    
    self->pri.a0 =  -(1.0f - 1/tgAnaWT)/(1.0f + 1/tgAnaWT);
}
/*******************************************************************************
 * 函 数 名         : InitSet
 * 函数功能         : 初始化
 * 输入参数         : 无
 * 返 回 值         : 无
 *******************************************************************************/
static void InitSet(struct Order1LpFilter *self, float cutFreq, float runFreq)
{
    self->Init.cutFreq = MID(cutFreq, 0, runFreq*0.5f);               //截止频率
    self->Init.samFreq = runFreq;               //采样频率
    self->pri.Ts = 1.0f / self->Init.samFreq;    //采样周期
    _Update(self);
}
/*******************************************************************************
 * 函 数 名         : InitVaryCutF
 * 函数功能         : 改变截止频率
 * 输入参数         : 无
 * 返 回 值         : 无
 *******************************************************************************/
static void InitVaryCutF(struct Order1LpFilter *self, float cutFreq)
{
    self->Init.cutFreq = cutFreq;
    _Update(self);
}
/*******************************************************************************
 * 函 数 名         : 
 * 函数功能         : 本次输出结果计算
 * 输入参数         : 无
 * 返 回 值         : 无
 * 计算公式         : Y(n)=b0*X(n)+b1*X(n-1)+a0*Y(n-1)
 *******************************************************************************/
static float PrdIn(struct Order1LpFilter *self, float Xn)
{
    self->Prd.out_y =  self->pri.b0 * Xn +  self->pri.b1 * self->pri.Xn_1  + self->pri.a0 * self->pri.Yn_1;
    self->pri.Yn_1  =  self->Prd.out_y;
    self->pri.Xn_1  =  Xn;
    return self->Prd.out_y;
}
/*******************************************************************************
 * 函 数 名         : Order1LpFilter_Create
 * 函数功能         : 创建对象 初始化
 * 输入参数         : self对象
 * 返 回 值         : 无
 *******************************************************************************/
void Order1LpFilter_Create(struct Order1LpFilter *self)
{
    memset(self, 0, sizeof(struct Order1LpFilter));
    self->Init.Set = InitSet;
    self->Init.VaryCutFreq = InitVaryCutF;
    self->Prd.In = PrdIn;
}

 

 

  • 14
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 一阶巴特沃斯滤波器是一种常见的滤波器,常用于信号处理中。它是由巴特沃斯函数转换得到的滤波器,其特点是具有快速衰减的特性,能够有效地滤除噪声和频率干扰。 在C语言中实现一阶巴特沃斯滤波器的关键是计算滤波器的传递函数和滤波器的差分方程。 首先,我们需要确定滤波器的截止频率和采样频率。截止频率定义了滤波器的频率阈值,采样频率表示输入信号的采样速率。 其次,我们可以使用以下公式计算一阶巴特沃斯滤波器的传递函数: H(s) = 1 / (s + 1 / (2 * π * fc)) 其中,H(s)为传递函数,s为复变量,fc为截止频率。 接下来,我们需要将传递函数转换为差分方程,以便在数字系统中进行实现。差分方程的一般形式为: y(n) = a * x(n) + b * y(n-1) 这里,x(n)为输入信号,y(n)为滤波器的输出信号,a和b是滤波器的系数。 最后,我们可以使用C语言代码实现一阶巴特沃斯滤波器。其中,x(n)和y(n)可以表示为数组或变量,根据差分方程递推计算y(n)的值。 以下是简化的代码示例: ```c // 定义滤波器系数 float a = 1 / (1 + (2 * π * fc)); float b = (1 - a); // 定义输入信号和输出信号 float x[n]; // 输入信号 float y[n]; // 输出信号 // 初始化输出信号 y[0] = x[0]; // 递推计算滤波器的输出信号 for(int i=1; i<n; i++) { y[i] = a * x[i] + b * y[i-1]; } ``` 这段代码用于计算滤波器的输出信号y(n),其中x(n)为输入信号。滤波器的系数a和b由截止频率fc确定。 需要注意的是,这只是一种简化实现,实际应用中可能需要考虑更多的因素,如滤波器的阶数、输入信号的采样和量化等。 ### 回答2: 一阶巴特沃斯滤波器是一种常用的模拟滤波器,它采用巴特沃斯滤波器设计方法来实现滤波功能。巴特沃斯滤波器的特点是在通带内具有平坦的幅频特性,即不引入额外的谐波失真。在滤波器设计中,频率是以离散点为单位的,因此需要对频率进行归一化处理。 在C语言中实现一阶巴特沃斯滤波器,首先需要定义滤波器的传递函数,滤波器的传递函数用于描述输入信号经过滤波器后的输出信号的关系。一阶巴特沃斯滤波器的传递函数可以表示为: H(s) = 1 / (s + ωc) 其中,s是复频域变量,ωc是截止频率。将传递函数转化为离散时间域的差分方程形式,可以得到: y[n] = (x[n] + x[n-1]) / (1 + ωc) 其中,y[n]是滤波器的输出信号,x[n]是滤波器的输入信号,x[n-1]是输入信号的上一个采样点的值。 在C语言中,可以使用一个循环来实现滤波器的计算过程。首先,定义输入信号和输出信号的数组,以及截止频率ωc。接着,在循环中,采用上述的差分方程进行滤波计算: for(int n=0; n<N; n++) { y[n] = (x[n] + x[n-1]) / (1 + ωc); } 其中,N是输入信号的长度。 通过上述的C语言代码,可以实现一阶巴特沃斯滤波器的功能。可以根据具体的应用场景和需求,调整截止频率和输入信号的长度,来实现不同的滤波效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

紫气东来d

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

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

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

打赏作者

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

抵扣说明:

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

余额充值