In many previous projects I used a 2.8" TFT 262K Color LCD display with resistive touchscreen. Since the display had no touchscreen controller, I implemented one on Espruino (Resistive Touchscreen directly (no touch controller)). Recently I wanted to use the display again, but for whatever reason it turned out to be dead not only like a possum, but really really dead. So I ordered some cheaper once of 2.2" size, since needed them just to verify code for the ILI9341 display controller.
The cheap 2.4" display showed though up with a XPT2046 touchscreen controller from XPTEK TECHNOLOGY CO., LTD, SHENZHEN. After consulting the data sheet it seems that the XPT2046 is functionally about equal to Burr-Brown's / TI's ADS7843 and thus Espruino's ADS7843 module works... at least, it returns coordinates... dodged that bullet... easily...
But from there on in went tricky to say the least... and unfortunately ended with the conclusion: module useless (from the point of usable values,.. and more), because the user's touch accuracy is about +- 2..3 pixels... but the module error is up to 32... just not useful for a touch UI.
Why?
Below code and and attached shot show. The code sets up the display and the touch screen, then draws calibration markers in all corners and the center and then logs values for calibration.
// TFT24TRCportraitCalibr.js
//
// 2.4" 240x320 262K Color TFT LCD ILI9341 on SPI1 with
// Resistive Touch Screen Controller XPT2046 on SPI2
// using out of box ILI9341 and ADS7843 modules.
//
// Wiring:
// 2.4"
// DSP PICO [<---USB
// 1 VCC red 3 3.3 shared
// 2 GND blk 1 GND shared
// 3 CS blu 7 B6 CS LCD
// 4 RST brn 9 A8 reset RST LCD
// 5 D/C grn 8 B7 D/C LCD
// 6 MOSI ylw 6 B5 SPI1 MOSI LCD
// 7 SCK wht 4 B3 SPI1 SCK LCD
// 8 LED org 18 A5 LED LCD
// 9 MISO grn 5 B4 SPI1 MISO LCD
// 10 T_CLK wht 23 B13 SPI2 SCK Touch
// 11 T_CS ylw 22 B10 CS Touch
// 12 T_MOSI grn 25 B15 SPI2 MOSI Touch
// 13 T_MISO blu 24 B14 SPI2 MISO Touch
// 14 T_IRQ blk 21 B1 IRQ Touch
var dW = 240, dH = 320, dsp, dMod = require("ILI9341"),
tSPI=SPI2, tCs = B10, tIrq = B1,
touch, tMod = require("ADS7843");
// marker specs (lik dice face 5; top left to bottom right)
var mrks =
[{i:1, label:"topLeft" , x: 20, y: 20, xOff: 14, yOff:-6}
,{i:2, label:"topRight" , x:220, y: 20, xOff:-66, yOff:-6}
,{i:3, label:"center" , x:120, y:160, xOff:-29, yOff:14}
,{i:4, label:"bottomLeft" , x: 20, y:300, xOff: 14, yOff:-6}
,{i:5, label:"bottomRight", x:220, y:300, xOff:-74, yOff:-6}
];
var mSiz = 9; // half of marker size, (0.7 of font size)
// print marker at x/y of size s with x/y label
function mrkr(d,x,y,s,xOff,yOff) {
dsp.setColor(1,1,1);
dsp.drawRect(x-s,y-s,x+s,y+s);
dsp.drawLine(x-s,y,x+s,y);
dsp.drawLine(x,y-s,x,y+s);
dsp.setFontVector(s / 0.7);
dsp.drawString(x + " / " + y, x+xOff, y+yOff);
}
function average(arry) { // return avarage of array values
return arry.reduce(
function(p,c) { return p + c; },0) / arry.length; }
function logAverage(seq,xs,ys) { // log x / y average
var x = Math.round(average(xs)),
y = Math.round(average(ys));
console.log(
seq + 1
, mrks[seq].label
, mrks[seq].x, mrks[seq].y
, x ,"(" + (x - mrks[seq].x) + ")"
, y ,"(" + (y - mrks[seq].y) + ")"
);
}
function onInit() {
A5.set();
SPI1.setup({sck:B3, miso:B4, mosi:B5, baud: 1000000});
// spi, dc, cs, rst, callback
dsp = dMod.connect(SPI1, B7, B6, A8, function() {
dsp.clear();
// print markers like dice face of 5
mrks.forEach(function(m) {
mrkr(dsp, m.x, m.y, mSiz, m.xOff, m.yOff); });
// setup touchscreen with callback averaging
// x and y sequence for calibration of
// touchscreen to lcd display.
SPI2.setup({sck:B13, miso:B14, mosi:B15, baud: 2000000});
var seq = 0, xs = [], ys = [], x, y;
touch = tMod.connect(
// spi, cs, irq, offsetx, offsety, w, h, callback // landscape
SPI2, B10, B1, -15, 6, dH, dW, function(yt, xt) { // portrait
if (yt !== undefined) {
// collect x and y for averaging
xs.push(dW - xt); ys.push(yt);
} else {
// log x and y avarages in console
logAverage(seq, xs, ys);
xs = []; ys = []; seq = (seq +1) % 5;
}
});
});
}
onInit();
The issues are:
ILI9341 initializes in portrait with x=0..239 - 240 pixels wide - and y=0...319 - 320 pixels high - and 0 / 0 top left (see shot).
XPT2046 controller is wired portrait, but not in a twisted way... not just rotated by 90 degrees... It could be fixed with the some additional calculation: with or hight - coordinate touch value.
it is not good enough to have an x and y offset for the controller function to calculate the actual x and y for a given display size. The offset helps with the touch screen not aligning with the display, but it messes up the scaling: if the low value is ok, the high value is too much off and vice versa. This can be seen in the output generated by above code when touching the calibration points from top left to bottom right.
Because many touch screens are larger than the display because they show fixed, printed buttons in the overhang area. For touching in the overhang, proper calculation returns values beyond the screen coordinates.
Produced output (aligned and with headings added):
Looking at x coordinate, the low value is about correct, but the deviation for higher values goes linearly up by about 10 per 120 pixels (half screen width). The 'balconies' or 'porches'
(screen vs display sizes and alignments) impact the calculation beyond what an offset can handle.
Same can be said for the y coordinate: after adjusting with an offset, the error is even worse.
Since the issues are hardware - wiring, size and alignment dependent, a module has to provide an option to pass a calculation function that takes minimum AND maximum touch values into account to scale properly with the display size. I'll take a stab at it and will publish in a next post.
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
In many previous projects I used a 2.8" TFT 262K Color LCD display with resistive touchscreen. Since the display had no touchscreen controller, I implemented one on Espruino (Resistive Touchscreen directly (no touch controller)). Recently I wanted to use the display again, but for whatever reason it turned out to be dead not only like a possum, but really really dead. So I ordered some cheaper once of 2.2" size, since needed them just to verify code for the ILI9341 display controller.
The cheap 2.4" display showed though up with a XPT2046 touchscreen controller from XPTEK TECHNOLOGY CO., LTD, SHENZHEN. After consulting the data sheet it seems that the XPT2046 is functionally about equal to Burr-Brown's / TI's ADS7843 and thus Espruino's ADS7843 module works... at least, it returns coordinates... dodged that bullet... easily...
But from there on in went tricky to say the least... and unfortunately ended with the conclusion: module useless (from the point of usable values,.. and more), because the user's touch accuracy is about +- 2..3 pixels... but the module error is up to 32... just not useful for a touch UI.
Why?
Below code and and attached shot show. The code sets up the display and the touch screen, then draws calibration markers in all corners and the center and then logs values for calibration.
The issues are:
ILI9341 initializes in portrait with x=0..239 - 240 pixels wide - and y=0...319 - 320 pixels high - and 0 / 0 top left (see shot).
XPT2046 controller is wired portrait, but not in a twisted way... not just rotated by 90 degrees... It could be fixed with the some additional calculation: with or hight - coordinate touch value.
it is not good enough to have an x and y offset for the controller function to calculate the actual x and y for a given display size. The offset helps with the touch screen not aligning with the display, but it messes up the scaling: if the low value is ok, the high value is too much off and vice versa. This can be seen in the output generated by above code when touching the calibration points from top left to bottom right.
Because many touch screens are larger than the display because they show fixed, printed buttons in the overhang area. For touching in the overhang, proper calculation returns values beyond the screen coordinates.
Produced output (aligned and with headings added):
Looking at x coordinate, the low value is about correct, but the deviation for higher values goes linearly up by about 10 per 120 pixels (half screen width). The 'balconies' or 'porches'
(screen vs display sizes and alignments) impact the calculation beyond what an offset can handle.
Same can be said for the y coordinate: after adjusting with an offset, the error is even worse.
Since the issues are hardware - wiring, size and alignment dependent, a module has to provide an option to pass a calculation function that takes minimum AND maximum touch values into account to scale properly with the display size. I'll take a stab at it and will publish in a next post.
2 Attachments