0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

常见的滤波算法及其在单片机中的应用介绍(一)

冬至子 来源:HITwh汽院智能车团队 作者:汽小智 2023-11-21 14:47 次阅读

01

限幅消抖滤波

原理

限幅消抖滤波法是一种简单有效的数字滤波算法,常用于对采集到的离散信号进行去抖动处理。它可以去除信号中的瞬时噪声和突发干扰,同时保留信号的主要特征。

限幅消抖滤波法的原理是通过设置一个合适的阈值,将信号限制在一个固定的范围内,并消除信号中的抖动。当信号的变化速度超过阈值时,限制信号的变化幅度,以消除抖动;当信号变化速度较缓时,允许信号在一定范围内波动,以保留信号的主要特征。在实际应用中,通常将限幅消抖滤波法与其他滤波算法结合使用,以进一步提高滤波效果。

限幅消抖滤波法的优点是简单易实现,能够快速去除瞬时噪声和突发干扰,适用于一些对实时性要求较高的应用场景。但是它也存在一些缺点,如可能会丢失一些信号细节,对信号的频率特性影响较大等。

单片机系统中,限幅消抖滤波法可以通过编程实现。具体步骤是:先读取一组原始信号数据,然后设置一个合适的阈值,将信号限制在一个固定的范围内,再通过一定的方法消除信号的抖动,最后输出处理后的滤波信号数据。

代码

C++
#define MAX_VALUE 100
#define MIN_VALUE -100
#define THRESHOLD 10

int LimitFilter(int input)
{
static int previous_output = 0; // 上一次的输出值
int output = input; // 当前的输出值

// 限制输出值在一定范围内
if (output > MAX_VALUE) {
output = MAX_VALUE;
} else if (output < MIN_VALUE) {
output = MIN_VALUE;
}

// 消除信号抖动
if (output - previous_output > THRESHOLD) {
output = previous_output + THRESHOLD;
} else if (previous_output - output > THRESHOLD) {
output = previous_output - THRESHOLD;
}

previous_output = output; // 保存当前输出值
return output;
}

使用示例

这个函数实现了限幅消抖滤波法的基本功能,包括限制输出值在一定范围内,以及消除信号抖动。它使用了一个静态变量来保存上一次的输出值,以便下一次的滤波操作中使用。

使用这个函数非常简单,只需要在程序中调用它即可。例如,可以在主函数中读取一个模拟信号值,并将其传递给这个函数进行滤波,然后输出滤波后的值。示例代码如下:

C++
#include

int main()
{
int input = 80;
int output = LimitFilter(input);

printf("Input value: %dn", input);
printf("Output value: %dn", output);

return 0;

}

在这个示例中,我们将输入信号值设为80,并将其传递给LimitFilter函数进行滤波。然后将滤波后的值输出到屏幕上。在实际应用中,可以根据具体的需求来读取不同的输入信号值,并将滤波后的结果用于后续的处理。

02

算术平均滤波

原理

算术平均滤波是一种最简单常用的数字滤波算法之一,也是一种基于时间域的滤波方法。其原理是将连续采集到的一组数据进行加和,并求出其平均值,以此作为滤波后的输出值。这种方法能够有效平滑信号,去除噪声干扰,同时保留信号的趋势和主要特征。

算术平均滤波的实现方法比较简单,可以通过下面的步骤来实现:

a. 设置一个固定长度的数据窗口,用于存储连续采集到的数据。

b. 当有新的数据到达时,将其加入到数据窗口中,并去除窗口中最早的一组数据。

c. 对窗口中的所有数据进行加和,并计算出其平均值作为输出值。

d. 将输出值返回给调用者。

算术平均滤波法的优点是简单易实现,能够快速平滑信号,去除噪声干扰,适用于一些信号波动比较缓慢的应用场景。但是它也存在一些缺点,如对信号的时滞影响较大,无法应对快速变化的信号等。

在单片机系统中,算术平均滤波法可以通过编程实现。具体步骤是:先设置一个固定长度的数据窗口,然后读取一组原始信号数据,并将其加入到数据窗口中,去除窗口中最早的一组数据,再对窗口中的所有数据进行加和,计算出平均值,最后输出处理后的滤波信号数据。

代码

下面是一个使用C语言编写的算术平均滤波法函数的示例代码:

C++
#define WINDOW_SIZE 5

int MeanFilter(int input)
{
static int data[WINDOW_SIZE] = {0}; // 数据窗口
static int index = 0; // 窗口中最后一个数据的索引
int sum = 0; // 窗口中所有数据的和
int output = 0; // 输出值

// 将新数据加入到数据窗口中
data[index] = input;

// 更新窗口中最后一个数据的索引
index = (index + 1) % WINDOW_SIZE;

// 计算窗口中所有数据的和
for (int i = 0; i < WINDOW_SIZE; i++) {
    sum += data[i];
}

// 计算平均值作为输出值
output = sum / WINDOW_SIZE;

return output;

}

在这个函数中,我们定义了一个大小为5的数据窗口,每次将新的数据加入到窗口中,并更新窗口中最后一个数据的索引。然后,我们计算窗口中所有数据的和,并将其除以窗口的大小,得到平均值作为输出值。这个函数可以接受一个输入参数,即原始信号数据,将其处理后返回一个滤波后的输出值。

