DustinWatts / FT6236

Arduino Library for the FocalTech FT6236. Also works with ESP boards.
MIT License
34 stars 9 forks source link

Touches regularly return an incorrect `0:0` x:y coordinate #3

Closed danielhunt closed 3 years ago

danielhunt commented 3 years ago

While investigating regular odd/wrong touch behaviour I've found that the touch screen reports a 0:0 coordinate for a touch sometimes when it shouldn't.

This is a problem because it can sometimes result in a button tap not registering (or worse, auto-tapping a button that's sitting @ 0:0 on the screen)

I have narrowed the source of the problem to this line: https://github.com/DustinWatts/FT6236/blob/main/FT6236.cpp#L74 ... but I don't know what the solution is yet. That line does have valid coordinates in touchX and touchY (verified by adding a print line: Serial.printf("xxx: n / x:y --- %d / %d:%d", n, touchX[n], touchY[n]);) but it's returning 0:0 because it's told to.

I'm using this code below to verify things - if you just keep tapping the screen eventually it flashed red (keep an eye on the serial output to see it happen there too, with coordinate information)

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

#include <FT6236.h>
FT6236 ts = FT6236();

bool needsReset = false;

void reset() {
  needsReset = false;
  tft.fillScreen(TFT_BLACK);
  tft.setTextFont(2);
  tft.println(" Touch test - keep tapping. When an incorrect (0:0) coordinate is returned for a tap the screen will turn red...");
}

void setup(void) {
  Serial.begin(115200);

  if (!ts.begin(40)) {
    Serial.println("[WARNING]: Unable to start the capacitive touchscreen");
  }
  else {
    Serial.println("[INFO]: Capacitive touch started");
  }

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

  reset();
}

void loop() {
  if (ts.touched())
  {
    // Retrieve a point
    TS_Point p = ts.getPoint();

    //Flip things around so it matches our screen rotation
    //intentionally flipped for the FreeTouchDown display
    uint16_t t_x = p.y;
    uint16_t t_y = (uint16_t)map((long)p.x, (long)0, (long)tft.height(), (long)tft.height(), (long)0);

    // print out the originally detected coordinates, followed by the screen dimensions, followed by the converted
    // coordinates *for every touch*
    Serial.printf("touch x:y - %d:%d (%d/%d)    -> %d:%d\n", p.x, p.y, tft.width(), tft.height(), t_x, t_y);

    if (p.x == 0 && p.y == 0) {
      Serial.println("=============================================");
      Serial.printf("                    %d : %d\n", p.x, p.y); //How is this possible?
      Serial.println("=============================================");

      needsReset = true;
      tft.fillScreen(TFT_RED);
    } else if (needsReset) {
      reset();
    }
  }
}
danielhunt commented 3 years ago

Funnily enough, when I use the FT6x36 library instead of your this one, I don't have the same problem.

Here's my test code for that library:

#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

#include <Arduino.h>
#include <Wire.h>
#include <FT6X36.h>

FT6X36 ts(&Wire, 27); // 27 is needed for the FreeTouchDeck

bool needsReset = false;

void reset() {
  needsReset = false;
  tft.fillScreen(TFT_BLACK);
  tft.setTextFont(2);
  tft.println(" Touch test - keep tapping. When an incorrect (0:0) coordinate is returned for a tap the screen will turn red...");
}

void touch(TPoint p, TEvent e) {
  if (e != TEvent::TouchStart) {
    return;
  }

  //Flip things around so it matches our screen rotation
  //intentionally flipped for the FreeTouchDown display
  uint16_t t_x = p.y;
  uint16_t t_y = (uint16_t)map((long)p.x, (long)0, (long)tft.height(), (long)tft.height(), (long)0);

  // print out the originally detected coordinates, followed by the screen dimensions, followed by the converted
  // coordinates *for every touch*
  Serial.printf("touch x:y - %d:%d (%d/%d)    -> %d:%d\n", p.x, p.y, tft.width(), tft.height(), t_x, t_y);

  if (p.x == 0 && p.y == 0) {
    Serial.println("=============================================");
    Serial.printf("                    %d : %d\n", p.x, p.y); //How is this possible?
    Serial.println("=============================================");

    needsReset = true;
    tft.fillScreen(TFT_RED);
  } else if (needsReset) {
    reset();
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println(F("Starting..."));

  Wire.begin();

  if (!ts.begin(40)) {
    Serial.println("[WARNING]: Unable to start the capacitive touchscreen");
  }
  else {
    Serial.println("[INFO]: Capacitive touch started");
  }
  ts.registerTouchHandler(touch);

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

  reset();
}

void loop() {
  ts.loop();
}
DustinWatts commented 3 years ago

I don't have a quick fix, I have to dive in the library again. It has been a while since I made this. It is basically a simplified version of the Adafruit library. I also never ran in to this problem, because besides checking if touched, I also check if the touch falls within the boundary of a button. And since there is never a button with at 0:0 this is not a problem.

How did you run in to this, if I may ask? And how frequent does it happen?

DustinWatts commented 3 years ago

Btw... i just tried your code and it only happens when I use two or more fingers rapidly touching in different positions with a very light touch. You could try and play with the sensitivity ts.begin(40). Another simple solution would be checking if an X or Y coordinate is not 0.

danielhunt commented 3 years ago

How did you run in to this, if I may ask? And how frequent does it happen?

I'm building an alternative (very basic) UI that displays some coloured buttons on a grid. When you tap a colour, that colour gets selected with an outline, and a rest HTTP command is sent over Wifi to a Shelly device controlling an RGB LED strip.

I've found that the selection logic is de-selecting the colour I'm tapping because the screen is reporting a tap on 0:0, which removes the currently selected outline (which is intentional - but the 0:0 isn't)

danielhunt commented 3 years ago

This is only really a problem because I want a non-selected touch to do something (deselect the currently selected colour)

Otherwise I would never have spotted it

danielhunt commented 3 years ago

it only happens when I use two or more fingers rapidly touching in different positions with a very light touch

It happens reliably for me with just one finger .. but I noticed earlier that it usually happens on release as opposed to on touch

danielhunt commented 3 years ago

Incase you're interested I've pushed my full (working) code now - https://github.com/danielhunt/FreeTouchShelly

It looks like that other library works well. Maybe I should just continue using that, and close this issue?

DustinWatts commented 3 years ago

You should of course use whichever library works the best for you :) I will add a check to the example code to make sure to ignore 0:0

The FreeTouchShelly looks great btw :)