ILI9341 Touch Screen debounce?

Status
Not open for further replies.

paynterf

Well-known member
Hi,

I have been working with a Teensy 3.2 connected to a ILI9341 TFT/Touch display from Paul's store, and I am having a problem debouncing the touch screen. I have a very simple sketch that takes a stylus touch point, maps it to an appropriate display coordinate, and draws a small filled circle at the mapped point. For each point I print out the program time in milliSec, the raw (touch screen) coordinates and the mapped display coordinates. I also have some 'debounce' code to prevent multiple touch detections from a single stylus tap. The debounce code works perfectly, UNLESS I tap on the lower left hand corner of the screen, where I get 10-15 touch detections even with the debounce code present. Here's the sketch:

Code:
/*
    Name:       KurtTouchV2.ino
    Created:	2/15/2021 4:16:52 PM
    Author:     FRANKNEWXPS15\Frank

*/

 //****************************************************************************
 // Includes
 //****************************************************************************
#include <XPT2046_Touchscreen.h>
#include <ILI9341_t3n.h>
#include "ili9341_t3n_font_Arial.h"

//****************************************************************************
// This is calibration data for the raw touch data to the screen coordinates
//****************************************************************************
// Warning, These are approximate values
#define TS_MINX 600
#define TS_MINY 600
#define TS_MAXX 3758
#define TS_MAXY 3612

#define SCREEN_ORIENTATION_1

//02/16/21 change from using #defines to variables, so can 
//  update via calibration.
uint16_t ts_minx = TS_MINX;
uint16_t ts_maxx = TS_MAXX;
uint16_t ts_miny = TS_MINY;
uint16_t ts_maxy = TS_MAXY;


//****************************************************************************
// Settings and objects
//****************************************************************************
//02/15/21 pin assignments from https://www.pjrc.com/store/display_ili9341_touch.html
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#define TOUCH_CS  8

XPT2046_Touchscreen ts(TOUCH_CS);
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO);

// Size of the color selection boxes and the paintbrush size
#define MAX_DISPLAY_X 240
#define MAX_DISPLAY_Y 320
#define NUMBOXES 7
//#define BOXSIZE MAX_DISPLAY_X / NUMBOXES
#define BOXSIZE 34
#define PENRADIUS 3
int oldcolor, currentcolor;

int BoxColorArray[] = { ILI9341_RED, ILI9341_YELLOW, ILI9341_GREEN, ILI9341_CYAN,
  ILI9341_BLUE, ILI9341_MAGENTA, ILI9341_WHITE, ILI9341_ORANGE, ILI9341_GREENYELLOW, ILI9341_PINK };

//****************************************************************************
// Setup
//****************************************************************************
void setup(void) 
{
  Serial.begin(9600);
  while (!Serial && (millis() <= 3000))
  {
    delay(100);
  }

  tft.begin();
  tft.setRotation(1);

  // by default use SPI
  if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
  Serial.println("Touchscreen started");


  tft.fillScreen(ILI9341_BLACK);
  }

void loop()
{
  // See if there's any  touch data for us
  // You can also wait for a touch
  if (!ts.touched()) 
  {
    return;
  }

  // Retrieve a point
  TS_Point p = ts.getPoint();

  Serial.printf("%lu: Raw P(%d,%d) maps to ", millis(), p.x, p.y);

  // Scale from ~0->4000 to tft.width using the calibration #'s
#ifdef SCREEN_ORIENTATION_1
  p.x = map(p.x, TS_MAXX, TS_MINX, 0, tft.width());
  p.y = map(p.y, TS_MAXY, TS_MINY, 0, tft.height());
#else
  uint16_t px = map(p.y, TS_MINY, TS_MAXY, 0, tft.width());
  p.y = map(p.x, TS_MAXX, TS_MINX, 0, tft.height());
  p.x = px;
#endif

  Serial.printf(" (%d,%d): ", p.x, p.y);
  Serial.printf("drawing circle at (%d,%d)\n", p.x, p.y);
  tft.fillCircle(p.x, p.y, PENRADIUS, ILI9341_RED);

  //touch screen debounce
  while (ts.touched())
  {
    p = ts.getPoint();
    delay(10);
  }
}

And a photo of the setup, showing some of the dots from the program