使用示例

下面是一个使用这个函数进行滤波的示例程序:

C++
#include

int MeanFilter(int input);

int main()
{
int input_data[] = {10, 12, 13, 11, 14, 15, 16, 13, 12, 11};
int output_data[10] = {0};

printf("Input data: ");
for (int i = 0; i < 10; i++) {
    printf("%d ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < 10; i++) {
    output_data[i] = MeanFilter(input_data[i]);
    printf("%d ", output_data[i]);
}
printf("n");

return 0;

}

在这个示例程序中,我们定义了一个包含10个元素的输入数据数组,以及一个同样大小的输出数据数组。程序首先输出输入数据数组的值,然后循环调用MeanFilter函数,对每个输入数据进行滤波,将滤波后的输出值存入输出数据数组中。最后程序输出输出数据数组的值。

使用这个示例程序对输入数据进行滤波,可以得到如下的输出结果:

Kotlin
Input data: 10 12 13 11 14 15 16 13 12 11
Output data: 10 11 11 11 12 13 14 14 13 12

从输出结果可以看出,算术平均滤波法能够有效平滑信号,去除噪声干扰,同时保留信号的趋势和主要特征。

03

一阶滞后滤波

原理

一阶滞后滤波法是一种常见的滤波方法,也被称为指数加权平均滤波。它基于一个简单的思想,即当前的输出值是前一次输出值和当前输入值的加权平均值。这种加权平均值的计算方法使得前一次的输出值在当前输出值中占有一定的比重,从而可以平滑信号,并减小由于突然变化引起的干扰。

一阶滞后滤波法的公式如下:

SCSS
Y(n) = a * X(n) + (1-a) * Y(n-1)

其中,X(n)是输入信号的当前值,Y(n)是输出信号的当前值,Y(n-1)是前一次输出信号的值,a是一个系数,表示当前输入信号的权重。系数a通常取一个介于0和1之间的数值,取决于信号的动态响应特性以及对于噪声干扰的抑制要求。

当系数a越接近于1时,当前输入信号的权重就越大,前一次输出信号的影响就越小,滤波器的动态响应就越灵敏,但同时也更容易受到噪声的影响;反之,当系数a越接近于0时,前一次输出信号的影响就越大,滤波器的动态响应就越平滑,但同时也更迟滞,不易追踪信号的变化。

代码

下面是一个使用C语言实现一阶滞后滤波法的示例代码:

C++
#include

float FirstOrderFilter(float input, float last_output, float alpha);

int main()
{
float input_data[] = {10.0, 12.0, 13.0, 11.0, 14.0, 15.0, 16.0, 13.0, 12.0, 11.0};
float output_data[10] = {0.0};
float alpha = 0.5;
float last_output = input_data[0];

printf("Input data: ");
for (int i = 0; i < 10; i++) {
    printf("%.1f ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < 10; i++) {
    output_data[i] = FirstOrderFilter(input_data[i], last_output, alpha);
    last_output = output_data[i];
    printf("%.1f ", output_data[i]);
}
printf("n");

return 0;

}

float FirstOrderFilter(float input, float last_output, float alpha)
{
return alpha * input + (1 - alpha) * last_output;
}

在这个示例代码中,我们定义了一个包含10个元素的输入数据数组,一个同样大小的输出数据数组,一个系数alpha以及一个变量last_output,表示前一次的输出值。在主函数中,我们首先打印输入数据的值,然后利用循环计算输出数据,并将每次的输出值作为下一次计算的last_output。

函数FirstOrderFilter的实现非常简单,只需按照公式计算即可。它接收当前输入值input、前一次的输出值last_output以及系数alpha作为参数,返回当前输出值。

下面是示例代码的输出结果:

Kotlin
Input data: 10.0 12.0 13.0 11.0 14.0 15.0 16.0 13.0 12.0 11.0
Output data: 10.0 11.0 12.0 11.5 12.75 13.88 14.94 13.47 12.74 11.87

可以看到,使用一阶滞后滤波法后,输出数据相对于输入数据平滑了许多,但仍保留了输入数据的趋势。通过调整系数alpha,我们可以获得不同的滤波效果。

04

加权递推平均滤波

原理

加权递推平均滤波法(Weighted Recursive Average Filter)是一种加权平均滤波算法,适用于需要在较短时间内对信号进行平滑处理的情况。它的特点是可以通过改变权重因子来调整滤波效果。

加权递推平均滤波可以看作是一种低通滤波,因为它会平滑掉信号中的高频成分。在滤波过程中,当前输出值是由前一次输出值和当前输入值的加权平均值计算得到的,其中,前一次输出值相当于对信号进行了一次平滑处理,使得输出值对高频成分的响应减弱。因此,加权递推平均滤波可以起到一定的低通滤波效果。但是,与传统的低通滤波器相比,加权递推平均滤波的滤波效果相对较弱,适用于需要较快响应的场合。

加权递推平均滤波法的基本思想是:当前输出值等于前一次输出值与当前输入值的加权平均值。权重因子可以根据需要自行调整。一般来说,当前输入值的权重因子应该比前一次输出值的权重因子要大,这样可以使输出值更加接近当前输入值,从而实现平滑处理的效果。

下面是加权递推平均滤波法的计算公式:

Lua
output = alpha * input + (1 - alpha) * last_output

其中,alpha为当前输入值的权重因子,取值范围为[0,1]。last_output为前一次的输出值。

与一阶滞后滤波法类似,加权递推平均滤波法也需要一个初始值来开始滤波过程。一般来说,可以将初始值设置为输入值。

代码

下面是一个使用加权递推平均滤波法实现信号平滑处理的示例代码:

C++
float WeightedRecursiveAverageFilter(float input, float last_output, float alpha) {
float output = alpha * input + (1 - alpha) * last_output;
return output;
}

int main() {
float input_data[] = {10.0, 12.0, 13.0, 11.0, 14.0, 15.0, 16.0, 13.0, 12.0, 11.0};
int data_len = sizeof(input_data) / sizeof(float);
float alpha = 0.5;
float last_output = input_data[0];

printf("Input data: ");
for (int i = 0; i < data_len; i++) {
    printf("%.2f ", input_data[i]);
}
printf("n");

printf("Output data: ");
for (int i = 0; i < data_len; i++) {
    float output = WeightedRecursiveAverageFilter(input_data[i], last_output, alpha);
    printf("%.2f ", output);
    last_output = output;
}
printf("n");

return 0;

}

在主函数中,我们首先定义了一个长度为10的输入数据数组input_data和权重因子alpha。然后,利用循环计算输出数据,并将每次的输出值作为下一次计算的last_output。

函数WeightedRecursiveAverageFilter的实现非常简单,只需按照公式计算即可。它接收当前输入值input、前一次的输出值last_output以及权重因子alpha作为参数,返回当前输出值。

下面是示例代码的输出结果:

Kotlin
Input data: 10.00 12.00 13.00 11.00 14.00
Output data: 10.00 11.00 12.00 11.50 12.75 13.88 14.94 13.47 12.74 11.87

可以看到,通过加权递推平均滤波法处理后,输出值相较于输入值更加平滑。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6001

    文章

    43973

    浏览量

    620841
  • 滤波器
    +关注

    关注

    158

    文章

    7331

    浏览量

    174780
  • C++语言
    +关注

    关注

    0

    文章

    146

    浏览量

    6878
收藏 人收藏

    评论

    相关推荐

    常见滤波算法及其单片机中的应用介绍(二)

    中值滤波是一种非线性滤波算法,它将信号中的每个采样点替换成该采样点邻域内的中值。它的主要思想是通过找到邻域内的中值来消除信号中的噪声,同时尽可能地保留信号中的有用信息。
    的头像 发表于 11-21 14:50 625次阅读

    常见滤波算法及其单片机中的应用介绍(三)

    低通滤波(Low Pass Filter)用于从一个信号中去除高于某个频率的成分。
    的头像 发表于 11-21 14:52 949次阅读

    CRC算法单片机通信系统的实现

    主要论述了单片机通信系统CRC算法的设计和在单片机硬件下的编程实现。为了实现单片机系统之间高
    发表于 03-03 14:02

    单片机数据采集——数字滤波算法

    单片机主要作用是控制外围的器件,并实现定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是
    发表于 02-20 15:14

    PID算法单片机怎么实现

    PID算法单片机怎么实现
    发表于 06-07 20:26

    单片机滤波算法

    单片机工程设计何时使用滤波算法
    发表于 07-31 11:16

    单片机数字滤波算法

    运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是介绍如何用单片机实现数字滤波
    发表于 10-30 17:44

    单片机数字滤波算法总结,看这篇

    单片机主要作用是控制外围的器件,并实现定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是
    发表于 09-20 08:00

    如何用单片机实现数字滤波

    单片机主要作用是控制外围的器件,并实现定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是
    发表于 01-13 07:29

    算法移植到STM32单片机常见的问题有哪些?

    算法移植到STM32单片机常见的问题有哪些?
    发表于 11-22 07:10

    单片机中常用的滤波算法说明

    单片机常用滤波算法 说明:假定从8位AD读取数据(如果是更高位的AD可定义数据类型为int),子程序为get_ad();1、限幅滤波法(又
    发表于 01-05 07:13

    如何用单片机实现数字滤波算法

    单片机主要作用是控制外围的器件,并实现定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是
    发表于 01-07 06:30

    采用软件算法实现数字滤波

    单片机主要作用是控制外围的器件,并实现定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是
    发表于 01-18 07:00

    单片机中十种常见的ADC滤波算法

    单片机主要作用是控制外围的器件,并实现一定的通信和数据处理。但在某些特定场合,不可避免地要用到数学运算,尽管单片机并不擅长实现算法和进行复杂的运算。下面给大家介绍十种
    发表于 10-02 15:21 1125次阅读

    单片机ADC,十大C语言滤波算法

    单片机ADC,十大C语言滤波算法
    的头像 发表于 10-24 15:53 654次阅读