滤波算法整理

限幅滤波法

  • 优点:能有效克服因偶然因素引起的脉冲干扰。
  • 缺点:无法抑制周期性干扰,平滑度差。
  • C语言实现
#define A 10
unsigned char Value;
unsigned char AmplitudeLimiterFilter() {
    unsigned char NewValue = GetAD(); // 假设GetAD()是ADC采集函数
    unsigned char ReturnValue;
    if (abs(NewValue - Value) > A)
        ReturnValue = Value;
    else
        ReturnValue = NewValue;
    return ReturnValue;
}

中位值滤波法

  • 优点:能有效克服因偶然因素引起的波动干扰,对温度、液位等变化缓慢的参数有良好滤波效果。
  • 缺点:对流量、速度等快速变化的参数滤波效果较差。
  • C语言实现
#define N 9  // 采样次数,需为奇数
unsigned char ArrDataBuffer[N];
void MiddleValueFilter() {
    unsigned char i, j, temp;
    for (i = 0; i < N; i++) {
        ArrDataBuffer[i] = GetAD();
    }
    for (j = 0; j < N - 1; j++) {
        for (int k = 0; k < N - 1 - j; k++) {
            if (ArrDataBuffer[k] > ArrDataBuffer[k + 1]) {
                temp = ArrDataBuffer[k];
                ArrDataBuffer[k] = ArrDataBuffer[k + 1];
                ArrDataBuffer[k + 1] = temp;
            }
        }
    }
    unsigned char ReturnValue = ArrDataBuffer[(N - 1) / 2];
    // 使用ReturnValue
}

算术平均滤波法

  • 优点:适用于对一般具有随机干扰的信号进行滤波。
  • 缺点:存在滞后,对于要求数据计算速度较快或测量速度较慢的实时控制不适用。
  • C语言实现
#define N 5  // 采样次数
unsigned int sum = 0;
for (int i = 0; i < N; i++) {
    sum += GetAD();
}
unsigned char average = sum / N;
// 使用average

滑动平均滤波法 

  • 优点:对周期性干扰有良好的抑制作用,平滑度高。
  • 缺点:灵敏度低,不易消除脉冲干扰引起的采样值偏差。
  • C语言实现
unsigned int sum = 0; // 用于存储最近N个采样值的总和
unsigned char value_buf[N]; // 存储最近N个采样值的数组

// 假设GetAD()是一个从ADC获取最新采样值的函数
void UpdateFilter() {
    unsigned int new_sum = 0; // 用于计算新的总和
    for (int i = 0; i < N; i++) {
        if (i > 0) {
            sum -= value_buf[i - 1]; // 移除最老的采样值
        }
        value_buf[i] = GetAD(); // 获取并存储最新的采样值
        new_sum += value_buf[i]; // 累加新采样值到总和
    }
    sum = new_sum; // 更新总和
    unsigned char average = sum / N; // 计算新的平均值
    // 使用average,例如将其作为滤波后的输出
}

int main() {
    // 初始化代码,例如初始化ADC等
    while(1) {
        UpdateFilter(); // 定期更新滤波器
        // 其他任务...
    }
    return 0;
}

                可以使用结构体和数组来实现一个固定大小的队列,创建一个固定大小为5的队列,并计算其平均值,新值加入队列时,最老的值会被自动移除。

#include <stdio.h>

#define QUEUE_SIZE 5

// 队列结构体
typedef struct {
    int data[QUEUE_SIZE];
    int front; // 队列头部索引
    int rear;  // 队列尾部索引
} FixedSizeQueue;

// 初始化队列
void initQueue(FixedSizeQueue *q) {
    q->front = 0;
    q->rear = -1;
}

// 检查队列是否已满
int isFull(FixedSizeQueue *q) {
    return (q->rear + 1) % QUEUE_SIZE == q->front;
}

// 检查队列是否为空
int isEmpty(FixedSizeQueue *q) {
    return q->rear == -1;
}

// 入队操作
void enqueue(FixedSizeQueue *q, int value) {
    if (isFull(q)) {
        printf("Queue is full. Cannot add new value.\n");
        return;
    }
    q->rear = (q->rear + 1) % QUEUE_SIZE;
    q->data[q->rear] = value;
}

// 出队操作(移除最老的值)
void dequeue(FixedSizeQueue *q) {
    if (isEmpty(q)) {
        printf("Queue is empty.\n");
        return;
    }
    q->front = (q->front + 1) % QUEUE_SIZE;
}

