常用滤波
文档参考:https://sneak.blog.csdn.net/article/details/129629485
常用滤波
文档参考:https://sneak.blog.csdn.net/article/details/12962948
未添加滤波算法
main函数
while(1){
HAL_ADC_Start(&hadc1); //开启ADC1,放置在while循环中
ADC_value=HAL_ADC_GetValue(&hadc1); //获取ADC1的数值
HAL_Delay(10); //延迟函数,防止采样失效
printf("ADC_value:%d\n", ADC_value);
}
一阶互补滤波
方法:取a=0~1,本次滤波结果=(1-a)本次采样值+a上次滤波结果
优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合
缺点:相位滞后,灵敏度低滞后程度取决于a值大小不能消除滤波频率高于采样频率的1/2的干扰信号
//一阶互补滤波
int firstOrderFilter(int newValue, int oldValue, float a)
{
return a * newValue + (1-a) * oldValue;
}
ADC_value=HAL_ADC_GetValue(&hadc1); //获取ADC1的数值
//主函数
while(1){
HAL_ADC_Start(&hadc1); //开启ADC1,放置在while循环中
Filtering_Value = firstOrderFilter(HAL_ADC_GetValue(&hadc1),ADC_value,0.3); //滤波算法
HAL_Delay(10); //延迟函数,防止采样失效
printf("ADC_value:%d\n", ADC_value);
printf(“ADC_value:%d\n”, ADC_value);
}
一阶互补滤波的局限性还是很大的,效果非常一般。
中位值滤波
方法:连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值
优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果
缺点:对流量,速度等快速变化的参数不宜
//中值滤波算法
int middleValueFilter(int N)
{
int value_buf[N];
int i,j,k,temp;
for( i = 0; i < N; ++i)
{
value_buf[i] = HAL_ADC_GetValue(&hadc1);
}
for(j = 0 ; j < N-1; ++j)
{
for(k = 0; k < N-j-1; ++k)
{
//从小到大排序,冒泡法排序
if(value_buf[k] > value_buf[k+1])
{
temp = value_buf[k];
value_buf[k] = value_buf[k+1];
value_buf[k+1] = temp;
}
}
}
return value_buf[(N-1)/2];
}
中值滤波对消除异常值和平稳化AD采样都具有十分有效的结果。
算术平均滤波
方法:连续取N个采样值进行算术平均运算;
N值较大时:信号平滑度较高,但灵敏度较低
N值较小时:信号平滑度较低,但灵敏度较高
N值的选取:一般流量,N=12;压力:N=4
优点:试用于对一般具有随机干扰的信号进行滤波。这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
缺点:测量速度较慢或要求数据计算较快的实时控制不适用。
//算术平均值滤波
int averageFilter(int N)
{
int sum = 0;
short i;
for(i = 0; i < N; ++i)
{
sum += HAL_ADC_GetValue(&hadc1);
}
return sum/N;
}
平滑均值滤波相较于普通的算术平均滤波,突出一个平滑特性。可以从上述VOFA+的波形图看出,平滑滤波可以有效抵消AD采样的刺噪并稳定化采集(据作者同门实战反应平滑滤波的效果还是非常好的,尤其在控制方面)。
限幅平均滤波
方法:相当于“限幅滤波法”+“递推平均滤波法”
每次采样到的新数据先进行限幅处理再送入队列进行递推平均滤波处理
优点:对于偶然出现的脉冲性干扰,可消除有其引起的采样值偏差。
缺点:比较浪费RAM
//限幅平均滤波
#define A 50 //限制幅度阈值
#define M 12
int data[M];
int First_flag=0;
int LAverageFilter()
{
int i;
int temp,sum,flag=0;
data[0]=HAL_ADC_GetValue(&hadc1);
for(i=1;i<M;i++)
{
temp=HAL_ADC_GetValue(&hadc1);
if((temp-data[i-1])>A||((data[i-1]-temp)>A))
{
i--;flag++;
}
else
{
data[i]=temp;
}
}
for(i=0;i<M;i++)
{
sum+=data[i];
}
return sum/M;
}
限幅平均滤波类似于缝合怪,但是效果是非常显著的,它有效的解决了实际场景下突变噪声对AD采样的影响,但是消耗内存。
卡尔曼滤波
核心思想:根据当前的仪器"测量值" 和上一刻的 “预测量” 和 “误差”,计算得到当前的最优量,再预测下一刻的量。里面比较突出的是观点是:把误差纳入计算,而且分为预测误差和测量误差两种,通称为噪声。还有一个非常大的特点是:误差独立存在,始终不受测量数据的影响。
优点:巧妙的融合了观测数据与估计数据,对误差进行闭环管理,将误差限定在一定范围。适用性范围很广,时效性和效果都很优秀。
缺点:需要调参,参数的大小对滤波的效果影响较大。
//卡尔曼滤波
int KalmanFilter(int inData)
{
static float prevData = 0; //先前数值
static float p = 10, q = 0.001, r = 0.001, kGain = 0; // q控制误差 r控制响应速度
p = p + q;
kGain = p / ( p + r ); //计算卡尔曼增益
inData = prevData + ( kGain * ( inData - prevData ) ); //计算本次滤波估计值
p = ( 1 - kGain ) * p; //更新测量方差
prevData = inData;
return inData; //返回滤波值
}
作者本人是非常喜欢卡尔曼滤波的,VOFA+显示的波形图开源看出卡尔曼滤波有一定的去噪稳定特性的,虽然效果不是特别优秀。卡尔曼滤波的普适性很强,尤其在控制与多传感器融合方向,只要参数调整的好,效果出奇优秀。
标签:采样,常用,HAL,int,滤波,value,ADC From: https://www.cnblogs.com/baolixin/p/17611698.html