2.8" ILI9341 touch screen calibration issue

odd issue with an ILI9341 based screen, module is TJCTM24028-SPI 2.8" TFT SPI module, XPT2046 touch screen, nice SD card on the back.

using the adafruit libraries, connected to a 3.3v 8MHz Pro Mini, currently just playing with the screen - this has worked fine on a DUE previously.

issue is a simple programme (code below) - starts up, calibrates, then runs - draws a pixel where you touch it and shows the X,Y as text.

calibration routine is essentially the supplied one, re-written not to use UGCLib (change the drawing routines the the adafruit library, may end up going back)

problem, the touch screen works, for low values of X, goes a bit higher and it goes odd.

e.g. X,Y, reports as 56184,34, which is slightly outside the screen area.

have compared the re-written calibration routine to the UGCLib calibration routine, both output similar values and the UGCLib based touch screen drawing test has the same behaviour.

wondering, does this likely mean the touch screen is FUBAR?

have tried to "adjust" the values, basically by shifting by a constant, however the "constant" needed varies...

thoughts?

#include <Adafruit_TFTLCD.h>
#include <pin_magic.h>
#include <registers.h>
#include <XPT2046.h>

// test code, for Pro Mini, 3.3v 8MHz
// 2.8" TFT board

#define ScreenCS    4       // screen  select
#define ScreenLED   5       // screen LED backlight
#define ScreenReset 6       // screen reset
#define ScreenDC    7       // screen data/command

#define SDCS        8       // SD card select

#define TouchCS     9       // touch screen select
#define TouchIRQ    3       // touch screen interrupt

// screen is ILI9341
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>


Adafruit_ILI9341 tft = Adafruit_ILI9341(ScreenCS, ScreenDC);
XPT2046 touch(TouchCS, TouchIRQ);

void setup() {
  // put your setup code here, to run once:
  pinMode(ScreenLED, OUTPUT);
  pinMode(ScreenReset, OUTPUT);

  digitalWrite(ScreenLED, HIGH);    // turn on backlight
  digitalWrite(ScreenReset, HIGH);  // screen exit reset mode

  tft.begin();
  
  tft.fillScreen(ILI9341_BLACK);    // black out the screen
  touch.begin(240, 320);
  TouchCalibrate();                 // run calibration routine
  
  tft.setRotation(0);     // 0: SD card header top, portrait, (240x320)
                          // 1: SD card header right, landscape
                          // 2: SD card header bottom, portrait
                          // 3: SD card header left, landscape

  
  touch.setRotation(touch.ROT0);    // ROT0, ROT90, ROT180 or ROT270
  //touch.setCalibration(209, 1759, 1775, 273);     // need to update these for the specific panel


  // fill background black
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setCursor(5,5);
  tft.setTextSize(2);     // 1: small (not very readable), 2: twice the height (readable)
  tft.println("Hello");

  // draw a bit of a frame
  tft.drawFastHLine(0, 0, tft.width(), ILI9341_WHITE);  // top
  tft.drawFastHLine(0, tft.height()-1, tft.width(), ILI9341_WHITE);  // bottom
  tft.drawFastVLine(0,0, tft.height(), ILI9341_WHITE);  // left
  tft.drawFastVLine(tft.width()-1, 0, tft.height(), ILI9341_WHITE);   // right
  
}

void loop() {
  // put your main code here, to run repeatedly:

  // if screen is touched, draw a pixel and write out coordinates
  if (touch.isTouching())
  {
    uint16_t x,y;
    uint16_t x1,y1;
    touch.getPosition(x,y);
    if (x > 20)
    {
      x1 = x-56000;
    }
    else
    {
      x1=x;
    }

    //tft.drawCircle(x-1, y-1, 3, ILI9341_WHITE);
    tft.drawPixel(x, y, ILI9341_WHITE);
    tft.setCursor(5,25);
    tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    tft.print(x);
    tft.print(", ");
    tft.print(y);
    tft.println("              ");    // blank to overwrite previous if needed
    tft.print(x1);
    tft.print(", ");
    tft.print(y1);
    tft.println("              ");
  }
}

static void calibratePoint(uint16_t x, uint16_t y, uint16_t &vi, uint16_t &vj) {
  // Draw cross
  tft.drawFastHLine(x-8, y, 16, ILI9341_WHITE);
  tft.drawFastVLine(x,y-8, 16, ILI9341_WHITE);
  
  while (!touch.isTouching()) {
    delay(10);
  }
  touch.getRaw(vi, vj);
  // Erase by overwriting with black
  tft.drawFastHLine(x-8, y, 16, ILI9341_BLACK);
  tft.drawFastVLine(x,y-8, 16, ILI9341_BLACK);
}

void TouchCalibrate(void)
{
  uint16_t x1, y1, x2, y2;
  uint16_t vi1, vj1, vi2, vj2;
  touch.getCalibrationPoints(x1, y1, x2, y2);
  calibratePoint(x1, y1, vi1, vj1);
  delay(1000);
  calibratePoint(x2, y2, vi2, vj2);
  touch.setCalibration(vi1, vj1, vi2, vj2);

  char buf[80];
  snprintf(buf, sizeof(buf), "%d,%d,%d,%d", (int)vi1, (int)vj1, (int)vi2, (int)vj2);

  // calibration results: 267,1672,1736,298

  tft.setCursor(5,5);
  tft.println("Screen Calibration");
  tft.println(buf);
  delay(5000);
  
}

Please post link to the actual display that you have bought. e.g. Ebay sale page.

