当前位置: 首页 > news >正文

软件低通滤波器(附代码)

软件低通滤波器(附代码)

1. 什么是低通滤波器

低通滤波器(Low-Pass Filter, LPF)就像是一个数字世界的“筛子”。它允许低频信号(平缓的变化,如飞机的姿态)通过,而阻挡高频信号(剧烈的震动,如电机的噪声)。

在传感器数据处理中,信号通常由两部分组成:
有用信号: 变化相对缓慢的真实物理运动。
噪声: 由电子干扰或机械振动引起的高频随机跳动。
低通滤波器的核心任务就是:抹除尖锐的毛刺,保留平滑的趋势。

一阶低通滤波器 (1st Order LPF)
一阶滤波器是最基础的形式,通常被称为加权指数平均滤波
差分方程
y[n]=α⋅x[n]+(1-α)⋅y[n-1]
x[n]:本次采样值。
y[n-1]:上一次的滤波输出。
α:平滑系数(0 到 1 之间)。

一阶滤波器优缺点:
优点: 算法极简,计算量极小,只需要存储一个上一次的值。
缺点: “杀伤力”有限。它在截止频率之后的衰减速度只有 -20dB/dec。这意味着如果你想强力过滤噪声就必须把α设得很小,但这会导致严重的信号延迟(相位滞后)


二阶低通滤波器 (2nd Order LPF)
硬件类比: 如果一阶滤器是一层海绵,二阶滤器就是弹簧 + 减震筒的组合。

衰减速度: 它的衰减速度是 -40dB/dec。在同样的截止频率下,二阶滤器对高频噪声的抑制能力是一阶的 100 倍左右。

巴特沃斯特性: 代码中实现的巴特沃斯(Butterworth)型,最大的特点是在通带内(你想保留的频率范围内)非常平坦,不会让你的原始数据变形。


性能对比

应该如何选择
选一阶: 当你的单片机性能极差,或者噪声非常微弱,只需要稍微润色一下数据时。
选二阶: 当你处理的是陀螺仪、加速度计这种处于高振动环境(如无人机、平衡车)下的传感器时。

2. PT1 实现代码

#ifndef __FILTER_H
#define __FILTER_H
#include <stdint.h>
#include <math.h>
#include <stdbool.h>
/*=================== 一阶低通滤波器 (PT1) ===================*/
typedef struct {float state;    // 滤波器状态 (上一次的输出值)float RC;       // RC时间常数 = 1/(2π*fc)float dT;       // 采样周期 (秒)
} pt1Filter_t;
// 初始化
void pt1FilterInit(pt1Filter_t *filter, uint8_t f_cut, float dT);
// 应用滤波
float pt1FilterApply(pt1Filter_t *filter, float input);
// 重置
void pt1FilterReset(pt1Filter_t *filter, float input);
#endif //__FILTER_H#include "filter.h"#define M_PI_F 3.14159265f/*** @brief 初始化PT1滤波器* @param filter 滤波器结构体指针* @param f_cut  截止频率 (Hz)* @param dT     采样周期 (秒)*/
void pt1FilterInit(pt1Filter_t *filter, uint8_t f_cut, float dT)
{filter->RC = 1.0f / (2.0f * M_PI_F * f_cut);  // RC = 1/(2πfc)filter->dT = dT;filter->state = 0.0f;
}
/*** @brief 应用一阶低通滤波* @param filter 滤波器结构体指针* @param input  输入样本值* @return 滤波后的输出值* * 公式: y[n] = y[n-1] + (dt/(RC+dt)) * (x[n] - y[n-1])*/
float pt1FilterApply(pt1Filter_t *filter, float input)
{filter->state = filter->state + filter->dT / (filter->RC + filter->dT) * (input - filter->state);return filter->state;
}
/*** @brief 重置滤波器状态*/
void pt1FilterReset(pt1Filter_t *filter, float input)
{filter->state = input;
}// 示例1:一阶滤波器 (PT1) - 遥控信号平滑#include "filter.h"
// 定义滤波器 (必须保持状态,用static或全局变量)
static pt1Filter_t rcRollFilter;
static pt1Filter_t rcPitchFilter;
void init(void)
{// 初始化:截止频率10Hz,采样周期20ms (50Hz更新率)pt1FilterInit(&rcRollFilter,  10, 0.02f);pt1FilterInit(&rcPitchFilter, 10, 0.02f);
}
void mainLoop(void)
{// 读取原始遥控值 (0-65535)uint16_t rawRoll = getRCChannel(ROLL_CHANNEL);// 应用滤波 (平滑后的值)float rollSmooth = pt1FilterApply(&rcRollFilter, (float)rawRoll);// 使用滤波后的值setpoint.attitude.roll = rollSmooth;
}

