[经验分享]

一阶低通滤波的C语言实现

[复制链接]
2145|29
手机看帖
扫描二维码
随时随地手机跟帖
olivem55arlowe|  楼主 | 2024-4-29 11:00 | 显示全部楼层 |阅读模式



#include <stdio.h>
#include <string.h>

/*************************** 模拟输入数据 ********************************/
float input_data[251] = {
    0.00, 0.86, 1.59, 2.10, 2.35, 2.35, 2.18, 1.94, 1.76, 1.73, 1.90, 2.26, 2.75,
    3.24, 3.63, 3.80, 3.70, 3.30, 2.68, 1.93, 1.18, 0.54, 0.11, -0.10, -0.11,
    0.00, 0.11, 0.10, -0.11, -0.54, -1.18, -1.93, -2.68, -3.30, -3.70, -3.80,
    -3.63, -3.24, -2.75, -2.26, -1.90, -1.73, -1.76, -1.94, -2.18, -2.35, -2.35,
    -2.10, -1.59, -0.86, 0.00, 0.86, 1.59, 2.10, 2.35, 2.35, 2.18, 1.94, 1.76,
    1.73, 1.90, 2.26, 2.75, 3.24, 3.63, 3.80, 3.70, 3.30, 2.68, 1.93, 1.18,
    0.54, 0.11, -0.10, -0.11, 0.00, 0.11, 0.10, -0.11, -0.54, -1.18, -1.93,
    -2.68, -3.30, -3.70, -3.80, -3.63, -3.24, -2.75, -2.26, -1.90, -1.73,
    -1.76, -1.94, -2.18, -2.35, -2.35, -2.10, -1.59, -0.86, 0.00, 0.86, 1.59,
    2.10, 2.35, 2.35, 2.18, 1.94, 1.76, 1.73, 1.90, 2.26, 2.75, 3.24, 3.63,
    3.80, 3.70, 3.30, 2.68, 1.93, 1.18, 0.54, 0.11, -0.10, -0.11, 0.00, 0.11,
    0.10, -0.11, -0.54, -1.18, -1.93, -2.68, -3.30, -3.70, -3.80, -3.63, -3.24,
    -2.75, -2.26, -1.90, -1.73, -1.76, -1.94, -2.18, -2.35, -2.35, -2.10, -1.59,
    -0.86, 0.00, 0.86, 1.59, 2.10, 2.35, 2.35, 2.18, 1.94, 1.76, 1.73, 1.90, 2.26,
    2.75, 3.24, 3.63, 3.80, 3.70, 3.30, 2.68, 1.93, 1.18, 0.54, 0.11, -0.10, -0.11,
    0.00, 0.11, 0.10, -0.11, -0.54, -1.18, -1.93, -2.68, -3.30, -3.70, -3.80, -3.63,
    -3.24, -2.75, -2.26, -1.90, -1.73, -1.76, -1.94, -2.18, -2.35, -2.35, -2.10, -1.59,
    -0.86, 0.00, 0.86, 1.59, 2.10, 2.35, 2.35, 2.18, 1.94, 1.76, 1.73, 1.90, 2.26, 2.75,
    3.24, 3.63, 3.80, 3.70, 3.30, 2.68, 1.93, 1.18, 0.54, 0.11, -0.10, -0.11, 0.00, 0.11,
    0.10, -0.11, -0.54, -1.18, -1.93, -2.68, -3.30, -3.70, -3.80, -3.63, -3.24, -2.75,
    -2.26, -1.90, -1.73, -1.76, -1.94, -2.18, -2.35, -2.35, -2.10, -1.59, -0.86, 0.00};

float get_data(void)
{
  static int i = 0;
  return (input_data[i++]);
  if (i == 251) //轮回
    i = 0;
}

float fc = 2.0f;     //截止频率
float Ts = 0.02f;    //采样周期
float pi = 3.14159f; //π
float alpha = 0;     //滤波系数

/************************ 滤波器初始化 alpha *****************************/
void low_pass_filter_init(void)
{
  float b = 2.0 * pi * fc * Ts;
  alpha = b / (b + 1);
}

