文章摘要
这篇文章介绍了两种有意思又好用的小算法:线性归一化和一阶低通滤波器。线性归一化是一种数据预处理方法,主要用于将数据缩放到一个特定范围,常用于嵌入式或其他类型传感器的数据处理。它通过将待测数值映射到一个区间,方便后续处理。线性归一化有正比关系和反比关系两种情况,公式进行了变形以适应不同的反比关系。文章还提供了一个代码演示,展示了如何通过线性归一化计算值对应的百分比,并用于传感器百分比数据转换。 一阶低通滤波器则是一种使用递归方式平滑信号的算法,它能够抑制高频噪声,适合处理连续信号。一阶低通滤波器的计算简单,实时性强,通常用于处理不稳定的信号,使信号变得平滑。平滑因子的设定需要根据实际情况决定,过大会减弱效果,过小会增加输出迟滞性。文章也提供了一个一阶低通滤波器的代码演示,展示了如何对原始信号进行平滑处理。
我认为再简单的算法,只要能解决实际问题,提高解决问题的效率,都是好算法。下面介绍一些有意思又好用的算法,希望对大家有所帮助。
1. 线性归一化
1.1 简介
线性归一化是一种常用的数据预处理方法,主要用于将数据缩放到一个特定的范围,通常是[0, 1]。在嵌入式中常用于ADC或其他类型传感器的数据处理,将获取到的待测数值 映射到[0%, 100%]之间,方便后续处理。
公式1:
公式1中 X':计算得到的归一化百分比结果 X:待测数值 min:标定的最小值 max:标定的最大值
以上公式1待测数值与结果是正比关系,即待测数值越大,结果百分比越大。但实际情况中,呈现反比关系的传感器并不少见,这时需要对公式1进行变形才能得到反比公式。反比关系无非就是计算100%-X',即用100%减去正比的百分比结果,最后得到的就是反比结果,公式变形过程如下:
最终得到公式2:
公式2中 Y':反比的百分比结果
1.2 代码演示
C
#include <stdio.h>
typedef struct {
int min; // 标定值最小值
int max; // 标定值最大值
int adc_value; // adc值
float value_z; // 正比百分比值
float value_f; // 反比百分比值
} PERCENT;
/**
* @brief 通过线性归一化计算ADC值对应的百分比,常用于传感器百分比数据转换
* @param PERCENT PERCENT结构体指针
*/
void percent_computed(PERCENT *percent)
{
// X' = ((X - Xmin) / (Xmax - Xmin)) * 100% // (原公式)
percent->value_z = (float)(percent->adc_value - percent->min) / (percent->max - percent->min) * 100; // (正比)
percent->value_f = (float)(percent->max - percent->adc_value) / (percent->max - percent->min) * 100; // (反比)
}
int main()
{
PERCENT percent = {0};
percent.min = 2000; // 设定标定值最小值
percent.max = 3500; // 设定标定值最大值
percent.adc_value = 2680; // 设定待测值
percent_computed(&percent); // 计算百分比
printf("value_z: %.2f%%\n", percent.value_z); // 输出正比百分比值 value_z: 45.33%
printf("value_f: %.2f%%\n", percent.value_f); // 输出反比百分比值 value_f: 54.67%
return 0;
}
2. 一阶低通
2.1 简介
一阶低通滤波器通常使用递归的方式来平滑信号。其基本形式可以表示为:
其中: y[n] 是当前输出, x[n] 是当前输入, alpha 是平滑因子(0 < alpha < 1),决定了滤波器的响应速度。
特点:
对高频噪声有较好的抑制效果。
适合处理连续信号。
计算简单,实时性强。
该算法通常用来处理不稳定的信号,使信号变得平滑。平滑因子需要根据实际情况设定,不宜过大也不宜过小,过大会导致效果大大减弱,而过小则太过于偏向于上一次输出的值,会增加输出迟滞性。
2.2 代码演示
C
#include <stdio.h>
#define DATA_SIZE 10
int main()
{
int n;
float alpha = 0.6; // 平滑因子
float raw_signal[DATA_SIZE] = {1.1, 1.4, 1.8, 2.6, 2.9, 3.7, 4.1, 4.4, 5.3, 5.5}; // 原始信号数据
float filtered_signal[DATA_SIZE]; // 过滤后信号数据
filtered_signal[0] = raw_signal[0]; // 初始化第一个输出
for (n = 1; n < DATA_SIZE; n++)
{
filtered_signal[n] = alpha * raw_signal[n] + (1 - alpha) * filtered_signal[n - 1];
}
// 输出结果
printf("时间点 | 原始信号 | 过滤后信号\n");
for (n = 0; n < DATA_SIZE; n++)
{
printf("%d | %.2f | %.2f\n", n, raw_signal[n], filtered_signal[n]);
}
return 0;
}
编译,查看输出结果:
BASH
PS E:\project\C_C++\adc> gcc t2.c -o t2; ./t2
时间点 | 原始信号 | 过滤后信号
0 | 1.10 | 1.10
1 | 1.40 | 1.28
2 | 1.80 | 1.59
3 | 2.60 | 2.20
4 | 2.90 | 2.62
5 | 3.70 | 3.27
6 | 4.10 | 3.77
7 | 4.40 | 4.15
8 | 5.30 | 4.84
9 | 5.50 | 5.24
本文是原创文章,采用 CC BY-NC-SA 4.0 协议,完整转载请注明来自 昔枫沐杰
评论
隐私政策
0/500
滚动到此处加载评论...


