信号处理学习笔记1:软件RC一阶高通\低通滤波

今日学习一下 一阶惯性数字低通滤波 一阶惯性数字高通滤波

目录

[为什么叫 "一阶":](#为什么叫 “一阶”:)

适用场景与优势:

初值毛刺的影响与解决:

测试代码贴出:

C语言:

C运行结果:

数据绘图展示(Python):

绘图结果:


为什么叫 "一阶":

因为公式里只用到上一时刻的值,没有更复杂的历史数据。

低通:只依赖 上一次输出

高通:只依赖 上一次输出 + 上一次输入

没有二阶、三阶那种多阶记忆,所以叫 一阶

适用场景与优势:

一阶滤波适用场景:

一阶数字滤波适用于温度、湿度、压力、直流电压、液位变化缓慢、易受高频噪声干扰的物理量采集场景。低通滤波可有效去除采样噪声,使数据平滑稳定;高通滤波可去除信号基线漂移,提取动态变化量。

低通 = 显示当前值(平滑后)

高通 = 只显示变化幅度(变了多少)
优势:

算法简单,计算量小,适合单片机等嵌入式平台实时运行。

稳定性高,不易受数据异常影响(除初始值外)。

对于慢变物理量,一阶滤波即可满足降噪与平滑需求。

实时性好,无明显信号延迟。

初值毛刺的影响与解决:

如果第一个值就是毛刺(极大 / 极小)

低通是:起点错了 → 慢慢修正 前面一大段数据全废

那么低通滤波会从这个错误值开始,慢慢往正确值靠近过程会很慢、很歪,

前面一大段数 据全废。

高通是:起点错了 → 整条路都歪了! 波形基线整体偏移 整条波形报废

高通输出会整体往上飘 / 往下沉,再也回不到 0 基线!

高通滤波会认为:"整个信号的基准就是 100,不是 0"

于是它把所有数据都减去 100最终整条波形整体下沉 / 偏移 基线永远歪了!
解决办法:

方法 1:跳过前 N 个数据(最简单,实验最常用)

方法 2:初始值不用第一个数据,用手动设定值

方法 3:先采样多次求平均,再开始滤波(最稳)用平均值当起点,毛刺就被平均掉了。

测试代码贴出:

C语言:

cpp 复制代码
 #include <stdio.h>


// 滤波参数(alpha 越小,滤波越强)
#define ALPHA 0.05f

/*
    1. 一阶低通滤波(去噪、平滑)
    输入:当前原始数据,上一次滤波结果
    输出:本次滤波后数据

    新值 = 一小部分当前值 + 一大部分上一次的值
    新值 = 0.05 * 当前采样 + 0.95 * 上一次结果
    只相信当前数据 5%,95% 相信过去的稳定值
    低通滤波的目的:去掉噪声,保留趋势
    噪声 = 快速跳变(要去掉)
    真实信号 = 缓慢变化(要保留)
    低通滤波确实会改变数据 作用就是抑制突变、减小剧烈变化
    让数据从 "乱跳" 变成 "平稳顺滑"
*/
float low_pass_filter(float current_data, float last_filtered)
{
    float filtered;
    // 公式:本次输出 = alpha * 当前值 + (1-alpha) * 上一次输出
    filtered = ALPHA * current_data + (1 - ALPHA) * last_filtered;
    return filtered;
}



// ==============================
// 2. 一阶高通滤波(去漂移、提变化)
// 输入:当前原始数据,上一次输入,上一次输出
// 输出:本次滤波后数据
// ==============================
float high_pass_filter(float current_data, float last_data, float last_filtered)
{
    float filtered;
    // 公式:本次输出 = (1-alpha) * (上一次输出 + 当前输入 - 上一次输入)
    filtered = (1 - ALPHA) * (last_filtered + current_data - last_data);
    return filtered;
}


// 测试主函数
int main()
{
    // 模拟一组带漂移+噪声的原始数据(模拟传感器信号)
    float raw_data[] = {10.2, 10.3, 10.8, 10.1, 10.5,
                        11.2, 11.1, 11.6, 11.0, 11.3};

    int data_len = sizeof(raw_data) / sizeof(raw_data[0]);

    // 滤波变量初始化
    float last_low = raw_data[0];  // 低通上一帧结果
    float last_high = 0;           // 高通上一帧结果
    float last_in = raw_data[0];   // 高通上一帧输入

    printf("序号\t原始数据\t低通滤波\t高通滤波\n");
    printf("---------------------------------------------\n");

    for (int i = 0; i < data_len; i++)
    {
        // 低通滤波
        float out_low = low_pass_filter(raw_data[i], last_low);
        last_low = out_low;

        // 高通滤波
        float out_high = high_pass_filter(raw_data[i], last_in, last_high);
        last_in = raw_data[i];
        last_high = out_high;

        // 打印结果
        printf("%d\t%.2f\t\t%.2f\t\t%.2f\n",
               i, raw_data[i], out_low, out_high);
    }

    return 0;
}

C运行结果:

数据绘图展示(Python):

先装库:

cpp 复制代码
pip install matplotlib

再输代码运行:

python 复制代码
import matplotlib.pyplot as plt

# 修复中文显示问题
plt.rcParams["font.family"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS"]
plt.rcParams["axes.unicode_minus"] = False  # 修复负号显示

# C程序原始数据 & 对应滤波结果
x = [0,1,2,3,4,5,6,7,8,9]
raw  = [10.2, 10.3, 10.8, 10.1, 10.5, 11.2, 11.1, 11.6, 11.0, 11.3]
low  = [10.20, 10.21, 10.24, 10.23, 10.25, 10.30, 10.34, 10.40, 10.43, 10.47]
high = [0.00, 0.10, 0.57, -0.14, 0.27, 0.94, 0.85, 1.31, 0.70, 0.97]

plt.figure(figsize=(11,7))

# 1.原始信号
plt.subplot(3,1,1)
plt.plot(x, raw, color="#666666", marker="o", linewidth=2, label="原始传感器数据")
plt.title("原始信号(含波动+缓慢漂移)", fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend()

# 2.低通滤波
plt.subplot(3,1,2)
plt.plot(x, low, color="#0066ff", marker="o", linewidth=2, label="一阶低通滤波(平滑去噪)")
plt.title("低通滤波结果:抑制毛刺、保留缓慢趋势", fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend()

# 3.高通滤波
plt.subplot(3,1,3)
plt.plot(x, high, color="#ff2200", marker="o", linewidth=2, label="一阶高通滤波(提取变化量)")
plt.axhline(y=0, color='black', linestyle='--', alpha=0.5)
plt.title("高通滤波结果:去除基线、只保留信号变化幅度", fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend()

plt.tight_layout()
plt.show()

绘图结果:

相关推荐
寒秋花开曾相惜3 小时前
(学习笔记)第四章 处理器体系结构
linux·网络·数据结构·笔记·学习
低代码布道师5 小时前
微搭低代码MBA 培训管理系统实战 30——学习卡
学习·低代码·rxjava
南無忘码至尊5 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎
LN花开富贵5 小时前
【ROS】鱼香ROS2学习笔记二
linux·笔记·python·学习·嵌入式
檬柠wan5 小时前
MySQL-数据库增删改查学习
数据库·学习·mysql
minglie16 小时前
Zynq 开发中的工程文件管理
学习
炽烈小老头7 小时前
【每天学习一点算法 2026/04/16】逆波兰表达式求值
学习·算法
千寻girling8 小时前
机器学习 | 线性回归 | 尚硅谷学习
学习·机器学习·线性回归
jasonblog8 小时前
对小龙虾openclaw的关注、学习、使用和变化观察
人工智能·学习·ai
Hical_W9 小时前
深入学习CPP17_PMR
c++·学习