// 计算队列中的平均值
double calculateAverage(FixedSizeQueue *q) {
    if (isEmpty(q)) {
        return 0;
    }
    int sum = 0;
    int count = 0;
    for (int i = q->front; i != (q->rear + 1) % QUEUE_SIZE; i = (i + 1) % QUEUE_SIZE) {
        sum += q->data[i];
        count++;
    }
    return (double)sum / count;
}

int main() {
    FixedSizeQueue queue;
    initQueue(&queue);

    // 添加一些值到队列
    enqueue(&queue, 10);
    enqueue(&queue, 20);
    enqueue(&queue, 30);
    printf("Current average: %.2f\n", calculateAverage(&queue));

    // 添加新值,最老的值将被移除
    enqueue(&queue, 40);
    printf("New average after adding 40: %.2f\n", calculateAverage(&queue));

    enqueue(&queue, 50);
    printf("New average after adding 50: %.2f\n", calculateAverage(&queue));

    return 0;
}

        定义一个FixedSizeQueue结构体,它包含一个整数数组data来存储队列中的元素,以及两个整数frontrear来分别表示队列的头部和尾部索引。

  initQueue函数用于初始化队列,isFullisEmpty函数用于检查队列是否已满或为空,enqueue函数用于添加新元素到队列,如果队列已满则不添加并打印提示信息,dequeue函数用于从队列中移除最老的元素,calculateAverage函数用于计算队列中所有元素的平均值。

        另一种实现方式,通过一个固定大小的数组来存储最近的五个数值,并在每次添加新值时,如果数组已满,就替换掉最老的值(即数组中的第一个值)。

#include <stdio.h>

#define ARRAY_SIZE 5

// 函数声明
void addValue(int *array, int value, int *index);
double calculateAverage(int *array, int size);

int main() {
    int values[ARRAY_SIZE]; // 存储五个数值的数组
    int index = 0; // 用于记录新值的插入位置
    int i;

    // 初始化数组
    for (i = 0; i < ARRAY_SIZE; i++) {
        values[i] = 0;
    }

    // 添加一些值
    addValue(values, 10, &index);
    addValue(values, 20, &index);
    addValue(values, 30, &index);
    printf("Current average: %.2f\n", calculateAverage(values, ARRAY_SIZE));

    // 添加新值,最老的值将被移除
    addValue(values, 40, &index);
    printf("New average after adding 40: %.2f\n", calculateAverage(values, ARRAY_SIZE));

    addValue(values, 50, &index);
    printf("New average after adding 50: %.2f\n", calculateAverage(values, ARRAY_SIZE));

    return 0;
}

// 添加新值到数组,并更新索引
void addValue(int *array, int value, int *index) {
    array[*index] = value; // 添加新值
    (*index) = (*index + 1) % ARRAY_SIZE; // 更新索引,如果达到数组末尾则回到开头
}

// 计算数组中所有数值的平均值
double calculateAverage(int *array, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += array[i];
    }
    return (double)sum / size;
}

​​​​​​​​​​​​​​使用示例

/**************************.c文件*****************************/
#include "stdint.h"
#include "Filter.h"

Sliding_Mean_Filter Example_Filter = {{0}, 0, 0, 0};

void Sliding_Mean_Filter_Calc(Sliding_Mean_Filter *filter, double Data)
{
	filter->sum -= filter->Filter_Buffer[filter->id];	//减去最旧的数
	filter->sum += Data;								//加进最新的数
	filter->Filter_Buffer[filter->id] = Data;			//将最新的数覆盖最旧的数
	filter->average = filter->sum / Sliding_Mean_Filter_Buffer_Size;	//求均值
	if(++filter->id == Sliding_Mean_Filter_Buffer_Size)
		filter->id = 0;
}




/**************************.h文件*****************************/
#ifndef Filter_H_
#define Filter_H_ 

#define Sliding_Mean_Filter_Buffer_Size 5

typedef struct
{
	double Filter_Buffer[Sliding_Mean_Filter_Buffer_Size];
	uint16_t id;
	double sum;
	double average;
}Sliding_Mean_Filter;

void Sliding_Mean_Filter_Calc(Sliding_Mean_Filter *filter, double Data);

extern Sliding_Mean_Filter Example_Filter;

#endif

一阶滞后滤波法(惯性滤波法) 

  • 优点:适用于波动频繁的被测量滤波,能很好地消除周期性干扰。
  • 缺点:带来了相位滞后,且灵敏度不高。
  • C语言实现
float alpha = 0.1;  // 滤波系数,0 < alpha <= 1
float last_value = 0;  // 上一次滤波结果
float new_value = GetAD();  // 新采样值
float filtered_value = alpha * new_value + (1 - alpha) * last_value;
last_value = filtered_value;  // 更新为下一次使用
// 使用filtered_value

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值