电阻式触摸屏校准算法分析<一> 算法分析电阻式触摸屏在X,Y坐标方向上是线性的,比如S32采用的触摸屏,理论上Xmin=0,Xmax=1023,Ymin=0,Ymax=1023。
但是实际的触摸屏,往往是xmin>0,xmax<1023,ymin>0,ymax<1023。
所以就需要校准。
此文讨论的校准算法,其原理就是利用触摸屏的线性特性,针对被校准的触摸屏,获取其真正的x,y的范围,即xmin,ymin,xmax,ymax将其记录下来。
以后当触摸事件发生,将触摸屏报告的原始坐标(x,y)按比例投射到0~1023的坐标上即可。
注意,TP与LCD在相同的坐标方向上,具有相似性,即比例一致性。
看看对原始坐标的处理:If (x<xmin) x=0;Else if (x>xmax) x=xmax-xmin;Else x=1023*(x-xmin)/(xmax-xmin);If (y<ymin) y=0;Else if (y>ymax) y=ymax-ymin;Else y=1023*(y-ymin)/(ymax-ymin);可见,对原始坐标,先减去一个0位置的偏移量(x-xmin),然后求得它X范围上的比率((x-xmin)/(xmax-xmin)),再乘以1023,就得到了投射到(0~1023)上的坐标。
再看看校准算法。
在以下的讨论中,所谓物理坐标,指触摸屏上的坐标PT;所谓逻辑坐标,指LCD上的坐标PL。
LCD的宽度(W)对应TP的X方向,LCD的高度(H)对应TP的Y方向。
通过点击三个校准点Po(x,y),Px(x,y),Py(x,y),我们能得到图中内层方框的X,Y的物理坐标范围,即Xm = Px.x – Po.x Ym = Py.y – Po.y将此图投射到LCD上,有如下(物理值->逻辑值)的对应关系:Xl->Lwl,Xm->Lwm,Xr->Lwr,Yb->Lhb,Ym->Lhm,Yt->Lht。
根据TP与LCD的比例一致性,可以这样计算得到Xl,Xr,Yb,Yt:Xl = (Xm/ Lwm) * Lwl Xr = (Xm/ Lwm) * LwrYb = (Ym/Lhm) * Lhb Yt = (Ym/Lhm) * Lht于是我们的目的达到了:x范围:xmin = Po.x – Xl xmax = Px.x + Xry范围:ymin = Po.y – Yb ymax = Py.y + Yt<二> 代码实现1、对触屏上报的物理坐标值PT的处理。
PTx = (((x > input_dev->absmax[ABS_X]) ? (input_dev->absmax[ABS_X] - input_dev->absmin[ABS_X]) : ((x <= input_dev->absmin[ABS_X]) ? 0 : (x - input_dev->absmin[ABS_X]))) * 1023) /(input_dev->absmax[ABS_X] - input_dev->absmin[ABS_X]);PTy = (((y > input_dev->absmax[ABS_Y]) ? (input_dev->absmax[ABS_Y] - input_dev->absmin[ABS_Y]) : ((y <= input_dev->absmin[ABS_Y]) ? 0 : (y - input_dev->absmin[ABS_Y]))) * 1023) /(input_dev->absmax[ABS_Y] - input_dev->absmin[ABS_Y]);2、应用层根据上报的物理坐标,换算得到对应LCD宽高的逻辑坐标值PL。
PLx = (PTx/1023)*240Ply = (Pty/1023)*4003、校准数据的计算过程。
factor_x = (ts_cal_cmd.cur_ts_maxx - ts_cal_cmd.cur_ts_minx) / ts_cal_cmd.gui_w;factor_y = (ts_cal_cmd.cur_ts_maxy - ts_cal_cmd.cur_ts_miny) / ts_cal_cmd.gui_h;/* calculate the real boundary from the data collected by Android calibration application *//*+++++++++++++++++++++++++++++++++++*/high_adc_x = (ts_cal_cmd.p_ts.px.x * factor_x) ;low_adc_x = (ts_cal_cmd.p_ts.po.x * factor_x) ;high_adc_y = (ts_cal_cmd.p_ts.py.y * factor_y) ;low_adc_y = (ts_cal_cmd.p_ts.po.y * factor_y) ;unit_adc_x = (high_adc_x - low_adc_x)/((ts_cal_cmd.p_gui.px.x - ts_cal_cmd.p_gui.po.x) / ts_cal_cmd.grid_x_size);unit_adc_y = (high_adc_y - low_adc_y)/((ts_cal_cmd.p_gui.py.y - ts_cal_cmd.p_gui.po.y) / ts_cal_cmd.grid_y_size);g_ts_range.max_x = high_adc_x + ((ts_cal_cmd.gui_w - ts_cal_cmd.p_gui.px.x)/ts_cal_cmd.grid_x_size) * unit_adc_x;g_ts_range.min_x = low_adc_x - (ts_cal_cmd.p_gui.po.x)/ts_cal_cmd.grid_x_size * unit_adc_x;g_ts_range.max_y = high_adc_y + (ts_cal_cmd.gui_h - ts_cal_cmd.p_gui.py.y)/ts_cal_cmd.grid_y_size * unit_adc_y;g_ts_range.min_y = low_adc_y - (ts_cal_cmd.p_gui.po.y)/ts_cal_cmd.grid_y_size * unit_adc_y;;g_ts_range.y_th = unit_adc_y;/*-----------------------------------*//* report the calibrated boundary data*//*+++++++++++++++++++++++++++++++++++*/g_ts_range.min_x += ts_cal_cmd.cur_ts_minx;g_ts_range.max_x += ts_cal_cmd.cur_ts_minx;g_ts_range.min_y += ts_cal_cmd.cur_ts_miny;g_ts_range.max_y += ts_cal_cmd.cur_ts_miny;ts_cal_cmd.cur_ts_cal_minx = g_ts_range.min_x;ts_cal_cmd.cur_ts_cal_maxx = g_ts_range.max_x;ts_cal_cmd.cur_ts_cal_miny = g_ts_range.min_y;ts_cal_cmd.cur_ts_cal_maxy = g_ts_range.max_y;4、填入代码中的默认校准数据T_ts_calibrate_gui_cmd g_default_cal_data = {1,0,1023, 0,1023, //cur_ts_minx,maxx,miny,maxy240, 400, // LCM: width/height defined in im9815_lcm.h{ // Calibration points: po, px, py{20, 20},{220, 20},{20, 380}},{ // Touch points: po, px, py{20, 20},{220, 20},{20, 380}},20, 20, // x, y grid size0,1023, 0,1023, //cur_ts_cal_minx,maxx,miny,maxy};<三> 实例分析1、第1次使用触屏,进入图形校准界面。
2、载入默认校准数据g_default_cal_data,3、得到3个校准点的物理坐标, 用默认校准数据参与处理,上报,最后转换为逻辑坐标。
点(20,20): 触屏得到的坐标Po(260,210)->上报坐标(260,210)->逻辑坐标(61,82)点(220,20) 触屏得到的坐标Px(865,200) ->上报坐标(865,200)->逻辑坐标(203,78)点(20,380) 触屏得到的坐标Py(250,950) ->上报坐标(250,950)->逻辑坐标(59,371)4、将得到的3个校准点的逻辑坐标,代入新校准数据的计算过程。
◎First step: 物理坐标/逻辑坐标的比值factor_x =(1023-0)/240=4.2625factor_y =(1023-0)/400=2.5575◎second step: 将测到的校准点之逻辑坐标转化为物理坐标。
得到以校准点为限的X范围,Y范围。
high_adc_x = (203* 4.2625) = 865.3low_adc_x = (61* 4.2625) = 260high_adc_y = (371*2.5575) = 948.8low_adc_y = (82* 2.5575) = 209.7◎third step: 得到每个逻辑格子对应的X、Y的物理宽度。
unit_adc_x = (865.3- 260) / ((220 - 20) / 20) =60.53unit_adc_y = (948.8- 209.7) / ((380 - 20) / 20) =41.06◎forth step: 以校准点为限的X范围,Y范围,加上校准点到屏边缘的距离所对应的物理宽度。