3. lpf2p 实现代码

#ifndef __FILTER_H
#define __FILTER_H
#include <stdint.h>
#include <math.h>
#include <stdbool.h>typedef struct {float a1, a2;           // 反馈系数 (分母)float b0, b1, b2;       // 前馈系数 (分子)float delay_element_1;  // 状态变量 y[n-1]float delay_element_2;  // 状态变量 y[n-2]
} lpf2pData;
// 初始化
void lpf2pInit(lpf2pData* lpfData, float sample_freq, float cutoff_freq);
// 应用滤波
float lpf2pApply(lpf2pData* lpfData, float sample);
// 重置
float lpf2pReset(lpf2pData* lpfData, float sample);#endif //__FILTER_H/*=================== 二阶低通滤波器实现 ===================*/#include "filter.h"
#define M_PI_F 3.14159265f
/*** @brief 初始化二阶低通滤波器* @param lpfData      滤波器结构体指针* @param sample_freq  采样频率 (Hz)* @param cutoff_freq  截止频率 (Hz)* * 使用双线性变换设计的Butterworth滤波器*/
void lpf2pInit(lpf2pData* lpfData, float sample_freq, float cutoff_freq)
{if (lpfData == NULL || cutoff_freq <= 0.0f) {return;}float fr = sample_freq / cutoff_freq;float ohm = tanf(M_PI_F / fr);float c = 1.0f + 2.0f * cosf(M_PI_F / 4.0f) * ohm + ohm * ohm;// 计算滤波器系数lpfData->b0 = ohm * ohm / c;lpfData->b1 = 2.0f * lpfData->b0;lpfData->b2 = lpfData->b0;lpfData->a1 = 2.0f * (ohm * ohm - 1.0f) / c;lpfData->a2 = (1.0f - 2.0f * cosf(M_PI_F / 4.0f) * ohm + ohm * ohm) / c;// 清零状态lpfData->delay_element_1 = 0.0f;lpfData->delay_element_2 = 0.0f;
}
/*** @brief 应用二阶低通滤波* @param lpfData 滤波器结构体指针* @param sample  输入样本值* @return 滤波后的输出值* * 差分方程:* y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2]*/
float lpf2pApply(lpf2pData* lpfData, float sample)
{// 计算中间变量 (输入部分)float delay_element_0 = sample - lpfData->delay_element_1 * lpfData->a1 - lpfData->delay_element_2 * lpfData->a2;// 检查非法值if (!isfinite(delay_element_0)) {delay_element_0 = sample;}// 计算输出float output = delay_element_0 * lpfData->b0 + lpfData->delay_element_1 * lpfData->b1 + lpfData->delay_element_2 * lpfData->b2;// 移位更新状态lpfData->delay_element_2 = lpfData->delay_element_1;lpfData->delay_element_1 = delay_element_0;return output;
}
/*** @brief 重置滤波器状态*/
float lpf2pReset(lpf2pData* lpfData, float sample)
{float dval = sample / (lpfData->b0 + lpfData->b1 + lpfData->b2);lpfData->delay_element_1 = dval;lpfData->delay_element_2 = dval;return lpf2pApply(lpfData, sample);
}#include "filter.h"
// 三轴传感器需要3个独立的滤波器
static lpf2pData gyroX_LPF, gyroY_LPF, gyroZ_LPF;
static lpf2pData accX_LPF,  accY_LPF,  accZ_LPF;
void sensorsInit(void)
{// 陀螺仪:采样率1000Hz,截止频率80Hzlpf2pInit(&gyroX_LPF, 1000.0f, 80.0f);lpf2pInit(&gyroY_LPF, 1000.0f, 80.0f);lpf2pInit(&gyroZ_LPF, 1000.0f, 80.0f);// 加速度计:采样率1000Hz,截止频率30Hzlpf2pInit(&accX_LPF, 1000.0f, 30.0f);lpf2pInit(&accY_LPF, 1000.0f, 30.0f);lpf2pInit(&accZ_LPF, 1000.0f, 30.0f);
}
void sensorTask(void)
{// 读取原始传感器数据float raw_gx = readGyroX();float raw_gy = readGyroY();float raw_gz = readGyroZ();// 应用滤波float filt_gx = lpf2pApply(&gyroX_LPF, raw_gx);float filt_gy = lpf2pApply(&gyroY_LPF, raw_gy);float filt_gz = lpf2pApply(&gyroZ_LPF, raw_gz);// 使用滤波后的数据imuUpdate(filt_gx, filt_gy, filt_gz, ...);
}

