2.8" TFT Touch Shield v2 with UNO

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
asteroid
 
Posts: 300
Joined: Tue Oct 22, 2013 9:10 pm

2.8" TFT Touch Shield v2 with UNO

Post by asteroid »

1) I'm unable to get the touch screen to report a single touch using (!tx.bufferEmpty()) and ts.getPoint(). It returns multiple points, usually 3-4 (see data). Is there any way that I could get the 'cluster' of points to be returned as a single touch? 2) I'm also unable to get ts.touched() to work correctly; it returns output repeatedly with each loop and does not appear to be triggered by a touch to the screen. It appears to be returning that the screen is touched all the time, when in fact it is not.

Data from Serial Monitor:

Touchscreen started.
(138, 183)
Screen touched ...0
====================
(138, 183)
Screen touched ...1
====================

(194, 101)
Screen touched ...2
====================
(194, 103)
Screen touched ...3
====================
(195, 104)
Screen touched ...4
====================

(41, 269)
Screen touched ...5
====================
(46, 267)
Screen touched ...6
====================
(51, 274)
Screen touched ...7
====================
(45, 275)
Screen touched ...8
====================


This is the Arduino sketch:

Code: Select all

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

int counter = 0;

void setup(void)
{
  Serial.begin(9600);
  tft.begin();
  Serial.println("Touchscreen started.");
  if (!ts.begin()) { Serial.println("Unable to start touchscreen."); } 
  tft.fillScreen(ILI9341_BLUE);
}

void loop()
{
 // See if there's any  touch data for us
  if (!ts.bufferEmpty())
  {
  // Retrieve a point  
  TS_Point p = ts.getPoint();
   // Scale from ~0->4000 to tft.width using the calibration #'s
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());

  Serial.print("("); Serial.print(p.x);
  Serial.print(", "); Serial.print(p.y);
  Serial.println(")");
  Serial.print("Screen touched ...");
  Serial.println(counter);
  Serial.println("====================");
  counter++;
  return;
  }
  // You can also wait for a touch
  if ( ts.touched())
  {
   // Serial.println("This is printed repeatedly.");
    return;
  }
    
}
Last edited by adafruit_support_rick on Thu Jan 30, 2014 10:16 am, edited 1 time in total.
Reason: please use [code][/code] tags when posting code

User avatar
Franklin97355
 
Posts: 23912
Joined: Mon Apr 21, 2008 2:33 pm

Re: 2.8" TFT Touch Shield v2 with UNO

Post by Franklin97355 »

It helps if you post your code between

Code: Select all

 tags.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 2.8" TFT Touch Shield v2 with UNO

Post by adafruit_support_rick »

Asteroid wrote:1) I'm unable to get the touch screen to report a single touch using (!tx.bufferEmpty()) and ts.getPoint(). It returns multiple points, usually 3-4 (see data). Is there any way that I could get the 'cluster' of points to be returned as a single touch?
Nope. You'll have to disambiguate that in your sketch.
Asteroid wrote:2) I'm also unable to get ts.touched() to work correctly; it returns output repeatedly with each loop and does not appear to be triggered by a touch to the screen. It appears to be returning that the screen is touched all the time, when in fact it is not.
Clearly, that doesn't work, but I don't know why. The library is testing the value of a touch register, and I don't know why that's returning an invalid indication
Edit: I've added an issue report to the library on github.

User avatar
asteroid
 
Posts: 300
Joined: Tue Oct 22, 2013 9:10 pm

Re: 2.8" TFT Touch Shield v2 with UNO

Post by asteroid »

> You'll have to disambiguate that in your sketch.

Thanks Rick. Here's my disambiguation:

Code: Select all

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

boolean RecordOn = false;

void frame()
{
 tft.drawRect(210, 180, 100, 50, ILI9341_BLACK);
}

void redBtn()
{
 tft.fillRect(212, 182, 45, 45, ILI9341_RED);
 tft.fillRect(260, 180, 50, 50, ILI9341_BLUE);
 frame();
 tft.setCursor(tft.width() - 50, tft.height() - 42);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(2);
 tft.println("ON");
 RecordOn = false;
}
 
void greenBtn()
{
 tft.fillRect(262, 182, 45, 45, ILI9341_GREEN);
 tft.fillRect(210, 180, 50, 50, ILI9341_BLUE);
 frame();
 tft.setCursor(tft.width() - 100, tft.height() - 42);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(2);
 tft.println("OFF");
 RecordOn = true;
}
 