Yes, you can quote an official Arduino board just by name e.g. Uno, Mega2560, ...
But third party boards are better shown with the specific web page.

It means that we can recognise most boards immediately. Otherwise we have to Google and guess.

Regular third party libraries can be installed via IDE Library Manager e.g.
Adafruit_GFX.h
Adafruit_ILI9341.h

It is wise to use the Manager to check for Updates, version numbers etc
Anyone, anywhere in the world can find those libraries through the Manager.

If you are using any library that is not available via the IDE Library Manager, please post a link to that library.
e.g.
pin_magic.h
registers.h
XPT2046.h

David.

the board is one of these beasties

the Adafruit libraries came via github, ditto the XPT2046 one, for a range of irritating issues I can't install libraries via the IDE here so have to drop them in manually

TJCTM24028-SPI is whats printed on the board and is basically how I found out how to get it working, note that it has worked before - the XPT2046 does report correct values, when the values are in the range 0-20 for x & 20+ for y, but then goes a bit daft.

there is a work around which is to calibrate once, hardcode the results then manually workout offsets to apply - works well for this specific board but needs recalculating for another one of the same type

pin_magic.h & register.h came via the adafruit example I started with and seem to come down with the adafruit graphics library

for ref examples of what the touch screen reports via "get.Position(x,y)" and what they actually should be:

16,241 - which is 16,241 and thus correct
11,295 - as above, correct
15,11801 - which should be 15,16, x value correct, y value offset by 11785
56990,218 - which should be 139,218, x value offset by 56851, y value correct
57066,11799 - which should be 215,14, neither correct and both offsets applied

essentially wondering if this means the touch panel is somehow mucked up or if this is likely a code muck up, it doesn't seem to be overflowing, can fire up and touch, gradually moving and watch X & Y change, x starts at 0, gradually increases, 18, 19, 20, 56871, 56872, 56873... y is similar.

calibration values the routine reports are 206, 1759, 1763 & 250, which are not massively different from the example.

the Adafruit libraries came via github, ditto the XPT2046 one, for a range of irritating issues I can't install libraries via the IDE here so have to drop them in manually

So please post the GitHub links.

And I suggest that you resolve your irritating issues.

Seriously, your sketch has serious problems.

If you provide accurate information we might help you.

David.

the "irritating" issue is a corporate firewall, its not moving, its annoying but can work around it - by downloading directly from Github and installing via the "add .zip library" method - basically the IDE cannot phone out, this is not changing any time soon - its also why this is being tested on the pro-mini (because the base install supports it) and not the DUE (because it doesn't)

aware the sketch almost certainly has issues, thats part of the reason for posting it

XPT2046 library GitHub - spapadim/XPT2046: Arduino library for XPT2046 / ADS7843 touchscreen driver
ILI9341 library GitHub - adafruit/Adafruit_ILI9341: Library for Adafruit ILI9341 displays
Adafruit GFX library GitHub - adafruit/Adafruit-GFX-Library: Adafruit GFX graphics core Arduino library, this is the 'core' class that all our other graphics libraries derive from
Adafruit TFTLCD library GitHub - adafruit/TFTLCD-Library: Arduino library for 8-bit TFT LCDs such as ILI9325, ILI9328, etc --> includes pin_magic.h & registers.h

the sketch is largely a very basic outline - fill the screen black, draw a white rectangle frame etc - the screen bit works just fine for the display - its not perfect, it was intended to provide something to see if the board was working.

the calibratePoint() routine is from the XPT2046 library, with the screen drawing routines changed to the tft library I'm using - the rest is copy & paste, ditto the touchCalibrate() routine, only changed the drawing code

note these code sources have been used previously and it worked just fine with the same calibration and touch screen library.

Thanks for the links. Only the XPT2046 was necessary because the Adafruit libraries are available through the Library Manager.

The XPT2046.h library has a Calibration example for Ucglib.h
You just need to adapt it for Adafruit_ILI9341.h

Which means that you remove all the unused includes like TFTLCD, magic etc
Translate the Ucglib calls to GFX methods.

It looks as if you have done the translation ok.

I will download the XPT2046 library and debug your sketch on a similar TFT. (a bit later)

David.

many thanks, also for the heads up on un-needed libraries

I'm expecting to find this is a hardware fault of some sort, seems odd it could work for part of the screen and return incorrect values for another part.

Your sketch was massively different to the XPT2046.h example.

  1. I translated the XPT2046.h example for Adafruit_ILI9341
  2. It "calibrated" but subsequent getPosition() calls were crap
  3. I built the original ucg example
  4. It "calibrated" but subsequent getPosition() calls were crap

Since everything is wrong it requires some investigation.

I have had good results with XPT2046_Touchscreen.h library which is supported by the Library Manager.

David.

cheers for the headsup, the only bits I brought over was the calibration stuff, which runs and gives a roughly expected output.

after that its "meah" but can be corrected, mostly.

will see if I can find that library, maybe at home and email it to myself.

have used this one before fine though, which is odd.

if something else works better though, will have a go.

my thanks for taking the time to have a look though :slight_smile:

The XPT2046 Repository on GitHub is 4 years old. The author has never responded to Issues or Pull Requests.

If you apply the Fix Overflow Pull Request it solves the problem.
However the library mapping does not really work for different display rotations.

I still recommend XPT2046_Touchscreen. You map the ADC values for the current rotation in the application.

There are lots of libraries on GitHub. I suggest that you only install the ones that are "approved" by the Library Manager.
Other repositories may be 100% reliable but treat with caution.

David.