IMG_4055.jpg

And here's some of the printed output, showing individual stylus presses and then a run of touch detections spaced about 10 mSec apart, all with the same approximate coordinates; these were generated from just one stylus touch in the lower left hand corner (corner closest to the Teensy and farthest away from the prototype board)

Code:
Opening port
Port open
19651: Raw P(3766,3562) maps to  (0,3): drawing circle at (0,3)
29334: Raw P(708,3459) maps to  (309,12): drawing circle at (309,12)
38322: Raw P(3813,362) maps to  (-5,258): drawing circle at (-5,258)
38333: Raw P(3825,307) maps to  (-6,263): drawing circle at (-6,263)
38343: Raw P(3844,307) maps to  (-8,263): drawing circle at (-8,263)
38354: Raw P(3840,305) maps to  (-8,263): drawing circle at (-8,263)
38364: Raw P(3840,305) maps to  (-8,263): drawing circle at (-8,263)
38375: Raw P(3862,317) maps to  (-10,262): drawing circle at (-10,262)
38385: Raw P(3861,301) maps to  (-10,263): drawing circle at (-10,263)
38395: Raw P(3845,292) maps to  (-8,264): drawing circle at (-8,264)

Any ideas why this is happening?

TIA,

Frank
 
Last edited:
The library has no hysteresis for Z_THRESHOLD so will inherently generate noisy z-values. This
probably is an oversight. The Z-threshold(s) probably ought to be tweakable in the API too.

Your debounce time is perhaps too short at 10ms, and the reason one corner is particularly sensitive is
likely that its closer to the threshold at normal stylus pressure for no deep reason.
 
>> drawing circle at (-8,263)

This is probably not your issue but something I noticed:
Your calls to fillCircle with coordinates off the screen probably return without doing any drawing. So your program will not have whatever delay fillCircle provides when you touch in the corner.
 
I modified my sketch to just record raw touch screen data every 10mSec during touch periods, and then touched each corner in turn for about 1 second, trying to apply approximately the same pressure each time. When I graphed the results in Excel I got the following chart

210228 CornerZVals1.jpg

The last segment of this chart is from the press event in the lower left-hand corner - the same corner that is giving me problems with the de-bounce code. It now appears that the problem with this corner isn't too much[ sensitivity, but too little. I've repeated this test a number of times, and it comes up the same way - that one corner is MUCH less sensitive than the others

Then I drew a rectangle, starting from UL to UR to LR to LL and then back to UL, offset about 8mm in from each edge, resulting in the following chart. I tried to keep the touch pressure as constant as possible during the procedure.

210228 CornerZVals2.jpg

The 'dip' in the graph corresponds to approaching and departing from the LL corner. Looks like this particular display is very insensitive in that one corner.

Frank
 
rcarr,

Thanks for the head-up! I noticed the off-screen coordinates but didn't think much of them at the time. I figured I would handle that later, when I actually had something working ;-)

Frank
 
I made some further tests by drawing a continuous rectangle starting at the upper left-hand corner and proceeding clockwise around the screen, ending up at upper left again. I did this twice - once with the rectangle as close to the screen edges as I could, and a second time with a smaller rectangle more-or-less centered in the display (see the photos). On each pass I recorded the X/Y coordinates as mapped to display pixel space, and the touchscreen pressure (Z-axis) value. When I charted the results it was clear that the lower left-hand region of the display has significantly lower Z-axis output.

Has anyone else had this experience or have some thoughts about these results?

TIA,

Frank

IMG_4057.jpg

IMG_4056.jpg

210228 LargeRectangleZValues.jpg
210228 SmallRectangleZValues.jpg
 
Frank:

I can imagine that it would be almost impossible to keep the pressure on the display constant as the rectangle is drawn. Would you expect a different result if the test was run four times, rotating the display 90 degrees between tests. That way, you can see if the lower sensitivity follows the specific corner, or if it might be either a result of the way the rectangle is drawn, or exacerbated by the method. You may be able to remove some of the variability by using an object (e.g. a large ball bearing) to rest on the display, which would provide an almost constant pressure. Food for thought . . .

Mark J Culross
KD5RXT