void setup(void)
{
 Serial.begin(9600);
 tft.begin();
 if (!ts.begin()) { 
   Serial.println("Unable to start touchscreen.");
   } else { 
   Serial.println("Touchscreen started."); }
 tft.fillScreen(ILI9341_BLUE);
 // origin = left,top landscape (USB left upper)
 tft.setRotation(1); 
 redBtn();
 frame();
}

void loop()
{
  // See if there's any  touch data for us
  if (!ts.bufferEmpty())
  {   
  // Retrieve a point  
  TS_Point p = ts.getPoint(); 
  // Scale from ~0->4000 to tft.width using the calibration #'s
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
  // Compensate for rotation
  int x = tft.height() - p.x;
  int y = p.y;
  Serial.print("("); Serial.print(x);
  Serial.print(", "); Serial.print(y);
  Serial.println(")");
  if(x < 200 && y < 180) {Serial.println("Red btn hit"); redBtn(); frame();}
  if(x < 200 && y > 180) {Serial.println("Green btn hit"); greenBtn(); frame();}
  Serial.println(RecordOn);
  return;
 }  
}
Are you interested in short demos like the one above? If so, where would be the best place to post them?

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 2.8" TFT Touch Shield v2 with UNO

Post by adafruit_support_rick »

That's not a bad little demo. If you don't mind, I'd actually like to put it in the library as an example. But it still has a couple of problems:
1)areas outside of the button are detected as button hits. Touch anywhere over on the left, and it registers as "Red Button Hit". Touch anywhere above the green button, and it registers as "Green Button Hit"
2) I'm still seeing multiple detection events of single touch points, according to the serial trace. Weren't you trying to eliminate that?

User avatar
asteroid
 
Posts: 300
Joined: Tue Oct 22, 2013 9:10 pm

Re: 2.8" TFT Touch Shield v2 with UNO

Post by asteroid »

> 1) areas outside of the button are detected as button hits.

Thanks for the feedback. New code is near bottom; nested 'ifs' could likely be rewritten to be more elegant, but it works and I could not get more 'elegant' code to work.

Code: Select all

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

boolean RecordOn = false;

void frame()
{
 tft.drawRect(210, 180, 100, 50, ILI9341_BLACK);
}

void redBtn()
{
 tft.fillRect(212, 182, 45, 45, ILI9341_RED);
 tft.fillRect(260, 180, 50, 50, ILI9341_BLUE);
 frame();
 tft.setCursor(tft.width() - 50, tft.height() - 42);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(2);
 tft.println("ON");
 RecordOn = false;
}
 
void greenBtn()
{
 tft.fillRect(262, 182, 45, 45, ILI9341_GREEN);
 tft.fillRect(210, 180, 50, 50, ILI9341_BLUE);
 frame();
 tft.setCursor(tft.width() - 100, tft.height() - 42);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(2);
 tft.println("OFF");
 RecordOn = true;
}
 
void setup(void)
{
 Serial.begin(9600);
 tft.begin();
 if (!ts.begin()) { 
   Serial.println("Unable to start touchscreen.");
   } else { 
   Serial.println("Touchscreen started."); }
 tft.fillScreen(ILI9341_BLUE);
 // origin = left,top landscape (USB left upper)
 tft.setRotation(1); 
 redBtn();
 frame();
}

void loop()
{
  // See if there's any  touch data for us
  if (!ts.bufferEmpty())
  {   
  // Retrieve a point  
  TS_Point p = ts.getPoint(); 
  // Scale from ~0->4000 to tft.width using the calibration #'s
  p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
  p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
  // Compensate for rotation
  int x = tft.height() - p.x;
  int y = p.y;
  Serial.print("("); Serial.print(x);
  Serial.print(", "); Serial.print(y);
  Serial.println(")");
  if(x > 165 && x < 200) {
     if (y > 150 && y < 180) {
      Serial.println("Red btn hit"); redBtn(); frame();}
    }
  if(x > 165 && x < 200) {
     if (y > 180 && y < 215) {
      Serial.println("Green btn hit"); greenBtn(); frame();}
    }
  Serial.println(RecordOn);
  return;
 }  
}
This code will work fine for my project, but I have concerns about widespread applicability.

