在ADC(模数转换器)采集过程中,信号往往会受到噪声和干扰的影响。为了提高信号的质量,滤波是必不可少的处理步骤。本文将介绍几种常见的滤波算法及其实现方法,帮助工程师们在嵌入式系统中有效处理数据,改善采集效果。
目录
在实际的ADC数据采集过程中,原始信号通常会受到噪声、干扰或传感器不稳定性的影响。为了提取出更为稳定和准确的信号结果,应用合适的滤波算法成为了关键。滤波的目的在于消除高频噪声、平滑数据或去除异常值,从而得到更接近真实的信号。
这些滤波算法不仅可以帮助有效处理噪声数据,还能在不丢失有效信息的前提下保持信号的平滑和稳定性。
零、卡尔曼滤波算法
卡尔曼滤波是一种基于线性系统的递推估计算法,广泛应用于信号处理、控制系统、导航和金融等领域。它通过使用动态系统模型和噪声模型,逐步估计出系统的真实状态,并且能够最小化噪声和不确定性对系统的影响。
算法原理:参考
参数解释
P:状态估计误差协方差,反映了估计的不确定性。P_:预测误差协方差。X:当前状态的估计值。X_:预测的状态值。K:卡尔曼增益,用于平衡预测值和测量值的权重。Q:过程噪声协方差,代表系统动态变化的随机性。R:测量噪声协方差,表示测量数据的噪声水平。Z:传感器的当前测量值。
优点
- 动态响应快:卡尔曼滤波能够在有噪声的环境下快速收敛到真实值,适合处理实时信号。
- 最优估计:在已知系统噪声和测量噪声的前提下,卡尔曼滤波可以提供最优的线性状态估计。
- 适应性强:可以有效应对系统的突发变化,能够在不同噪声条件下动态调整估计结果。
缺点
- 模型依赖:卡尔曼滤波器的性能依赖于准确的系统模型和噪声模型,若这些参数设定不准,滤波效果将大大降低。
- 非线性问题:传统卡尔曼滤波只适用于线性系统,若系统是非线性的,需要使用扩展卡尔曼滤波(EKF)或无迹卡尔曼滤波(UKF)。
- 计算复杂度:虽然计算量不大,但在多维空间的状态估计中,卡尔曼滤波的矩阵运算复杂度可能会增加。
-
/***************************************** 卡尔曼滤波算法 参数解释 P:状态估计误差协方差,反映了估计的不确定性。 P_:预测误差协方差。 X:当前状态的估计值。 X_:预测的状态值。 K:卡尔曼增益,用于平衡预测值和测量值的权重。 Q:过程噪声协方差,代表系统动态变化的随机性。 R:测量噪声协方差,表示测量数据的噪声水平。 Z:传感器的当前测量值。 ******************************************/ float P = 1, P_, X = 0, X_, K = 0, Q = 0.01, R = 0.5; // 卡尔曼滤波参数 float Kalman_Filter(float Z) { X_ = X; // 预测状态:将上一状态作为预测的初始值 P_ = P + Q; // 预测误差协方差:加上过程噪声Q // 计算卡尔曼增益K:当前预测误差协方差除以测量误差协方差与预测误差协方差的和 K = P_ / (P_ + R); // 更新状态:预测状态加上卡尔曼增益乘以测量值与预测状态的差 X = X_ + K * (Z - X_); // 更新误差协方差:(1 - K)乘以预测误差协方差 P = (1 - K) * P_; return X; // 返回估计值 }
一、算数平均滤波
算数平均滤波通过对一定次数的输入数据进行采样,将这些数据的平均值作为输出。它的优点是能有效减少噪声干扰,但对突变的异常值反应较慢。
在算数平均滤波中,系统会连续采样N次,然后将这些采样值相加,再除以N得到平均值。这个平均值被用作滤波后的输出结果。
- 当N较大时,平滑度较高,滤波效果好,能有效减小噪声干扰,但同时灵敏度降低,对信号变化的反应会较慢。
- 当N较小时,灵敏度较高,系统对输入信号的变化反应更快,但平滑效果较差,可能无法有效地滤除噪声。
通常情况下,N=12 是一个比较常用的设定值,能够在平滑度和灵敏度之间取得较好的平衡。
优点
- 适用于存在随机干扰的系统:算数平均滤波对随机噪声的抑制效果非常好,因此非常适合处理有随机干扰的系统,如温度、湿度等传感器数据。
- 平滑性好:通过增加N值,可以提高平滑性,能够有效地消除高频噪声,使输出信号更加稳定。
- 实现简单:该算法逻辑非常简单,容易实现和理解,计算只是简单的加法和除法。
缺点
- 占用RAM多:由于需要存储N次采样的数据,占用一定的内存资源,N值越大,占用的RAM越多。这在资源有限的嵌入式系统中可能是一个问题。
- 计算速度慢:如果N值较大,计算平均值的速度较慢,特别是对于需要快速响应的系统,这种滤波方法可能不太适用。
- 灵敏度较低:当N值较大时,虽然滤波效果好,但系统对输入信号的变化反应较慢,导致灵敏度降低,不能快速捕捉到信号的突变。
- 无法去除突变异常值:算数平均滤波对异常值没有特殊的处理,容易受到极端数据点的影响,导致输出结果偏离真实值。
/*****************************************
算数平均滤波
******************************************/
u16 Get_Adc_Average(u8 ch, u8 times) {
u32 temp_val = 0;
for(u8 t = 0; t < times; t++) {
temp_val += get_ad(ch); // 累加ADC采样值
delay_ms(5); // 采样间隔
}
return temp_val / times; // 返回平均值
}
二、递推平均滤波
递推平均滤波是一种通过不断更新的方式计算平均值的滤波方法。它与算数平均滤波的不同在于,每次新的采样数据进入时,仅更新当前的平均值,而不需要重新累加所有的采样值。这使得它能够在连续数据流中以较低的计算成本实时进行滤波。
在递推平均滤波中,新的采样值加入时,将它与之前的滤波结果进行加权平均,旧的采样数据逐渐淡出,从而得到平滑的输出。
优点
- 内存占用少:与算数平均滤波相比,递推平均滤波不需要存储所有的历史采样值,仅需保留当前的滤波结果和新采样值,因此占用内存较少,非常适合嵌入式系统和低资源环境。
- 计算速度快:因为递推平均滤波只需更新平均值而无需对所有数据重新求和,计算速度快,适合对实时性要求较高的系统。
- 实现简单:算法逻辑简单,仅需使用上一次的平均值和当前采样值进行计算,易于实现。
- 适合长期稳定信号:递推平均滤波在处理长期稳定的信号时表现较好,能够消除较小幅度的随机干扰。
缺点
- 灵敏度较低:与算数平均滤波类似,递推平均滤波的灵敏度受历史数据的影响较大,对信号的突变响应较慢。如果信号发生快速变化,滤波后的输出无法迅速反映这种变化。
- 对异常值敏感:递推平均滤波对突发的异常值同样没有特别的处理机制,因此极端的采样值会影响滤波结果,导致瞬时偏差。
- 平滑性受限:由于递推平均滤波在每次更新时只使用最新的采样数据,平滑效果不如算数平均滤波好,尤其在对高频噪声的抑制上效果有限。
/*****************************************
递推平均滤波
// ch - ADC通道号
// Value - 上一次滤波后的值
// Recursive_average_filterA - 限幅范围
// 返回值:滤波后的新的值
******************************************/
float Recursive_average_filter(int ch, float Value, int Recursive_average_filterA)
{
float new_Value = get_ad(ch); // 获取当前采样值
if(fabs(new_Value - Value) > Recursive_average_filterA) // 判断是否超过限幅范围
// 如果当前采样值与上一次滤波后的值之差的绝对值大于限幅范围
return Value; // 则返回上一次的滤波值,不更新滤波结果
return new_Value; // 如果没有超过限幅范围,则返回滤波后的值
}
三、中位值平均滤波
中位值平均滤波是一种通过对多次采样数据进行排序,然后取中间值或去除极端值后的平均值来作为输出的滤波方法。与算数平均滤波不同,它更加侧重于去除异常的极端数据,因此在面对突发异常值时具有更好的鲁棒性。
在中位值平均滤波中,系统会对N次采样数据进行排序,取出中间值,或者去掉最大值和最小值后计算剩余数据的平均值,这使得它能有效滤除突变的异常值,得到更加稳定的输出。
优点
- 抗干扰能力强:中位值平均滤波对异常值具有很强的抑制作用,能够有效地滤除突发的极端数据,使输出结果不受单个极端值的影响。这使得它在应对传感器噪声尖峰等突发干扰时表现优异。
- 适用于非高斯噪声:与算数平均滤波主要处理高斯噪声不同,中位值平均滤波适用于含有非高斯噪声的系统,尤其是在数据中存在显著的突发异常值时,它能提供更加稳定的输出。
- 平滑效果较好:去除极端值后的平均值能够有效减少噪声干扰,使得输出信号更加平滑。
- 实现简单:虽然涉及到排序操作,但算法整体上仍然相对简单,容易在大多数系统中实现。
缺点
- 计算复杂度高:中位值平均滤波需要对N个采样值进行排序,当N值较大时,排序过程会增加计算复杂度,特别是在对实时性要求较高的系统中,这可能成为一个瓶颈。
- 延迟问题:由于中位值平均滤波需要对一批采样值进行操作,滤波后的结果相对于当前输入数据会有一定的延迟,尤其是在采样次数较多的情况下,这种延迟会更加明显。
- 对大噪声成分敏感:虽然能去除单个极端值,但如果噪声较多且集中在采样数据中间位置,中位值平均滤波可能无法完全去除这些噪声,从而导致输出结果偏差较大。
- 占用内存多:与算数平均滤波类似,中位值平均滤波也需要存储多个采样数据,内存消耗较大,尤其在N值较大时,这对内存有限的系统可能不太适用。
/*****************************************
中位值平均滤波
// ch - ADC通道号
// N - 采样值的数量
// 返回值:滤波后的中位平均值
******************************************/
float Median_average_filter(int ch, int N)
{
float Value_buf[N]; // 创建一个数组,用于存储采样值
float sum = 0; // 初始化总和为0
// 获取N个采样值
for(int count = 0; count < N; count++) {
Value_buf[count] = get_ad(ch);
}
// 冒泡排序
// 对采样值进行排序,以便于找到中位数
for(int j = 0; j < N - 1; j++) {
for(int i = 0; i < N - j - 1; i++) {
if(Value_buf[i] > Value_buf[i + 1]) {
float temp = Value_buf[i];
Value_buf[i] = Value_buf[i + 1];
Value_buf[i + 1] = temp;
}
}
}
// 去掉最大最小值,计算中间值的平均
// 遍历排序后的数组,跳过最大和最小的值,累加中间的值
for(int count = 1; count < N - 1; count++) {
sum += Value_buf[count];
}
// 返回中位平均值,即中间值的平均数
return sum / (N - 2);
}
四、限幅平均滤波
限幅平均滤波是一种通过设置上下限范围,去除超过限幅范围的异常值,从而在剩余有效数据中进行算术平均的滤波方法。该方法通过丢弃突变值来保证输出的平滑性和稳定性,适用于含有突发噪声或异常干扰的系统。
在限幅平均滤波中,系统会连续采样N次,每次采样的值与前一次滤波值进行比较。如果采样值与前一值的差异超出设定的限幅范围,则认为该值是异常值,不参与平均计算。如果在范围内,则加入到有效数据中并用于计算新的平均值。
优点
- 能有效去除异常数据:通过设置上下限幅度,限幅平均滤波可以有效地去除那些超出正常波动范围的异常数据,避免它们对滤波结果的影响。
- 平滑性较好:与算数平均滤波相比,限幅平均滤波在减少异常值的影响的同时,仍然能提供较好的平滑效果,适合对数据进行细化处理。
- 实现简单:该算法基于简单的限幅判断和算术平均计算,逻辑简单,易于实现和理解。
- 适应性强:通过调整限幅值,可以在平滑度和灵敏度之间进行调节,适应不同的应用场景。
缺点
- 需要合理设置限幅范围:限幅值的设定至关重要。如果限幅范围设置过小,可能会误判正常数据为异常值,导致有效数据被忽略;如果限幅范围设置过大,异常值仍然可能影响滤波效果。
- 对连续变化的信号不敏感:当输入信号存在较大的变化时,限幅平均滤波可能会误将这些正常变化认为是异常值,从而忽略掉,导致输出结果与实际信号不符。
- 占用RAM资源:与算数平均滤波类似,该算法需要存储N次采样的数据,因此占用一定的内存资源,尤其当N值较大时,这对内存有限的系统会产生影响。
- 计算复杂度增加:相对于普通的算数平均滤波,限幅平均滤波在每次采样时还需要进行限幅判断,因此计算复杂度略有增加。
/*****************************************
限幅平均滤波
// N - 采样值的数量,即要采集多少个数据点来进行滤波
// value - 上一次滤波后的值
// Limit_Average_FilterA - 限幅范围
// 返回值:滤波后的新的值
******************************************/
float Limit_Average_Filter(int N,float value,float Limit_Average_FilterA)
{
float new_value = get_ad(0); // 获取当前采样值
float sum = 0; // 初始化总和为0
int i = 0; // 初始化索引为0
float value_buf[N]; // 创建一个数组,用于存储采样值
// 限幅判断
if(fabs(new_value - value) < Limit_Average_FilterA) {
value_buf[i++] = new_value; // 如果新采样值在限幅范围内,则存入缓冲区
}
if(i == N) i = 0; // 如果索引达到数组长度,则回到0,实现循环队列
// 计算平均值
for(int count = 0; count < N; count++) {
sum += value_buf[count]; // 累加缓冲区中的所有值
}
return sum / N; // 返回滤波后的平均值
}
五、指数加权移动平均滤波(EWMA)
指数加权移动平均滤波(EWMA),是一种通过平滑当前输入信号和历史输出信号来减少噪声影响的滤波方法。它使用一个滞后系数来控制当前采样值和前一次滤波结果的权重,从而实现信号的平滑。
该方法特别适合处理具有较小波动的信号,通过减少高频噪声,使得输出更加平滑、稳定。滤波公式如下:
输出=α×当前采样值+(1−α)×上次输出值
其中,α\alphaα 是一个滞后系数,范围为 0 到 1。它决定了滤波器对当前输入和历史输出的权重分配。 α\alphaα 越大,当前采样值的权重越高,系统的灵敏度也越高;α\alphaα 越小,历史输出的权重越高,滤波效果更好。
优点
- 平滑性强:一阶滞后滤波通过引入历史数据进行平滑,能很好地减少高频噪声干扰,适合处理稳定的信号。
- 计算简单:算法只需要简单的加权求和,计算速度快,占用的资源少,非常适合嵌入式系统等实时性要求较高的场合。
- 适应性强:可以通过调整滞后系数 α\alphaα,灵活调整系统的灵敏度和抗噪能力,适应不同的应用场景。
缺点
- 滞后效应明显:由于滤波器对历史输出值的依赖较强,它会引入滞后,导致系统对快速变化的信号反应较慢。当 α\alphaα 较小时,信号变化滞后更为明显。
- 无法完全去除突发异常值:一阶滞后滤波主要针对高频噪声,对于突发的大幅度异常值,它只能部分平滑,无法彻底滤除这些异常。
- 适合平稳信号:如果信号变化较剧烈,该滤波方法可能无法快速追踪信号的变化,导致滤波后的信号不够准确。
应用场景
- 温度和湿度传感:温度、湿度等环境监测通常变化缓慢,但容易受到随机噪声影响。一阶滞后滤波能有效平滑这些信号,提供更加稳定的测量数据。
- 电压和电流监控:在电压和电流的实时监控中,一阶滞后滤波可以用来平滑因噪声和电磁干扰导致的短时波动,确保系统的稳定性。
- 运动传感器数据:在惯性测量单元(IMU)或加速度传感器中,该滤波方法能够平滑快速变化的加速度或角速度数据,减少小幅度的波动对测量精度的影响。
参数调整
滞后系数 α\alphaα 是影响一阶滞后滤波效果的关键参数:
- 当 α\alphaα 较大时,滤波器对当前输入的反应更加灵敏,系统能够更快地跟踪输入信号的变化,但抗噪能力下降,平滑效果较差。
- 当 α\alphaα 较小时,历史输出的权重增加,滤波效果更好,能更有效地消除噪声,但系统对输入信号的变化反应较慢。
α\alphaα 的典型值一般在 0.1 到 0.3 之间,这能在平滑性和响应速度之间取得较好的平衡。
/*****************************************
指数加权移动平均滤波(EWMA)
// current_value: 当前采样值
// previous_value: 上一次滤波值
// alpha: 加权系数(0~1)
******************************************/
float EWMA_Filter(float current_value, float previous_value, float alpha) {
return alpha * current_value + (1 - alpha) * previous_value;
}
六、一阶滞后滤波
一阶滞后滤波是一种常用的平滑算法,它根据当前值和历史值的权重比例,递推计算出平滑后的输出。其核心思想是通过对当前输入和之前的滤波结果进行加权平均来减少信号中的高频波动。
在一阶滞后滤波中,系统会给当前的采样值 new_value 和上一次的滤波结果 value 分配不同的权重,权重的大小由参数 α 决定,通常取值范围在 0 到 1 之间。计算公式如下:
output=(1−α)×previous value+α×current value
其中,α 越大,滤波结果对当前值的响应越敏感;α 越小,滤波结果越平滑,更依赖于历史值。
优点
- 适用于低频信号滤波:一阶滞后滤波能够有效抑制高频噪声,特别适合对温度、湿度、压力等低频信号进行平滑处理。
- 占用资源少:一阶滞后滤波仅需要保存一个历史滤波值,内存占用极小,非常适合资源有限的嵌入式系统。
- 平滑度和灵敏度可调:通过调整权重系数
α,可以在平滑度和系统的灵敏度之间取得平衡。例如,在需要更平滑的输出时,可以选择较小的α值;而在需要快速响应时,选择较大的α值。
缺点
- 对突变信号反应慢:由于是递推滤波方式,系统在面对信号突变时响应较慢,不能快速捕捉到信号的剧烈变化。
- 滤波效果依赖于
α的选择:如果α的取值不合理,可能会导致滤波效果不佳。例如,α值过大可能导致滤波效果不足,而α值过小会导致信号滞后。
适用场景
- 平滑噪声较多的信号:适合用于处理噪声较多但信号变化相对平稳的系统,如温度传感器、气压传感器等。
- 资源受限的系统:一阶滞后滤波对内存和计算资源的需求较少,非常适合嵌入式系统。
/*****************************************
一阶滞后滤波
// 函数声明:Exponential_Smoothing_Filter
// 参数:
// ch - ADC通道号
// Exponential_Smoothing_Filtera - 滤波系数,范围在0到100之间
******************************************/
float Exponential_Smoothing_Filter(int ch, int Exponential_Smoothing_Filtera)
{
float new_value = get_ad(ch); // 获取当前采样值
static float value = 0; // 静态变量,用于保持上一次的滤波值
return ((100 - Exponential_Smoothing_Filtera) * value + Exponential_Smoothing_Filtera * new_value) / 100; // 滤波计算
}
七、加权递推平均滤波
加权递推平均滤波是一种对输入信号进行加权平均的滤波方法,相比于简单的算术平均滤波,它为每一个采样点分配不同的权重,通常最近的采样值权重较大,历史采样值的权重较小,从而增强对当前信号变化的响应能力。
在这种滤波方法中,系统会连续采样 N 次,并且为每个采样值分配一个相应的权重 coe。滤波后的输出值是所有采样值与其权重的乘积之和,再除以权重总和 sum_coe,即加权平均值。
算法原理
- 首先,系统采集
N个采样点并存储在缓冲区中。 - 每个采样点与其对应的权重相乘,并将这些乘积相加得到一个加权和。
- 最后,将加权和除以权重的总和
sum_coe,得到加权后的滤波结果。
优点
- 对近期数据更加敏感:通过对不同的采样值分配不同的权重,能够使系统对较新的数据更加敏感,从而提高对突变信号的反应速度。
- 滤波效果可控:可以根据需要调整权重的分布,从而在平滑度和灵敏度之间取得更好的平衡。例如,可以让最近的采样值占较大的权重,历史采样值占较小的权重。
- 适用于趋势检测:加权递推平均滤波对信号趋势的检测较为有效,特别是在需要对信号趋势做出响应的场景。
缺点
- 计算复杂度较高:与普通的算术平均滤波相比,加权递推平均滤波需要进行多次乘法运算,增加了系统的计算复杂度。
- 权重选择复杂:权重的选择直接影响滤波效果,选择不当可能会导致滤波效果欠佳。例如,权重分布不合理可能会使系统反应过慢或过于敏感。
- 占用更多存储资源:为了保存权重和多个采样值,需要占用较多的存储空间,尤其在
N较大时,占用的RAM会较多。
/*****************************************
加权递推平均滤波
// ch - ADC通道号
// N - 采样值的数量,即要采集多少个数据点来进行滤波
// coe - 指向权重数组的指针,数组中每个元素代表对应采样值的权重
// sum_coe - 权重数组元素的总和
// 返回值:滤波后的加权平均值
******************************************/
float Weighted_Moving_Average_Filter(int ch, int N,float *coe,float sum_coe)
{
float value_buf[N]; // 创建一个数组,用于存储采样值
float sum = 0; // 初始化总和为0
// 获取N个采样值
for(int count = 0; count < N; count++) {
value_buf[count] = get_ad(ch);
}
// 加权平均计算
// 遍历采样值数组,将每个采样值乘以其对应的权重,然后累加
for(int count = 0; count < N; count++) {
sum += value_buf[count] * coe[count];
}
// 返回加权平均值,即累加的总和除以权重的总和
return sum / sum_coe;
}
八、消抖滤波
消抖滤波是一种专门用于处理开关或按钮等设备在状态变化时产生的噪声和抖动现象的滤波技术。设备在切换状态时,可能会因机械接触不良等原因产生瞬时的高频噪声,从而导致错误的状态读取。消抖滤波的目的是通过设置稳定状态的条件来消除这些瞬时波动。
算法原理
- 输入读取:首先,系统读取指定通道的输入值
new_value。 - 比较与计数:当新的输入值与之前的值
value不同时,系统会开始计数。 - 稳定性检查:如果新读取的值与旧值不同,计数器
count会增加。若计数器的值达到设定的阈值N,则认为新值是稳定的,返回这个新值。 - 返回旧值:如果在计数过程中,输入值再次变化,则会重置计数器,继续检测稳定状态,直到满足条件。
优点
- 消除抖动:有效减少开关或按钮在切换时产生的抖动,确保读取到的状态是稳定的。
- 提高可靠性:在电子设备的控制中,确保状态切换的准确性,从而提高系统的整体可靠性。
- 简单实现:算法逻辑简单,易于实现和理解。
缺点
- 响应延迟:由于需要等待
N次稳定读取,可能会导致系统对状态变化的响应延迟。在需要快速反应的应用中,这可能成为一个问题。 - 参数调整:参数
N的选择需要根据具体应用进行调整,选择不当可能会导致无法及时响应有效信号。 - 计算资源消耗:在某些情况下,尤其是在需要频繁检测状态的应用中,可能会增加计算资源的消耗。
/*****************************************
消抖滤波
// ch - ADC通道号
// value - 上一次的稳定值
// N - 最大允许的抖动次数
// 返回值:滤波后的稳定值
******************************************/
float Debounce_Filter(int ch, float value, int N)
{
float count = 0, new_value; // 初始化计数器和新的采样值
new_value = get_ad(ch); // 获取当前采样值
// 检查当前采样值是否与上一次的稳定值不同
while(value != new_value) {
count++; // 抖动次数加一
if(count >= N) return new_value; // 如果抖动次数达到N,则认为新的采样值是稳定的
new_value = get_ad(ch); // 再次获取当前采样值
}
return value; // 如果在N次内采样值没有变化,则返回上一次的稳定值
}
九、自适应滤波
自适应滤波是一种根据输入信号的特性动态调整滤波参数的滤波技术。其主要目的是在不断变化的环境中优化信号的处理效果,适应不同的噪声水平和信号变化,提供最佳的输出结果。
算法原理
- 输入信号:函数接收当前值
current_value和上一个值previous_value,用于计算自适应权重。 - 噪声检测:通过计算当前值与上一个值之间的差异
diff,判断信号的变化程度。如果这个差异大于设定的噪声阈值noise_threshold,则认为信号变化较快,需要提高灵敏度。 - 动态调整:根据差异的大小动态调整权重系数
alpha:- 当
diff大于noise_threshold时,设置较高的灵敏度(alpha = 0.8)。 - 当
diff小于或等于noise_threshold时,设置较高的平滑度(alpha = 0.2)。
- 当
- 输出计算:使用动态调整的权重系数计算滤波后的输出值。
优点
- 动态适应性:能够根据输入信号的特性实时调整滤波参数,适应不同的环境和信号变化,提高处理效果。
- 提高灵敏度与平滑性:在信号变化剧烈时,保持较高的灵敏度;在信号稳定时,提高平滑性,减少噪声影响。
- 应用广泛:适用于各种需要实时信号处理的场合,如音频信号处理、通信系统和控制系统等。
缺点
- 复杂度较高:相比于传统滤波器,自适应滤波的实现相对复杂,增加了计算和资源消耗。
- 参数调节难度:噪声阈值
noise_threshold和alpha的设定需要根据具体应用场景进行调节,选择不当可能影响滤波效果。 - 响应时间:在快速变化的环境中,可能需要一定时间来适应新的信号特性,导致初始反应速度较慢。
/*****************************************
自适应滤波(Adaptive Filter)
// current_value: 当前采样值
// previous_value: 上一次滤波值
// alpha: 指向加权系数的指针,根据噪声情况自动调整
******************************************/
float AdaptiveFilter(float current_value, float previous_value, float *alpha)
{
// 设定噪声的阈值,用于动态调整alpha
float noise_threshold = 0.5;
float diff = fabs(current_value - previous_value);
// 如果当前值和前一值的差异大于噪声阈值,则设置alpha为高灵敏度值
if (diff > noise_threshold)
*alpha = 0.8; // 高灵敏度
else
// 否则,设置alpha为高平滑度值
*alpha = 0.2; // 高平滑度
// 返回滤波后的值,根据alpha值加权当前值和前一值
return (*alpha) * current_value + (1 - (*alpha)) * previous_value;
}
十、巴特沃斯低通滤波器
巴特沃斯低通滤波器是一种常用的信号处理工具,旨在允许低频信号通过,同时抑制高频信号。其设计目标是实现一个平滑的频率响应,避免频率响应中的尖峰或波动,确保信号的平稳输出。
算法原理
- 输入信号:函数接收当前值
current_value和历史值数组history,用于计算新的滤波输出。 - 滤波计算:使用巴特沃斯滤波器的转移函数,对输入信号进行加权和差分计算,具体公式如下: new_value=b[0]⋅current_value+b[1]⋅history[0]+b[2]⋅history[1]−a[1]⋅history[2]−a[2]⋅history[3]其中,
b_coeff是前向系数,a_coeff是反馈系数。 - 历史值更新:在计算新值后,更新历史值数组
history,以便在下次滤波时使用:- 将
history[0]更新为current_value。 - 将
history[1]更新为history[0]。 - 将
history[2]更新为new_value。 - 将
history[3]更新为history[2]。
- 将
优点
- 平滑频率响应:巴特沃斯滤波器提供非常平滑的频率响应,没有明显的波动,使其在信号处理中的应用非常广泛。
- 良好的衰减特性:有效抑制高频噪声,能够很好地平衡信号的完整性和噪声的抑制。
- 多阶设计:可以通过调整滤波器的阶数(例如,二阶、四阶等)来改变滤波器的特性,满足不同应用的需求。
缺点
- 相位延迟:由于滤波器的设计,可能导致输出信号的相位延迟,在某些应用中,这种延迟可能是一个问题。
- 计算复杂度:相较于简单的平均滤波,巴特沃斯滤波器的计算较为复杂,需要较多的乘法和加法运算,可能会影响实时处理的效率。
- 参数敏感性:滤波器的性能对系数
b_coeff和a_coeff的选择敏感,需要根据具体的信号特性进行调试。
/*****************************************
巴特沃斯低通滤波器(Butterworth Low-pass Filter)
// current_value: 当前采样值
// history: 历史采样值数组
// b_coeff: 滤波器的b系数
// a_coeff: 滤波器的a系数
******************************************/
float ButterworthFilter(float current_value, float *history, float *b_coeff, float *a_coeff) {
// 使用巴特沃斯滤波器的差分方程计算新的滤波值
// b_coeff和a_coeff是滤波器的系数,分别对应于分子和分母多项式的系数
// history数组存储了前几次的输入和输出值,用于计算新的滤波值
float new_value = b_coeff[0] * current_value +
b_coeff[1] * history[0] +
b_coeff[2] * history[1] -
a_coeff[1] * history[2] -
a_coeff[2] * history[3];
// 更新历史值
// 将当前值和最近的滤波值存储起来,用于下一次计算
history[1] = history[0];
history[0] = current_value;
history[3] = history[2];
history[2] = new_value;
return new_value; // 返回新的滤波值
}
十一、Savitzky-Golay 滤波器
Savitzky-Golay 滤波器是一种用于平滑数据的数字滤波器,广泛应用于信号处理、数据分析和科学实验中。该滤波器通过拟合局部多项式来平滑数据,同时尽量保持数据的特征,如峰值和形状。
优点
- 保留特征:与简单的移动平均滤波器不同,Savitzky-Golay 滤波器在平滑数据的同时能够保留数据的原始形状和特征,特别是对于峰值和尖锐的特征。
- 灵活性:可以通过调整窗口大小和多项式的阶数来适应不同类型的数据和噪声特性。
- 有效处理噪声:特别适合于处理存在高频噪声的信号,能够有效降低噪声影响。
缺点
- 边界效应:在数据的开头和结尾处,由于没有足够的数据点,滤波效果可能会受到影响,造成边界效应。
- 计算复杂度:相较于简单的平均滤波器,Savitzky-Golay 滤波器的计算复杂度更高,尤其是在大数据集上。
- 需预计算系数:为了实现高效运算,必须预先计算滤波系数,这可能需要额外的准备工作。
/*****************************************
Savitzky-Golay 滤波器
// data: 输入数据数组
// size: 数据数组大小
// window_size: 窗口大小
// coeff: 滤波器系数数组
******************************************/
float SavitzkyGolayFilter(float *data, int size, int window_size, const float *coeff)
{
float result = 0.0; // 初始化结果为0
int half_window = window_size / 2; // 计算窗口的一半大小
// 遍历窗口内的每个数据点
for (int i = -half_window; i <= half_window; i++) {
// 计算加权和,即多项式拟合的结果
result += coeff[i + half_window] * data[i + half_window];
}
return result; // 返回计算得到的滤波值
}
滤波技术是提升ADC数据采集系统精度的重要手段,不同的滤波算法各有其适用场景和优缺点。在选择滤波算法时,需根据应用需求、实时性、灵敏度以及系统资源来综合考虑。
希望能为您的信号处理工作提供参考依据,并帮助您更好地实现数据采集系统的优化和稳定运行。

1640

被折叠的 条评论
为什么被折叠?