4. 常用参数选择

http://www.jsqmd.com/news/412251/

相关文章:

  • pc移动端自适应软件库网站源码
  • 餐饮店点餐小程序开源源码
  • Kubernetes(K8s)全面详解与实战指南
  • 发货100文章商品付费阅读系统源码
  • PostgreSQL 入门学习教程,从入门到精通,PostgreSQL 16 (Windows) 安装与核心语法实战指南(2)
  • 基于CEEMDAN-CNN-BiLSTM的多变量输入单步风电功率预测研究附Matlab代码
  • 基于西门子plc 博图 1200 药片自动 装瓶 机控制系统设计 1.仿真+报告(1.5W字)...
  • 2026最新十大知名全屋定制板材品牌推荐榜!优质环保品质与高性价比源头厂家选择指南,适配全空间定制需求 - 十大品牌榜
  • Jmeter和Postman那个工具更适合做接口测试?
  • 上海直饮水机代理商怎么选?5家靠谱供应商推荐 - 小坤哥
  • 程序员藏书神器!本本书屋onlinetoolsland.com 解锁技术学习高效路径
  • scFv 分子稳定性优化:核心策略与关键技术
  • 利用开源工具打造个人数字图书馆:从网络资源到本地管理的技术实践
  • 从资源索引到知识管理:利用“本本书屋”与开源工具构建个人数字图书馆
  • 基于CasADi框架的模型预测控制(MPC)方法,应用于质点车辆模型的轨迹跟踪问题附Matlab代码
  • COGS 3349. [HSOI 2020
  • 人工智能之数学基础:高阶导数
  • 搭建个人知识库:从“本本书屋”出发的电子书管理技术实践
  • 绕过技术书籍的“付费墙”:一个程序员如何用开源思维打造免费知识库
  • [豪の算法奇妙冒险] 代码随想录算法训练营第四十五天 | 115-不同的子序列、583-两个字符串的删除操作、72-编辑距离
  • 人工智能之数学基础:一元函数链式法则
  • 2025年电网校招录用人数Top50大学排名
  • 海康VM通信常见应用方式详细解释
  • Skoltech等机构揭秘:当AI压缩技术遭遇“信息堵车“时会发生什么
  • 上海科技大学+上海AI实验室:当AI助手被“越狱“后会做什么?
  • SaaS产品VS实物产品:哪个更适合新手推广?
  • 2026年“最稳”的5家央国企:比公务员还香,没人敢说
  • SkillsBench:斯坦福大学等机构揭秘AI代理“技能包“的真实威力
  • 谢彬彬新剧《校服的裙摆》开播,饶雪漫严选校园白月光上线
  • 设计院扎工:2025年全国设计院年终奖汇总(正式版)