I'm not happy with the mapping coordinates; they appear to have little correlation with the actual display coordinates. e.g., sometimes the x and y coordinates appear to be reversed. In general, I am unable to pinpoint the problem. Furthermore, the rotation compensation that I had to apply is counter-intuitive; I would have expected to use
int x = p.x;
int y = tft.height() - p.y;
instead of
int x = tft.height() - p.x;
int y = p.y;
which I wound up using to obtain semi-believable numbers.

Note that in the posted changes:

if(x > 165 && x < 200) {
if (y > 150 && y < 180) {
Serial.println("Red btn hit"); redBtn(); frame();}
}
if(x > 165 && x < 200) {
if (y > 180 && y < 215) {
Serial.println("Green btn hit"); greenBtn(); frame();}
}

the x values are in the same range and the y values increase from one side of the button to the other. I would have expected the opposite, the y values should have been the same and the x values should have increased. I did what I had to do to make it work, but none of it makes sense to me.

> 2) I'm still seeing multiple detection events of single touch points...Weren't you trying to eliminate that?

I don't have a clue how to fix this. If we knew when the touch 'event' started and stopped, then perhaps we could save these values to an array and then average them to get a single value. The way it is now, there is some 'flash' due to multiple redrawings of the buttons. The STMPE610 manual has an interesting section which states:

"The STMPE610 touchscreen controller can be configured to oversample by 2/4/8 times and provide the averaged value as final output. This feature helps to reduce the effect of surrounding noise."

There are also registers to change the origin: 0x42-0x48, but I am uncertain if these would help.

I have tried to be constructively critical. Overall, I am thrilled with this lcd and touch screen and hope to use it extensively in upcoming projects. I greatly appreciate your time and efforts.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 2.8" TFT Touch Shield v2 with UNO

Post by adafruit_support_rick »

I fixed the multiple button hits, and changed all the drawing stuff to symbolic constants. See what you think:

Code: Select all

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

boolean RecordOn = false;

#define FRAME_X 210
#define FRAME_Y 180
#define FRAME_W 100
#define FRAME_H 50

//#define REDBUTTON_X (FRAME_X + 2)
//#define REDBUTTON_Y (FRAME_Y + 2)
//#define REDBUTTON_W ((FRAME_W/2) - 4)
//#define REDBUTTON_H (FRAME_H - 4)
//
//#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W + 4)
//#define GREENBUTTON_Y (FRAME_Y + 2)
//#define GREENBUTTON_W ((FRAME_W/2) - 4)
//#define GREENBUTTON_H (FRAME_H - 4)

#define REDBUTTON_X FRAME_X
#define REDBUTTON_Y FRAME_Y
#define REDBUTTON_W (FRAME_W/2)
#define REDBUTTON_H FRAME_H

#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
#define GREENBUTTON_Y FRAME_Y
#define GREENBUTTON_W (FRAME_W/2)
#define GREENBUTTON_H FRAME_H

void drawFrame()
{
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
}

void redBtn()
{ 
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_BLUE);
  drawFrame();
  tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("ON");
  RecordOn = false;
}

void greenBtn()
{
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_GREEN);
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
  drawFrame();
  tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("OFF");
  RecordOn = true;
}

void setup(void)
{
  Serial.begin(9600);
  tft.begin();
  if (!ts.begin()) { 
    Serial.println("Unable to start touchscreen.");
  } 
  else { 
    Serial.println("Touchscreen started."); 
  }

  tft.fillScreen(ILI9341_BLUE);
  // origin = left,top landscape (USB left upper)
  tft.setRotation(1); 
  redBtn();
}

void loop()
{
  // See if there's any  touch data for us
  if (!ts.bufferEmpty())
  {   
    // Retrieve a point  
    TS_Point p = ts.getPoint(); 
    // Scale using the calibration #'s
    // and rotate coordinate system
    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
    int y = tft.height() - p.x;
    int x = p.y;

    if (RecordOn)
    {
      if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
        if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
          Serial.println("Red btn hit"); 
          redBtn();
        }
      }
    }
    else //Record is off (RecordOn == false)
    {
      if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
        if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
          Serial.println("Green btn hit"); 
          greenBtn();
        }
      }
    }

    Serial.println(RecordOn);
  }  
}



User avatar
asteroid
 
Posts: 300
Joined: Tue Oct 22, 2013 9:10 pm

Re: 2.8" TFT Touch Shield v2 with UNO

Post by asteroid »

> See what you think:

I think you fixed it. No more flash from multiple button drawings. Thank you so much.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: 2.8" TFT Touch Shield v2 with UNO

Post by adafruit_support_rick »

I put it in the examples folder of the library.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”