float low_pass_filter(float value)
{
  static float out_last = 0; //上一次滤波值
  float out;

  /***************** 如果第一次进入,则给 out_last 赋值 ******************/
  static char fisrt_flag = 1;
  if (fisrt_flag == 1)
  {
    fisrt_flag = 0;
    out_last = value;
  }

  /*************************** 一阶滤波 *********************************/
  out = out_last + alpha * (value - out_last);
  out_last = out;

  return out;
}

void main(void)
{
  float result[251];

  low_pass_filter_init();
  for (int i = 0; i < 251; i++)
  {
    result[i] = low_pass_filter(get_data());
    printf("%f,", result[i]);
  }
}




使用特权

评论回复
pmp| | 2024-5-1 20:38 | 显示全部楼层
根据截止频率、采样频率和时间常数计算滤波器的系数。对于一阶低通滤波器,通常使用以下公式计算系数:

α = τ / (τ + Δt)
Δt = 1 / 采样频率
其中,α是滤波器的系数,Δt是采样间隔。

使用特权

评论回复
i1mcu| | 2024-5-2 17:00 | 显示全部楼层
如果需要处理大量的数据或者在实时系统中使用,考虑优化算法以提高执行效率。

使用特权

评论回复
zerorobert| | 2024-5-3 11:01 | 显示全部楼层
#include<stdio.h>

float low_pass_filter(float input, float prev_output, float alpha) {
    float output = alpha * input + (1 - alpha) * prev_output;
    return output;
}

int main() {
    float input_signal[] = {/* 输入信号数据 */};
    float alpha = 0.1; // 滤波器系数
    float prev_output = 0; // 初始输出值
    float filtered_signal[sizeof(input_signal) / sizeof(input_signal[0])]; // 存储滤波后的信号

    for (int i = 0; i< sizeof(input_signal) / sizeof(input_signal[0]); i++) {
        prev_output = low_pass_filter(input_signal[i], prev_output, alpha);
        filtered_signal[i] = prev_output;
    }

    // 输出滤波后的信号
    for (int i = 0; i< sizeof(filtered_signal) / sizeof(filtered_signal[0]); i++) {
        printf("%.2f\n", filtered_signal[i]);
    }

    return 0;
}

使用特权

评论回复
pentruman| | 2024-5-6 11:09 | 显示全部楼层
滤波器系数(或称为“alpha”)决定了滤波器的平滑程度:系数越大,平滑度越高,但响应速度越慢;系数越小,响应速度越快,但平滑度降低。

使用特权

评论回复
uptown| | 2024-5-6 13:59 | 显示全部楼层
在计算过程中,要注意避免数值溢出或精度损失,这可能需要使用适当的数据类型和数值范围限制。

使用特权

评论回复
loutin| | 2024-5-6 14:22 | 显示全部楼层
考虑异常情况的处理,比如输入数据的非法值或意外情况

使用特权

评论回复
wwppd| | 2024-5-6 20:24 | 显示全部楼层
为了提高代码的可读性和可维护性,应添加必要的注释来解释代码的功能和重要步骤。

使用特权

评论回复
geraldbetty| | 2024-5-6 21:49 | 显示全部楼层
如果滤波器用于实时系统(如嵌入式系统或音频处理),则需要确保滤波器算法的执行时间足够短,以避免延迟或性能问题。

使用特权

评论回复
hudi008| | 2024-5-7 14:23 | 显示全部楼层
根据所需的截止频率和采样率来设定滤波器的系数。这些系数决定了滤波器的性能,如截止频率和阻带衰减。

使用特权

评论回复
robertesth| | 2024-5-7 19:03 | 显示全部楼层
对于一阶低通滤波器,通常需要将前一个输出值(即previous_output)设置为初始输入值或某个合理的起始值。

使用特权

评论回复
mmbs| | 2024-5-7 20:26 | 显示全部楼层
在实现一阶低通滤波器后,进行充分的测试和验证,以确保滤波器的性能和稳定性。可以使用示波器、频谱分析仪等工具分析滤波器的输出信号,以评估其性能和可靠性。

