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

2023-11-09

 

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;
}

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一阶数字低通滤波器的实现 的相关文章

  • 使用APIKey定向加密对外接口案例

    使用API Key定向加密对外接口案例 整体思路 前端通过某种方式生成一个动态字段 例如时间戳 随机数 UUID 等 前端将动态字段和其他请求参数一起发送给后端 并对请求参数进行加密 后端通过相同的加密算法 使用动态字段生成 API KEY
  • Python解析库lxml与xpath用法总结

    本文主要围绕以xpath和lxml库进行展开 一 xpath 概念 xpath节点 xpath语法 xpath轴 xpath运算符 二 lxml的安装 lxml的使用 lxml案例 一 xpath 1 xpath概念 XPath 是一门在

随机推荐

  • 通用分页的详解(Java后端常用)

    目录 一 通用分页 1 1通用分页是什么 1 2使用通用分页有什么好处 1 3经常在哪使用通用分页 二 往常的通用分页实现及代码 三 通用分页的讲解 思路 具体实现代码 四 JUnit框架的使用 4 1JUnit框架是什么 4 2JUnit
  • 动态加载 JS 文件

    动态加载JS文件是指在网页运行过程中通过JavaScript代码向页面中动态添加外部JS文件 这种方式能够提高页面加载速度和用户体验 并且可以帮助网站实现更多的功能和特效 本文将详细介绍动态加载JS文件的基本原理 优势 注意事项以及具体实现
  • MySQL Workbench 报错 Cannot connect to Database Server

    MySQL Workbench是一款专为MySQL设计的ER 数据库建模工具 可以使用MySQL Workbench设计和创建新的数据库图示 建立数据库文档 以及进行复杂的MySQL迁移 MySQL Workbench是下一代的可视化数据库
  • lstm with attention_一文搞懂NLP中的Attention机制(附详细代码讲解)

    公众号关注 ML NLP 设为 星标 重磅干货 第一时间送达 机器学习算法与自然语言处理出品 公众号原创专栏作者 Don hub 单位 京东算法工程师 学校 帝国理工大学 Outline Intuition Analysis Pros Co
  • 细谈select函数(C语言)

    文章目录 1 介绍 2 例程 例程1 例程2 1 介绍 select 在socket编程中还是比较重要的 可是对于初学Socket的人来说都不太爱用Select写程序 他们只是习惯写诸如connect accept recv 或 recvf
  • C++实现sqrt

    1 题目 给定接口double sqrt int x double delta 请你实现开平方 其中x为底数 delta为最大误差 2 分析实现 直觉 gt 二分法 为了方便处理 将范围砍掉一半 认为0 lt x 0 5 sqrt x lt
  • python算法中的字符串算法(详解)

    目录 学习目标 学习内容 字符串匹配算法 Brute Force算法 KMP算法
  • Vue2中如何使用vue.use对自定义组件/指令进行快速注册?

    在Vue js中 使用 Vue use 方法可以快速注册自定义组件和指令 下面是使用 Vue use 方法进行注册的示例 自定义组件的示例 const MyComponent 组件的选项 template div My Custom Com
  • Java工程师的职业规划(转载牛客)

    作者 牛客229127715号 链接 https www nowcoder com discuss 353149180384321536 sourceSSR search 来源 牛客网 Java工程师的职业规划 最全版本 第一篇 1 初级程
  • C++容器与算法

    容器 某一类型数据的集合 C 标准顺序容器包括 vector list queue 容器初始化 vector
  • QThread定时器

    如何在子线程中启动定时器 MyThread MyThread QObject parent QThread parent printf d construct n this gt currentThreadId MyThread MyThr
  • 【数据结构与算法】leetcode200.岛屿数量

    链接 题目 给你一个由 1 陆地 和 0 水 组成的的二维网格 请你计算网格中岛屿的数量 岛屿总是被水包围 并且每座岛屿只能由水平方向和 或竖直方向上相邻的陆地连接形成 此外 你可以假设该网格的四条边均被水包围 解题 利用深度优先搜索 遍历
  • JAVA环境、Tomcat、Mysql安装,创建IDEA JavaEE项目并使用JDBC连接Mysql

    1 Java环境安装配置 1 下载JDK 下载地址为http www oracle com technetwork java javase downloads index html 下载自己电脑所对应的版本 2 安装JDK和JRE 安装路径
  • H5 画布(canvas)的使用、元素的拖拽

    一 画布 canvas 的使用 1 绘图 画布 canvas 的使用 2 画布 页面中用于绘制图形的特殊区域 开发人员可以在这个区域内进行自定义图形的绘制 1 创建画布的方法
  • Langchain对设置代理地址

    可以通过如下方式对ChatOpenAI设置代理地址api base from langchain chat models import ChatOpenAI import os OPENAI API BASE https xxx v1 op
  • vue项目中引入XLSX插件,出现“export ‘default‘ (imported as ‘XLSX‘) was not found in ‘xlsx‘警告提示

    今天 天气晴朗 北风4 5级 今天在做element加xlsx表格导入功能时 使用xlsx时 在组件中引入xlsx 终端出现如下警告提示 经过一番捯饬 最终将0 18 3的版本uninstall卸载 而后安装低版本的xlsx 重新启动后发现
  • 关于UNIAPP环境下对自带组件的样式修改

    本人作为初学者 写博客只是为了巩固自己的所学记录错误 项目场景 项目场景 在公司提供的基本框架下使用UNIAPP开发移动端页面时 总能用到原生组件或一些框架提供的便利组件 像element等 本文只针对UNIAPP自带的组件进行解决 另外由
  • 开始使用Mac OS X——写给Mac新人

    本文转载至 http www cnblogs com chijianqiang archive 2011 08 03 2126593 html 写这篇文档的原因有两个 一 身边使用Mac的朋友越来越多 经常会有人来咨询一些常见的使用问题 比
  • 分布式核心设计原则

    目录 1 软件架构设计的六大原则 1 单一职责原则 Single Responsibility Principle SRP 2 开放封闭原则 Open Closed Principle OCP 3 里氏替换原则 Liskov Substit
  • 一阶数字低通滤波器的实现

    1 1 计算公式推导 一阶惯性滤波算法起源于一阶低通滤波电路 在电路设计中 用于吸收和消除叠加在低频信号源上的高频干扰成份十分有效 如图1所示 激励源 通过一个由电阻R和电容器C组成充 放电回路 并以电容两端的电压作为输出 构成了基本的一阶