Issue with Adafruit TFT 2.4" touch panel

I’m having an issue with the Adafruit 2.4" TFT touchscreen panel. In essence, everything seems to work fine, except the touchpoint I’m receiving is always the previous one.

I have the touch panel effectively divided into 3 portions. We’ll call them top, middle and bottom. When the device first starts and I touch, I don’t get a point printed out. However, upon the second touch, I’m getting the coordinates of the first touch. Then with each subsequent touch, I get the prior touch’s location. I can see this as I move from “top”, to “middle” or “bottom”.

I’m sure I’m doing something dumb here, but can’t see it. The library that was loaded was the 1.0.1 version ported by @rickkas7. I noticed the library is now up to 1.3.1(?), so I copied the code from that library and posted it into my .cpp and .h library files, hoping that might resolve the issue. However, it had no effect. The one change with the newer version is that it does empty the buffer when calling ts.getPoint() to return the “last” touch coordinates.

Here’s the relevant code from my app. Yes, it’s pretty simple, but just the starting point. Once I get this working properly, then I need to call some webhooks to change Ecobee thermostat settings. It’s an interesting project, but just a wee bit frustrating right now due to this issue and I’m hoping someone can shed some light on what I’m doing wrong.

Here’s the relevant code:


//Create the display object
Adafruit_ILI9341 tft(TFT_CS, TFT_DC); //create display object
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS); //create touch object

boolean processTouch = true; //used to indicate if touchscreen should be ignored while finger is held down

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


//the main loop
void loop() {
  if (ts.touched()) {
    //Serial.println("touched");
    if (processTouch) {
      getXYZ();
    }
    processTouch = false;
  }
  else {
    count = 0;
    processTouch = true;
    //Serial.println("not touched");
  }
}

void getXYZ() {
  if (!ts.bufferEmpty()) {
    count += 1;
    p = ts.getPoint();
    if (!ts.bufferEmpty()) {
      Serial.println("Buffer wasn't empty");
      p = ts.getPoint();
    }
    x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
    y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
    z = p.z;
    Serial.print("Final x=");Serial.print(x);
    Serial.print(", Final y=");Serial.print(y);
    Serial.print(", Final z =");Serial.print(z);
    Serial.print(", Count = ");Serial.println(count);
    delay(10);
  }
}

By the way, it never prints “Buffer not empty” and always prints count=1.

I’m not sure if this is a problem or not, but the sample code clears the interrupt after reading the coordinates. Your code doesn’t seem to do that:

Also, when pasting a library into a project make sure you delete the library from included libraries (Web IDE) or project.properties file and also delete the library from the lib directory (Workbench) otherwise you are likely to get the wrong version of the code.

Also make sure you apply the change in the _RK version of the library to enable SPI transactions if using it in SPI mode, otherwise bad things can happen if the SPI bus is used by anything else.

2 Likes

@rickkas7, I’m doing development in Workbench. I actually opened the ADAFRUIT_STMPE610.cpp file in the library folder and pasted the newer .cpp code into it and did the same with the .h file. The newer version of the .cpp file includes the following code, which I believe addresses the issue you were referencing:

/*!
 *  @brief  Returns point for touchscreen data
 *  @return The touch point using TS_Point
 */
TS_Point Adafruit_STMPE610::getPoint() {
  uint16_t x, y;
  uint8_t z;

  /* Making sure that we are reading all data before leaving */
  while (!bufferEmpty()) {
    readData(&x, &y, &z);
  }

  if (bufferEmpty())
    writeRegister8(STMPE_INT_STA, 0xFF); // reset all ints

  return TS_Point(x, y, z);
}

I had hoped the newer version of the library which reads through the buffer for the last entry would resolve my issue. Alas, it did not. My Featherwing is a year or two old. Perhaps its firmware has been changed to address this issue.

BTW, thanks so much for offering your thoughts!

Voila! After pulling my hair out and doing more searching for recommendations, I fortunately stumbled across the following via softsolder.

Turns out there are issues with how the buffer is managed and I’m guessing it usually not an issue, unless you’re trying to use the panel as a touchscreen with “buttons” on it and absolutely need the accurate touch point each and every time. This works great for my app and I thought I’d share in case someone else wants to use this touchscreen in a similar fashion.

Here’s my main loop:

void loop() {
  if(CleanTouch(&holdP)) {
    while (ts.touched())
      ts.getPoint();
    Serial.print("x=");Serial.print(holdP.x);Serial.print(", y=");Serial.println(holdP.y);
  }
}

And here’s the procedure that cleans up the touchpoints:

boolean CleanTouch(TS_Point *p) {
  TS_Point t;
  // Sort out possible touch and data queue conditions
      if (ts.touched())                           // screen touch?
          if (ts.bufferEmpty())                   //  if no data in queue
            return false;                       //   bail out
          else                                    //  touch and data!
            t = ts.getPoint();                  //   so get it!
      else {                                      // no touch, so ...
        while (!ts.bufferEmpty())               //  drain the buffer
            ts.getPoint();
        return false;
      }
  #if TS_TRACE
    Serial.printf("Raw touch (%d,%d)\r\n",t.x,t.y);
  #endif
  #if TS_TRACE
    Serial.printf(" constrained (%d,%d)\r\n",t.x,t.y);
    Serial.printf(" TFT (%d,%d)\r\n",tft.width(),tft.height());
  #endif
  p->y = map(t.y, TS_MAXY, TS_MINY, 0, tft.height());     
  p->x = map(t.x, TS_MAXX, TS_MINX, 0, tft.width());        
  p->z = t.z;
  #if TS_TRACE
    Serial.printf(" Clean (%d,%d)\r\n",p->x,p->y);
  #endif
  return true;
}
2 Likes