使用特权

评论回复
weifeng90| | 2024-5-7 21:22 | 显示全部楼层
这个在模拟信号采集滤波中常用

使用特权

评论回复
burgessmaggie| | 2024-5-7 22:27 | 显示全部楼层
#include <stdio.h>

// 一阶低通滤波函数
float lowPassFilter(float alpha, float x, float y_prev) {
    return alpha * x + (1 - alpha) * y_prev;
}

int main() {
    float alpha = 0.5;  // 滤波系数
    float x[5] = {1, 2, 3, 4, 5};  // 原始信号
    float y[5];  // 滤波后的信号

    // 设定初始值
    y[0] = x[0];

    // 进行滤波
    for (int i = 1; i < 5; i++) {
        y[i] = lowPassFilter(alpha, x[i], y[i-1]);
    }

    // 打印滤波后的信号
    printf("Filtered signal: ");
    for (int i = 0; i < 5; i++) {
        printf("%f ", y[i]);
    }
    printf("\n");

    return 0;
}

使用特权

评论回复
kmzuaz| | 2024-5-8 14:16 | 显示全部楼层
数据类型:选择适当的数据类型来存储滤波器的系数和输入信号。浮点数(float或double)通常用于滤波器设计,但在嵌入式系统中可能需要考虑精度和存储空间的权衡。
滤波器初始化:在C语言实现时,需要初始化滤波器的状态变量(如果是IIR滤波器的话)。
滤波器更新:在每次循环中更新滤波器的输入和输出。注意计算的顺序和精度问题。
溢出处理:在进行浮点运算时要特别注意溢出的情况,特别是在使用定点运算的嵌入式系统中。
量化误差:考虑量化误差对滤波器性能的影响,特别是在使用有限精度的硬件或软件实现时。

使用特权

评论回复
youtome| | 2024-5-8 19:46 | 显示全部楼层
如果使用定点数实现,需要注意溢出问题。可以通过缩放、截断或饱和来处理溢出。

使用特权

评论回复
primojones| | 2024-5-8 20:39 | 显示全部楼层
在滤波过程中,需要处理第一个采样值和最后一个采样值。对于第一个采样值,可以直接使用x[0]作为y[0];对于最后一个采样值,可以根据需要决定是否进行滤波。

使用特权

评论回复
mmbs| | 2024-5-8 22:58 | 显示全部楼层
根据应用需求选择合适的截止频率(3dB增益点)和时间常数(τ)。截止频率决定了滤波器对高频信号的抑制程度,而时间常数决定了滤波器的响应速度。

使用特权

评论回复
minzisc| | 2024-5-9 18:07 | 显示全部楼层
#include <stdio.h>  
  
typedef struct {  
    float alpha;  
    float previous_output;  
} LowPassFilter;  
  
float low_pass_filter(LowPassFilter *filter, float input) {  
    float output = filter->alpha * input + (1.0f - filter->alpha) * filter->previous_output;  
    filter->previous_output = output;  
    return output;  
}  
  
int main() {  
    LowPassFilter filter = {0.1f, 0.0f}; // 假设alpha为0.1,初始输出为0  
    float input_values[] = {1.0f, 2.0f, 3.0f, 2.0f, 1.0f};  
    int num_values = sizeof(input_values) / sizeof(input_values[0]);  
  
    for (int i = 0; i < num_values; i++) {  
        float output = low_pass_filter(&filter, input_values[i]);  
        printf("Input: %f, Output: %f\n", input_values[i], output);  
    }  
  
    return 0;  
}

使用特权

评论回复
usysm| | 2024-5-9 21:45 | 显示全部楼层
一阶低通滤波的核心是一个简单的公式:y[n] = α * x[n] + (1 - α) * y[n-1],其中α是滤波系数,x[n]是当前采样值,y[n]是滤波后的值,y[n-1]是上一次滤波后的值。α的选择会影响滤波的效果,一般来说,α越大,滤波效果越弱,信号变化越快;α越小,滤波效果越强,信号变化越慢。通常,α的取值范围在0到1之间。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

1149

帖子

0

粉丝