灭火机器人的设计与制作之滤波算法
传感器在系统中作为输入装置,输入的是模拟量,经过A/D转换器将模拟信号转换成数字信号后,才能被系统所使用。因此,数模转换后数值的准确性直接影响到系统的判断。本文就介绍了实际应用中使用的滤波算法。
在系统中总会存中部分电路噪声或电磁辐射干扰A/D信号,影响数字信号的准确性和平滑性。一般情况下先在硬件上尽可能地进行优化,降低噪声辐射干扰,当硬件上无法进一步改善信号干扰时,这时候就需要采用软件滤波的方法来减少干扰。
滤波算法有很多种,如:限幅滤波、中位值滤波、一阶滤波、消抖滤波等,但各种滤波算法各有特点,使用场合也各不相同。在本系统中使用了中位值、平均、递推复合滤波算法,简称中位值平均递推滤波。
中位值滤波算法是通过连续采样N次,把N次采样值排序,取中间值为本次有效值。该滤波算法能有效克服因偶然因素引起的波动干扰;对变化缓慢的被测参数有良好的滤波效果,但是对快速变化的参数不宜。使用在本系统中,可以消除因电压波动引起的偶然脉冲干扰。
算术平均滤波算法是连续取N个采样值进行算术平均运算,当N值较大时,信号平滑度较高,但灵敏度较低;N值较小时,信号平滑度较低,但灵敏度较高,该算法可以很好的滤除随机干扰。在本系统中,考虑到系统的执行速度较快,并且保证信号的灵敏度,这里N取4,可以很好的滤除随机干扰。
递推平均滤波算法又称滑动平均滤波法,它是将N个采样值放入一个队列,有新的采样值到来时,将最早的一个值去除,再将新值加入队列,求队列平均值。这种算法对周期性干扰有良好的抑制作用,平滑度高,但具有灵敏度低,数据滞后等特点。
在本系统中使用了以上三个算法的复合算法,结合了三种算法各自的优点,并且能够保证系统的灵敏度。
下面将滤波算法列出,以便更好地进行分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | uint16 ADC_mget(uint8 channel) { uint16 adc_temp[10]; static uint16 pre_temp[10][4]={0}; uint16 temp=0; uint32 sum=0; uint8 i=0,j=0; for(i=0;i<10;i++) adc_temp[i] = ADC_get(channel);//连取十个值 for(j=0;j<9;j++)//冒泡排序 { for(i=0;i<9-j;i++) { if(adc_temp[i]>adc_temp[i+1]) { temp = adc_temp[i]; adc_temp[i]=adc_temp[i+1]; adc_temp[i+1]=temp; } } } sum += adc_temp[3];//累加 sum += adc_temp[4]; sum += adc_temp[5]; sum += adc_temp[6]; sum >>= 2; //求均值 pre_temp[channel][3]=pre_temp[channel][2];//递推入列 pre_temp[channel][2]=pre_temp[channel][1]; pre_temp[channel][1]=pre_temp[channel][0]; pre_temp[channel][0]=(uint16)sum; sum = 0; sum += pre_temp[channel][3];//累加 sum += pre_temp[channel][2]; sum += pre_temp[channel][1]; sum += pre_temp[channel][0]; sum >>= 2; //求均值 return (uint16)sum; } |
从以上程序中可以看到,在中位值滤波中连取十个值,取中间四个有效,将这四个值累加求均值后加入到递推滤波算法的队列中,再累加求平均值后才作为最终有效值返回。在程序中,累加值个数都取四,是为了求均值时可以使用移位的方法来快速求平均值。
在嵌入式系统中,资源和效率始终是程序员不断追求的,求平均值时使用除法运算需要三到四个指令周期,如果使用移位操作同样可以达到除法的效果,但只要用一个指令周期,节省了CPU时间。同样地,递推入列的时候采用的是四个赋值语句,相比循环语句经编译器编译后,四个赋值语句执行效率更高。软件滤波的效果请参考图7-1。
由上图可以看出初始采样值波动比较大,峰峰值达到42,对实际距离的判断可能会有5cm左右的误差,经过软件滤波后峰峰值仅为1,大大提高了转换值的准确性,增强了系统的稳定性。

for(i=0;i<10;i++) adc_temp[i] = ADC_get(channel);//连取十个值
这里的连取十个值如何实现?我是新手,呵呵
ADC_get,这个函数就是从传感器返回一下值啊
pre_temp[channel][3]=pre_temp[channel][2];//递推入列
pre_temp[channel][2]=pre_temp[channel][1];
pre_temp[channel][1]=pre_temp[channel][0];
pre_temp[channel][0]=(uint16)sum;
sum = 0;
sum += pre_temp[channel][3];//累加
sum += pre_temp[channel][2];
sum += pre_temp[channel][1];
sum += pre_temp[channel][0];
sum >>= 2; //求均值
return (uint16)sum;
不能理解,能解释下嘛?
第一次采集AD后,静态变量pre_temp[channel][2],有值吗?如何赋值的?
pre_temp[channel][3]=pre_temp[channel][2];//递推入列
pre_temp[channel][2]=pre_temp[channel][1];
pre_temp[channel][1]=pre_temp[channel][0];
pre_temp[channel][0]=(uint16)sum;
这段话如何工作?
自己先偷懒了,没去跑跑试试看,呵呵
刚开始是无效值,所以,采用递推滤波的前几次的值是无效的。但后来就非常稳定了
恩,那就对了。。。~~~这几天在看LPC2132
校内找到的同学,你好!我工作涉及嵌入式也一直在学习。
想听听你的意见,共同交流!我的Q 16705879