Below module code I intend to use for my resistive touch screen. It is a much lighter version of what you have seen from me so far. It is inspired by @Gordon 's ADS7843 touch controller module AND is - of course - 100% callback backward-compatible. Planned name for the module is TOUCHR - R for resistive.
The module includes the defaults configuration for any ILI9341 controlled 320x240 262K Color TFT LCD with resistive touch screen (used in 65K color mode). Any of the default LCD and touch screen parameters can be overwritten on connect() to use it with other displays and touch screen, and to manage variations between same touch screens.
Power consumption is optimized and can be lowered even more for touch tracking by setting the scan interval i at connect time or afterwards, even dynamically in callback depending tracking needs identified on particular touch.
// TOUCHRsimple_inline.js
// Module for connecting resistive touch screen (passive X- X+ Y- Y+)
// var touchr = require("TOUCHR").connect(C0,C1,C2,C3,function(x,y,tr){
// if (tr.t) { console.log(x,y); } else { console.log("up"); }
// }).listen(true);
//
// // probe xy when NOT listening - touch.listen(false);
// if (touchr.xy().t) console.log(touchr.x,touchr.y);
// connect(X- C0,X+ C1,Y- C2,Y+ C3,callback(x,y,touchr),C{onfig}
// listen(boolean): start/stop
// xy(optCallback): read xy (ONLY when NOT listening)
// ...all returning touchr
// Config (for overriding adafruit's 2.8" 320x240 res touch LCD TFT):
// X: horizontal px #
// Y: vertical px #
// xt: x touch threshold #
// yt: y touch threshold #
// xc: x center value #
// yc: y center value #
// xd: x delta per px #
// yd: y delta per px #
// xr: x read (raw) # 0
// yr: y read (raw) # 0
// x: x touching # 0..X-1
// y: y douching # 0..Y-1
// t: touching boolean (null = ambiguous)
// i: track intervall [ms]
// l: listening boolean
// w: watch id
var touchrModule = { connect: function(xn,xp,yn,yp,callback,C) {
var tr =
{ X: 240
, Y: 320
, xt: 0.08
, yt: 0.05
, xc: 0.4960
, yc: 0.4795
, xd: 0.00318
, yd: 0.00251
, xr: 0
, yr: 0
, x: 0
, y: 0
, t: false
, i: 100
, l: true
, w: false
, cb: callback
};
if (C) { for (var v in C) tr[v] = C[v]; }
tr.xy = function(cb,l) {
pinMode(yn,"input_pulldown");
digitalRead(yp);
digitalWrite([xn,xp],2);
tr.xr = (analogRead(yn)+analogRead(yn))/2;
pinMode(xn,"input_pulldown");
digitalRead(xp);
digitalWrite([yn,yp],2);
tr.yr = (analogRead(xn)+analogRead(xn))/2;
digitalRead([yn,yp]); tr.t = null;
if (tr.xr>tr.xt && tr.yr>tr.yt) { tr.t = true;
tr.x = ((tr.x = Math.round(tr.X/2+(tr.xr-tr.xc)/tr.xd)-1)
<0) ? 0 : (tr.x<tr.X) ? tr.x : tr.X-1;
tr.y = ((tr.y = Math.round(tr.Y/2+(tr.yr-tr.yc)/tr.yd)-1)
<0) ? 0 : (tr.y<tr.Y) ? tr.y : tr.Y-1;
if (cb) { cb(tr.x,tr.y,tr); }
} else if (tr.xr<tr.xt && tr.yr<tr.yt) { tr.t = false;
if (cb) { cb(undefined,undefined,tr); }
} if (!l && cb) { cb(undefined,undefined,tr); }
return tr;
};
tr.track = function() {
tr.w = null; pinMode(xn); tr.xy(tr.cb,true);
if (tr.t === false) { tr.listen(tr.l);
} else { setTimeout(function(){ tr.track(); },tr.i); }
};
tr.listen = function(b) {
tr.l = b; if (b && !tr.w) {
pinMode(xn,"input_pulldown");
digitalRead(xp);
digitalWrite([yn,yp],3);
tr.w = setWatch(tr.track,xp,{edge:rising, repeat:false});
} else {
if (tr.w) { clearWatch(tr.w); tr.w = null; }
} return tr;
};
return tr;
}
};
shows the console output below on touching top-left, top-right, bottom-right, and bottom-left corner and the center of the LCD area. On touching, it shows the calculated x and y coordinates and the raw rx and ry values read by the ADC pins. On up (just once after touching) just the raw values read by the DC pin are shown. The touch thresholds (xt, yt) for detecting an un-touch are between the lowest read touch value and the up (un-touch) value and are different for x and y axis. Touches are detected by a hardware event caught by setWatch().
1v70 Copyright 2014 G.Williams
>echo(0);
=undefined
down 0 3 0.11865415426 0.08740367742
down 0 3 0.11609063859 0.08813611047
up undefined undefined 0.04345769436 0.02355992980
down 231 6 0.85181963836 0.09472800793
up undefined undefined 0.03808651865 0.02075226977
down 232 312 0.85621423666 0.86243991760
down 233 311 0.85743495841 0.86060883497
down 232 311 0.85584802014 0.86073090714
up undefined undefined 0.04345769436 0.02490272373
down 5 314 0.13464560921 0.86915388723
down 3 314 0.12610055695 0.86903181506
up undefined undefined 0.04406805523 0.02331578545
down 119 154 0.49488059815 0.46802471961
up undefined undefined 0.04321355001 0.02331578545
>
Because Espruino IS the (software) controller - like the ADS7843 chip in the ADS7843 module - the TOUCHR module returns a (singleton) control object at connect() to provide additional access - control and data. The control object returns itself also in listen() and xy() methods, and is passed to callback as third (3rd) argument. On connect() or connect().listen(true), it is useful to hold on to the control module in a global variable named, for example, touchr:
var touchCallback = ;
var touchr = require("TOUCHR").connect(C0,C1,C2,C3,
function(x,y,t) {
// your code using x, y, and t(ouch control object)
}).listen(true);
Some displays have touch screens mounted that are larger than the active display area. These areas are called porches. Some touch screens show a blank porch and some have printed icons on it, such as a letter, a clock, a calendar, etc., to mark function buttons. The porch can be used as input but. The touch screen at hand has a bottom porch of about 30px. To use the porch, the controllers Y and yc touch screen parms have to be adjusted:
var ph = 30; // bottom porch height in px
touchr.X += ph; // increase y detection cut toff / limit by bottom porch height
touchr.xc += touchr.xd * ph / 2; // incr. y center touch value by 1 px value times half porch height
Adjustment can be done anytime after connecting. Remember though to consider the extra y range in the callback as well and do not use it for mapping to pixel position of the display:
var touchCallback = function(x,y,t) {
if (t) { // touching, x and y are defined
if (y < 320) { // touching in display area
// display code
} else { // touching in porch area
// porch code
}
}
};
Below code is the classic drawing 'application':
Tapping a color in the menu at the bottom picks it up for drawing.
Tapping +/- increases/decreases brush size; brush size shown in black cotouchlor selection.
Tapping the X clears the screen for a new drawing.
Notice the shortened tracking interval time passed on on connect (line 42). Colors of attached screen shot are 'a bit' off... angle and exposure and ambient light matter messed with capturing.
var touchr;
SPI1.setup({sck:B3, miso:B4, mosi:B5, baud: 1000000});
var lcd = require("ILI9341").connect(SPI1, B6, B8, B7, function() {
lcd.clear();
var n=2,w=20,rgb=[0,0,0];cs=[];x=-w,ym1=300,ym2=319;
(function(){
cs.push(rgb.slice(0));
lcd.setColor(rgb[0],rgb[1],rgb[2]);
x += w;
lcd.fillRect(x,ym1,x+w-1,ym2);
for (var r=0;r<n;r++) { rgb[0] = 1 / (r + 1);
for (var g=0;g<n;g++) { rgb[1] = 1 / (g + 1);
for (var b=0;b<n;b++) { rgb[2] = 1 / (b + 1);
cs.push(rgb.slice(0));
lcd.setColor(rgb[0],rgb[1],rgb[2]);
x += w;
lcd.fillRect(x,ym1,x+w-1,ym2);
}
}
}
lcd.setColor(1,1,1);
lcd.setFontVector(16);
x += w; lcd.drawString("+",x+3,ym1+2);
x += w; lcd.drawString("-",x+3,ym1+2);
x += w; lcd.drawString("X",x+3,ym1+3);
lcd.drawLine(0,ym1,239,ym1);
})();
var rad = 2, ymd = ym1 - rad - 1, cxm=cs.length-1,cdx = 0,ym;
lcd.setColor(0,0,0); lcd.fillRect(0,ym1+1,w-1,ym2);
lcd.setColor(1,1,1); lcd.setFontVector(10);
lcd.drawString(rad * 2 + 1,0,ym1+5);
rgb = cs[0]; lcd.setColor(rgb[0],rgb[1],rgb[2]);
touchr = touchrModule.connect(C0,C1,C2,C3,function(x,y,tr){
if (tr.t) {
if (y < ym1) {
ym = (y < ymd) ? y : ymd;
lcd.fillRect(x-rad,ym-rad,x+rad,ym+rad);
} else if (y >= ym1) {
cdx = Math.floor(x / w);
if (cdx <= cxm) {
rgb = cs[cdx];
lcd.setColor(rgb[0],rgb[1],rgb[2]);
}
}
} else {
if (tr.y >= ym1) {
cdx = Math.floor(tr.x / w);
if (cdx > cxm) {
if (cdx <= cxm + 2) {
rad = Math.round(rad + ((cdx == cxm + 1)
? (rad / 2) : (0 - rad / 3)));
rad = (rad < 2) ? 2 : (rad <= 42) ? rad : 42;
ymd = ym1 - rad - 1;
lcd.setColor(0,0,0); lcd.fillRect(0,ym1+1,w-1,ym2);
lcd.setColor(1,1,1); lcd.setFontVector(10);
lcd.drawString(rad * 2 + 1,0,ym1+5);
lcd.setColor(rgb[0],rgb[1],rgb[2]);
} else {
rgb = cs[0]; lcd.setColor(rgb[0],rgb[1],rgb[2]);
lcd.fillRect(0,0,239,ym1 - 1);
}
}
}
}
},{i:20}).listen(true); // track every 50 [ms] = 20Hz = 20 times/s
});
A calibration module for TOUCHR module will be presented in a separate post. It will help you to set or adjust the touch screen parms xt, yt, xc, yc, xd, and yd for your (same or different LCD w/) resistive touch screen (...c stands for expected value at the center, ...d for the difference between pixel. In a nutshell, the calibration module uses the read raw values of touches at known (displayed px) x / y locations to calculate the touch screen parms.
The above provided simple test code can be used to manually gather the raw values and do the calculations. Set pixels at defined x / y coordinates equally close to the corners (about 10 px away from the borders) and one in the center, touch them, and perform the calculations. Simple average and linear formulae are accurate enough:
xd = avrg of delta x raw touch values divided by delta x pixels
yd = avrg of delta y raw touch values divided by delta y pixels
xc = avrg of (sums of low and high x / 2) and center x values
yc = avrg of (sums of low and high y / 2) and center y values
xt = between avrg of x off and avrg of lowest x touch values
yt = between avrg of y off and avrg of lowest y touch values
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.
Below module code I intend to use for my resistive touch screen. It is a much lighter version of what you have seen from me so far. It is inspired by @Gordon 's ADS7843 touch controller module AND is - of course - 100% callback backward-compatible. Planned name for the module is TOUCHR - R for resistive.
The module includes the defaults configuration for any ILI9341 controlled 320x240 262K Color TFT LCD with resistive touch screen (used in 65K color mode). Any of the default LCD and touch screen parameters can be overwritten on connect() to use it with other displays and touch screen, and to manage variations between same touch screens.
Power consumption is optimized and can be lowered even more for touch tracking by setting the scan interval i at connect time or afterwards, even dynamically in callback depending tracking needs identified on particular touch.
The sample test code
shows the console output below on touching top-left, top-right, bottom-right, and bottom-left corner and the center of the LCD area. On touching, it shows the calculated x and y coordinates and the raw rx and ry values read by the ADC pins. On up (just once after touching) just the raw values read by the DC pin are shown. The touch thresholds (xt, yt) for detecting an un-touch are between the lowest read touch value and the up (un-touch) value and are different for x and y axis. Touches are detected by a hardware event caught by setWatch().
Because Espruino IS the (software) controller - like the ADS7843 chip in the ADS7843 module - the TOUCHR module returns a (singleton) control object at connect() to provide additional access - control and data. The control object returns itself also in listen() and xy() methods, and is passed to callback as third (3rd) argument. On connect() or connect().listen(true), it is useful to hold on to the control module in a global variable named, for example, touchr:
Some displays have touch screens mounted that are larger than the active display area. These areas are called porches. Some touch screens show a blank porch and some have printed icons on it, such as a letter, a clock, a calendar, etc., to mark function buttons. The porch can be used as input but. The touch screen at hand has a bottom porch of about 30px. To use the porch, the controllers Y and yc touch screen parms have to be adjusted:
Adjustment can be done anytime after connecting. Remember though to consider the extra y range in the callback as well and do not use it for mapping to pixel position of the display:
Below code is the classic drawing 'application':
Notice the shortened tracking interval time passed on on connect (line 42). Colors of attached screen shot are 'a bit' off... angle and exposure and ambient light matter messed with capturing.
A calibration module for TOUCHR module will be presented in a separate post. It will help you to set or adjust the touch screen parms xt, yt, xc, yc, xd, and yd for your (same or different LCD w/) resistive touch screen (...c stands for expected value at the center, ...d for the difference between pixel. In a nutshell, the calibration module uses the read raw values of touches at known (displayed px) x / y locations to calculate the touch screen parms.
The above provided simple test code can be used to manually gather the raw values and do the calculations. Set pixels at defined x / y coordinates equally close to the corners (about 10 px away from the borders) and one in the center, touch them, and perform the calculations. Simple average and linear formulae are accurate enough:
4 Attachments