XPT2046_Touchscreen improve sampling accuracy

andreobi

Member
Hi,

a few days ago I started to use the XPT2046_Touchscreen lib and it wored out of the box.

I did some tests and also looked up the datasheet, but I wasn't quite happy with the result. So here I want to provide my changes to improve the measurement at the cost of spending more time on the sampling task.

What are my changes:
- doing one dummy sampling bevor x and y sampling to stbilize the system
- no switching between x ynd y sampling
- changing the Z evaluation according to the datasheet

and this could be a part of the lib
- adding a transformation from touch to display coordinates

void XPT2046_Touchscreen::update(){
if (!isrWake) return;
uint32_t now = millis();
if (now - msraw < MSEC_THRESHOLD) return;
int16_t data[6];
SPI.beginTransaction(SPI_SETTING);
digitalWrite(csPin, LOW);
SPI.transfer(0xB1); // Z1
int16_t z1 = SPI.transfer16(0xC1) >> 3; // Z2
int16_t z2 = SPI.transfer16(0xd1) >> 3; // X for pressed
SPI.transfer16(0xd1);
data[0] = SPI.transfer16(0xd1) >> 3;
data[1] = SPI.transfer16(0xd1) >> 3; // make 3 x-y measurements
data[2] = SPI.transfer16(0x91) >> 3;
SPI.transfer16(0x91);
data[3] = SPI.transfer16(0x91) >> 3;
data[4] = SPI.transfer16(0x90) >> 3; // Last Y touch power down
data[5] = SPI.transfer16(0) >> 3;
digitalWrite(csPin, HIGH);
SPI.endTransaction();

zraw = ((((z2<<2)/z1)-4)*(data[0]>>4))>>7;
if (zraw > Z_THRESHOLD_INT) {
if (255 != tirqPin){
isrWake = false;
}
return;
}else{
msraw = now; // good read completed, set wait
}
//Serial.printf(" z1=%d,z2=%d ", z1, z2);
xraw = besttwoavg( data[0], data[1], data[2] );
yraw = besttwoavg( data[3], data[4], data[5] );
}


...
These parameters depent on your hardware, measure three raw point on the screen
i.e (Xmin,Ymin), (Xmin,Ymax), (Xmax,Yhalf)

Xdmin= A * Xtmin + B * Ytmin + C
Xdmin= A * Xtmin + B * Ytmax + C
Xdmax= A * Xtmax + B * Ythalf + C

Ydmin= D * Ytmin + E * Xtmin + F
Ydmax= D * Ytmax + E * Xtmin + F
Ydhalf= D * Ythalf + E * Xtmax + F

insert the touch (Xt) and the display (Xd) points, solve the 6 equations and you get the parameters for A-F

#define PARAM_A 0.205667
#define PARAM_B 0.000756
#define PARAM_C -18.659607

#define PARAM_D 0.12984
#define PARAM_E -0.001794
#define PARAM_F -37.410868
...
i.e.:
disp_x_size = 799;
disp_y_size = 479;
...

update();
int16_t x = (long)((long)(PARAM_A*256*256) * (long)xraw + (long)(PARAM_B*256*256) *(long)yraw + (long)(PARAM_C*256*256))>>16;
if (x < 0) x=0;
else if (x>disp_x_size) x=disp_x_size;

int16_t y = (long)((long)(PARAM_D*256*256) * (long)yraw + (long)(PARAM_E*256*256) *(long)xraw + (long)(PARAM_F*256*256))>>16;
if (y < 0) y=0;
else if (y>disp_y_size) y=disp_y_size;
...


it is just a proposal, if you like it - use it!

Andre
 
A few weeks/months ago there was a thread about someone having trouble with this library, you might
want to hunt it down and see if you've addressed the issues from that thread, I suspect so.
 
Back
Top