P.S. I likewise experienced an insufferable variability in the touch point that was being detected when touching near the edges of my PJRC touchscreen (which made it almost impossible to layout my graphical touch sliders all the way to the edge of my screen). Turns out in my particular case, I was causing my own problem by trying to read the touchscreen way too quickly. A simple delay between touchscreen reads fixed the particular problem that I was seeing in my project. Hopefully yours turns out to be equally easy to find & fix. MJC
 
Mark,

Do you happen to remember what delay you found to be most effective? Where you just delaying, or averaging multiple readings?

To address your thoughts about the pressure variation being due to stylus pressure variations as a result of hand position/rotation, I ran another experiment where I first drew a rectangle in the original orientation to verify that the 'low output' phenomenon still existed (it did) and then physically rotated the entire prototype assembly 180 degrees so that now the UL corner was originally the LR corner. Then I drew the same rectangle using the same technique (as near as I could tell, anyway) and recorded the result in the chart shown below

210228 LargeRectangleRotated180ZValues.jpg

As I think you can see, now the second corner is the low output one, and this is the same physical corner as before. If the low output was occurring due to different pressure imposed by a biomechanics issue of some sort, I would expect it would show up in the third corner, not the second.

Thoughts?
 
As I think you can see, now the second corner is the low output one, and this is the same physical corner as before. If the low output was occurring due to different pressure imposed by a biomechanics issue of some sort, I would expect it would show up in the third corner, not the second.

Thoughts?

Had another look at the XPT2046 library code and it doesn't calculate Z values as per the datasheet, so its
sentitivity is inherently poor in one corner. The raw readings of x, y, z1, z2 have to be combined in an
equation to determine the touch resistance, and this equation requires knowing the x and y resistances of
the particular touchscreen to be properly calibrated, although I think only the ratio between them matters
so its not so critical (but not applying the equation is always going to be poor).
 
Interesting - I had seen some documentation in some of the Adafruit example code about measuring the X & Y resistance values, but since there seemed no way to do that with the PJRC displays using the XPT2046 chip I basically ignored it.

Is there a way to measure these values? I don't see anything obvious on my display. I guess I could cheat by reverse engineering the values needed to normalize the pressure readings in all four corners ;-)

Frank
 
Mark,

Do you happen to remember what delay you found to be most effective? Where you just delaying, or averaging multiple readings?

[snipped]

As I think you can see, now the second corner is the low output one, and this is the same physical corner as before. If the low output was occurring due to different pressure imposed by a biomechanics issue of some sort, I would expect it would show up in the third corner, not the second.

Thoughts?

Frank:

Yup, your 180 test confirms that (as you put it) "biomechanics" is not a major contributing factor . . . well done !!

My current project uses a millis() comparison set at 200ms (in loop(), don't take another touchscreen reading unless/until 200ms have elapsed since the last reading) & no averaging, but in my experimentation, I started seeing a positive effect at 100ms between readings. My first stab at averaging (keeping a running average, 5-values deep) caused a different problem: as my touchpoints moved across the screen (touch a point on a slider towards the left-hand side of the screen, release, then touch a point on a different slider towards the right-hand side of the screen), the touch point averaging was triggering sliders everywhere in between as the average made its way from the left-hand touch to the right-hand touch . . . most likely just very bad coding !! Simply delaying between reads settled things well enough that I did not need the additional averaging.

Mark J Culross
KD5RXT
 
MarkT,

That is a very good idea, but I don't have a clue where to find the X-/X+ and Y-/Y+ terminals. There's nothing labeled like that anywhere on the display I have from PJRC (or eBay), and I've even popped the display out of its spring-loaded clips to have a look at the back.

Can someone post a photo showing how to access these terminals

TIA,

Frank
 
Resistive touchscreens are an overlay, typically having a 4 wire flat-flex cable going the PCB in a different place to the
main CoG flatflex.
 
MarkT,

I understand the physics - I just can't find a way to physically access the X+/X- & Y+/Y- wires. Here's a photo of the back of the display, showing the flex cable routing. There doesn't appear to be any easy way to put a probe on these wires - am I missing something?

IMG_4058.jpg
 
Well I guess you just have to assume they are the same, or close enough, and apply the equations anyway - the
test circuit is ratiometric so the absolute resistance isn't important.
 
Status
Not open for further replies.
Back
Top