[原创].触摸屏滤波的一点心得
0赞引子
最近在编写Nios II的触摸屏驱动,TFT的驱动器为ILI9325,触摸AD为ADS9325。无论是轮询的方式抑或中断的方式,都会出现令人讨厌的散点。经过在SOPC技术联盟群的讨论,达克斯特兄给我一点启示,让我成功消除了散点。
第1种尝试 中位值平均滤波法
首先移植的是liujun6037的代码,他的代码思路为:对X、Y的坐标连续采样十次;不足十次则认为数据无效,不做任何操作;然后对十次数据进 行排序;最后取中间三次的数据进行平均,得到最终的X、Y坐标。不同的是,我把冒泡排序换成我常用的选择排序,其实还是O(n^2)。其效果如图1所示。 可以清楚地看到,本次尝试很失败,有很多莫名其妙的散点。
代码1 第一种尝试
void ads_GetXY(void) { u8 cnt=0; u8 i, j, k, min; u16 temp; u16 tempXY[2][9], XY[2]; do { if(ads_ReadXY()) { tempXY[0][cnt] = X; tempXY[1][cnt] = Y; cnt++; } }while(cnt<9); if(cnt==9) { for(k=0; k<2; k++) { // 降序排列 for(i=0; itempXY[k][j]) min=j; } temp = tempXY[k][i]; tempXY[k][i] = tempXY[k][min]; tempXY[k][min] = temp; } // 求中间值的均值 XY[k] = (tempXY[k][3]+tempXY[k][4]+tempXY[k][5]+tempXY[k][6]) / 4; } } // 矫正坐标 X = ((XY[0]-350)/11); Y = ((XY[1]-400)/14); }
图1 第一种尝试
第2种尝试 差值平均滤波法
由于第一种尝试比较失败,我就在网上搜到了参考2的算法。尝试了一下,效果极差,线条极其发散,图片就不贴了。代码贴到这里作为反面例程。
代码2 第二种尝试
void ads_GetXY(void) { u8 cnt=0; u8 i, j, k, min; u16 temp; u16 tempXY[2][9], avgXY[2][3], XY[2]; s16 diffXY[2][3]; do { if(ads_ReadXY()) { tempXY[0][cnt] = X; tempXY[1][cnt] = Y; cnt++; } }while(cnt<9); if(cnt==9) { for(k=0; k<2; k++) { // 取平均值 avgXY[k][0] = (tempXY[k][0]+tempXY[k][1]+tempXY[k][2])/3; avgXY[k][1] = (tempXY[k][3]+tempXY[k][4]+tempXY[k][5])/3; avgXY[k][2] = (tempXY[k][6]+tempXY[k][7]+tempXY[k][8])/3; // 取差值 diffXY[k][0] = avgXY[k][0] - avgXY[k][1]; diffXY[k][1] = avgXY[k][1] - avgXY[k][2]; diffXY[k][2] = avgXY[k][2] - avgXY[k][0]; // 取差值的绝对值 diffXY[k][0] = (diffXY[k][0] > 0) ? diffXY[k][0] : -diffXY[k][0]; diffXY[k][1] = (diffXY[k][1] > 0) ? diffXY[k][1] : -diffXY[k][1]; diffXY[k][2] = (diffXY[k][2] > 0) ? diffXY[k][2] : -diffXY[k][2]; // 取最小的数得平均值 if(diffXY[k][0] < diffXY[k][1]) { if(diffXY[k][2] < diffXY[k][1]) XY[k] = (avgXY[k][0]+avgXY[k][2])>>1; else XY[k] = (avgXY[k][0]+avgXY[k][1])>>1; } else if(diffXY[k][2] < diffXY[k][1]) XY[k] = (avgXY[k][0]+avgXY[k][2])>>1; else XY[k] = (avgXY[k][1]+avgXY[k][2])>>1; } } // 矫正坐标 X = ((XY[0]-350)/11); Y = ((XY[1]-400)/14); }
第3种尝试 中位值平均加阈值滤波法
既然第一种尝试的线条已经比较收敛,那么散点是怎么出来的呢?经过达克斯特兄的一点指导和我的多次实验,终于干掉了这个头疼的散点。原来虽然使用中 位值平均滤波法可以稳定获取符合触摸屏范围的数据,但是却无法滤除跳变的散点。对于跳变的散点必须通过加阈值才能消除。下面贴出我的代码。代码思路:采样 符合触摸屏范围的数据若干次,将其排序,取中间两位的差值;若差值大于阈值,则丢弃。因为数据已经排序,因此差值肯定是正值或零值,即无需申明为有符号 数。同时由于阈值判断的加入,我们可以将数据的采样次数适当调整,此处仅为4次,所得效果已经非常令人满意。需要注意的是采样数据不宜过多,否则连续的线 会变成离散的点。
代码3 第3种尝试
#define SAMP_CNT 4 #define SAMP_CNT_DIV2 2 u8 ads_GetXY(void) { u8 i, j, k, min; u16 temp; u16 tempXY[2][SAMP_CNT], XY[2]; // 采样 for(i=0; i<2; k++) { // 降序排列 for(i=0; i tempXY[k][j]) min=j; } temp = tempXY[k][i]; tempXY[k][i] = tempXY[k][min]; tempXY[k][min] = temp; } // 设定阈值 if((tempXY[k][SAMP_CNT_DIV2]-tempXY[k][SAMP_CNT_DIV2-1]) > 5) return 0; // 求中间值的均值 XY[k] = (tempXY[k][SAMP_CNT_DIV2]+tempXY[k][SAMP_CNT_DIV2-1]) / 2; } // 矫正坐标 X = ((XY[0]-350)/11); Y = ((XY[1]-400)/14); return 1; }
图片3 第三种尝试
视频,触摸屏测试:http://v.youku.com/v_show/id_XMjI2MDIzMTcy.html
参考
1. liujun6037.2.4寸TFTLCD触摸屏测试通过!(ADS7846/7843)
2. 鹰之翔.毕业设计第六天(触摸屏在S3C2410上的软件滤波 )