MCUFRIEND_kbv 2.8inch touch TFT problem with buttons

hey gang!

got the display going but this time I am having a hard time with buttons...

display is MCUFRIEND_kbv 2.8inch tft touch screen

got my calibration data correct... (unless affected by orientation?)

inserted my calibration in the code

got a demo button code going.

modified it for my application works GREAT... until... I changed the orientation to Landscape from Portrait???

I dont get it looks like the buttons staid almost (not quite!) where they were in Portrait... even thow the drawings moved? Help!

Richard VE2DX

here is my code

/* an alternative approach.   swap the #if 1 / 0 values to try it
* 
*/
#if 1

#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <TouchScreen.h>
#define MINPRESSURE 200
#define MAXPRESSURE 1000

// ALL Touch panels and wiring is DIFFERENT
// copy-paste results from TouchScreen_Calibr_native.ino
const int XP=8,XM=A2,YP=A3,YM=9 ; //240x320 ID=0x4535
const int TS_LEFT=843,TS_RT=171,TS_TOP=888,TS_BOT=117;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

Adafruit_GFX_Button stop_btn, tune_btn, up_btn, down_btn;

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
  TSPoint p = ts.getPoint();
  pinMode(YP, OUTPUT);      //restore shared pins
  pinMode(XM, OUTPUT);
  digitalWrite(YP, HIGH);   //because TFT control pins
  digitalWrite(XM, HIGH);
  bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
  if (pressed) {
      pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
      pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
  }
  return pressed;
}

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

void setup(void)
{
  Serial.begin(9600);
  uint16_t ID = tft.readID();
  Serial.print("TFT ID = 0x");
  Serial.println(ID, HEX);
  Serial.println("Calibrate for your Touch Panel");
  if (ID == 0xD3D3) ID = 0x9486; // write-only shield
  tft.begin(ID);
  tft.setRotation(0);            //PORTRAIT   [b]This is where I change to a 1 for Landscape try it![/b]
  tft.fillScreen(BLACK);
  stop_btn.initButton(&tft,  30, 200, 50, 40, BLUE, RED, BLACK, "STOP", 2);
  tune_btn.initButton(&tft, 90, 200, 50, 40, BLUE, BLUE, BLACK, "TUNE", 2);
  stop_btn.drawButton(false);
  tune_btn.drawButton(false);
  up_btn.initButton(&tft,  150, 200, 50, 40, BLUE, GREEN, BLACK, "UP", 2);
  down_btn.initButton(&tft, 210, 200, 50, 40, BLUE, GREEN, BLACK, "DOWN", 2);
  up_btn.drawButton(false);
  down_btn.drawButton(false);
  tft.fillRect(40, 80, 160, 80, RED);
}

/*  
* updating multiple buttons from a list
* 
* anything more than two buttons gets repetitive
* 
* you can place button addresses in separate lists
* e.g. for separate menu screens
*/

// Array of button addresses to behave like a list
Adafruit_GFX_Button *buttons[] = {&stop_btn, &tune_btn,&up_btn, &down_btn, NULL};

/* update the state of a button and redraw as reqd
*
* main program can use isPressed(), justPressed() etc
*/
bool update_button(Adafruit_GFX_Button *b, bool down)
{
  b->press(down && b->contains(pixel_x, pixel_y));
  if (b->justReleased())
      b->drawButton(false);
  if (b->justPressed())
      b->drawButton(true);
  return down;
}

/* most screens have different sets of buttons
* life is easier if you process whole list in one go
*/
bool update_button_list(Adafruit_GFX_Button **pb)
{
  bool down = Touch_getXY();
  for (int i = 0 ; pb[i] != NULL; i++) {
      update_button(pb[i], down);
  }
  return down;
}

/* compare the simplicity of update_button_list()
*/
void loop(void)
{
  update_button_list(buttons);  //use helper function
  if (stop_btn.justPressed()) {
      tft.fillRect(40, 80, 160, 80, GREEN);
      stop_btn.drawButton(true);
      }
  if (tune_btn.justPressed()) {
      tft.fillRect(40, 80, 160, 80, RED);
      tune_btn.drawButton(true);
      tft.fillRect(40, 80, 160, 80, YELLOW);
      delay (1000);
      tft.fillRect(40, 80, 160, 80, RED);
      }
  //update_button_list(buttons);  //use helper function
  if (up_btn.justPressed()) {
      tft.fillRect(40, 80, 160, 80, BLUE);
      up_btn.drawButton(true);
  }
  if (down_btn.justPressed()) {
      tft.fillRect(40, 80, 160, 80, YELLOW);
      down_btn.drawButton(true);
  }
}
#endif

dont think I am using calibration data correctly?

here it is

11:10:01.929 -> TouchScreen.h GFX Calibration
11:10:01.964 -> Making all control and bus pins INPUT_PULLUP
11:10:01.998 -> Typical 30k Analog pullup with corresponding pin
11:10:02.032 -> would read low when digital is written LOW
11:10:02.101 -> e.g. reads ~25 for 300R X direction
11:10:02.135 -> e.g. reads ~30 for 500R Y direction
11:10:02.169 -> 
11:10:02.169 -> Testing : (A2, D8) = 26
11:10:02.204 -> Testing : (A3, D9) = 29
11:10:02.238 -> Diagnosing as:-
11:10:02.238 -> XM,XP:  (A2, D8) = 26
11:10:02.273 -> YP,YM:  (A3, D9) = 29
11:10:02.480 -> ID = 0x4535
11:10:11.739 -> 
11:10:11.739 -> cx=539 cy=639 cz=101 LEFT, TOP, Pressure
11:10:13.042 -> cx=594 cy=592 cz=100 LEFT, MIDH, Pressure
11:10:14.658 -> cx=573 cy=540 cz=101 LEFT, BOT, Pressure
11:10:16.035 -> cx=523 cy=699 cz=99 MIDW, TOP, Pressure
11:10:17.826 -> cx=514 cy=619 cz=100 MIDW, BOT, Pressure
11:10:19.336 -> cx=436 cy=690 cz=97 RT, TOP, Pressure
11:10:20.741 -> cx=409 cy=579 cz=102 RT, MIDH, Pressure
11:10:22.289 -> cx=434 cy=503 cz=101 RT, BOT, Pressure
11:10:23.840 -> MCUFRIEND_kbv ID=0x4535  240 x 320
11:10:23.874 -> 
11:10:23.874 -> const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x4535
11:10:23.943 -> const int TS_LEFT=574,TS_RT=419,TS_TOP=680,TS_BOT=549;
11:10:24.045 -> PORTRAIT CALIBRATION     240 x 320
11:10:24.216 -> x = map(p.x, LEFT=574, RT=419, 0, 240)
11:10:24.361 -> y = map(p.y, TOP=680, BOT=549, 0, 320)
11:10:24.526 -> Touch Pin Wiring XP=8 XM=A2 YP=A3 YM=9
11:10:24.665 -> LANDSCAPE CALIBRATION    320 x 240
11:10:24.834 -> x = map(p.y, LEFT=680, RT=549, 0, 320)
11:10:24.969 -> y = map(p.x, TOP=419, BOT=574, 0, 240)

First off. Please read Forum Instructions. Edit you existing post to put code into a "window" with </> icon.

Please run the Touch_Shield_new sketch from the examples.

  1. Copy-paste your Calibration.

  2. Observe that the circle follows your stylus 100%

  3. Change the orientation to LANDSCAPE.

  4. Observe that the circle follows your stylus 100%

Rinse and repeat for PORTRAIT_REV and LANDSCAPE_REV

Now study the program statements that map the Touch "point" to "pixel values"

Ask if you don't understand something.

Your Calibration from #0 looks normal

const int XP=8,XM=A2,YP=A3,YM=9 ; //240x320 ID=0x4535
const int TS_LEFT=843,TS_RT=171,TS_TOP=888,TS_BOT=117;

Your results from #1 are garbage:

11:10:23.874 -> const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x4535
11:10:23.943 -> const int TS_LEFT=574,TS_RT=419,TS_TOP=680,TS_BOT=549;

I suggest that you run the Calibration program again. Turn off the timestamps. They make the Serial useless.

David.

for some reason I can not get Touch_shield_new.ino to work, it loads but never reacts to the stylus?

that is why I was using the TouchScreen_Calibr_native.ino

Please run the Calibration sketch again.

#0 and #1 seem to agree for the Touch "pins"

But I would expect a normal result to be ~800 difference between TS_LEFT and TS_RT.
Your #1 shows 155 difference which is not normal

Are you sure that your libraries are up to date? i.e. run Library Manager
MCUFRIEND_kbv should be v2.9.8
Adafruit_GFX should be v1.7.2
Adafruit_Touchscreen should be v1.0.4

David.

all were up to date except adafruit_GFX was down to v1.7.1

here is the calibration results from TouchScreen_Calibr_native.ino

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A2, D8) = 25
Testing : (A3, D9) = 29
Diagnosing as:-
XM,XP:  (A2, D8) = 25
YP,YM:  (A3, D9) = 29
ID = 0x4535

cx=679 cy=741 cz=104 LEFT, TOP, Pressure
cx=664 cy=572 cz=103 LEFT, MIDH, Pressure
cx=608 cy=494 cz=103 LEFT, BOT, Pressure
cx=518 cy=682 cz=103 MIDW, TOP, Pressure
cx=521 cy=481 cz=102 MIDW, BOT, Pressure
cx=476 cy=653 cz=103 RT, TOP, Pressure
cx=478 cy=607 cz=102 RT, MIDH, Pressure
cx=399 cy=457 cz=101 RT, BOT, Pressure
MCUFRIEND_kbv ID=0x4535  240 x 320

const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x4535
const int TS_LEFT=659,TS_RT=441,TS_TOP=699,TS_BOT=469;
PORTRAIT CALIBRATION     240 x 320
x = map(p.x, LEFT=659, RT=441, 0, 240)
y = map(p.y, TOP=699, BOT=469, 0, 320)
Touch Pin Wiring XP=8 XM=A2 YP=A3 YM=9
LANDSCAPE CALIBRATION    320 x 240
x = map(p.y, LEFT=699, RT=469, 0, 320)
y = map(p.x, TOP=441, BOT=659, 0, 240)

Here is a typical output:

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A1, D7) = 29
Testing : (A2, D6) = 24
Diagnosing as:-
YP,YM:  (A1, D7) = 29
XM,XP:  (A2, D6) = 24
ID = 0x1520

cx=870 cy=126 cz=621 LEFT, TOP, Pressure
cx=860 cy=501 cz=554 LEFT, MIDH, Pressure
cx=865 cy=868 cz=443 LEFT, BOT, Pressure
cx=501 cy=129 cz=557 MIDW, TOP, Pressure
cx=498 cy=862 cz=346 MIDW, BOT, Pressure
cx=146 cy=127 cz=524 RT, TOP, Pressure
cx=144 cy=499 cz=404 RT, MIDH, Pressure
cx=135 cy=872 cz=222 RT, BOT, Pressure
MCUFRIEND_kbv ID=0x1520  240 x 320

const int XP=6,XM=A2,YP=A1,YM=7; //240x320 ID=0x1520
const int TS_LEFT=897,TS_RT=108,TS_TOP=102,TS_BOT=891;
PORTRAIT CALIBRATION     240 x 320
x = map(p.x, LEFT=897, RT=108, 0, 240)
y = map(p.y, TOP=102, BOT=891, 0, 320)
Touch Pin Wiring XP=6 XM=A2 YP=A1 YM=7
LANDSCAPE CALIBRATION    320 x 240
x = map(p.y, LEFT=102, RT=891, 0, 320)
y = map(p.x, TOP=108, BOT=897, 0, 240)

Note that my LEFTs are 870,860,865 and RTs are 146,144,133 i.e. consistent values and significant difference between LEFT, RT

Ok, your Touch pins are different. I only possess one Shield with your Touch wiring. But that shield calibrates normally.

I have no explanation for your unusual values. I presume your shield is plugged into the Uno. And you are not pressing an external case on the Touch Panel.

David.

ok have you got a simple landscape set of code with a working button or 2 that I could use to test?

ty

I built your sketch from #0. Added my Calibration. It works 100% in PORTRAIT.

I then edited setup()

  tft.begin(ID);
  tft.setRotation(1);            //LANDSCAPE

and edited Touch_getXY() function:

bool Touch_getXY(void)
{
  TSPoint p = ts.getPoint();
  pinMode(YP, OUTPUT);      //restore shared pins
  pinMode(XM, OUTPUT);
  digitalWrite(YP, HIGH);   //because TFT control pins
  digitalWrite(XM, HIGH);
  bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
  if (pressed) {
    switch(tft.getRotation()) {
    case 0:    //PORTRAIT
      pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width());
      pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
      break;
    case 1:   //LANDSCAPE
      pixel_x = map(p.y, TS_TOP, TS_BOT, 0, tft.width());
      pixel_y = map(p.x, TS_RT, TS_LEFT, 0, tft.height());
      break;
    }
  }
  return pressed;
}

Obviously your buttons appear is different places but they are recognised in the normal way.

David.

JACKPOT you did it...

works fine...

and I understand how now...

many thanks and mery xmas

Please can you explain what your problem was.

The Calibration results from #1 are rubbish.
But your Calibration in #0 looks fine.

You are not alone. Many people struggle with Touch.
But I assume that most succeed in the end.

Unfortunately they seldom explain how they won. It would help all the other users. And possibly help me to write "better" examples in the first place.

David.

ok, good ideal.

well my problem was not a calibration issue, at best that created confusion more then anything else, caused by the newby (ME! :P)

the solution was adressing how to switch the touch screen portion of the programing to landscape whish you did in your code example from above where you simply added the orientation portion of the code

    case 0:    //PORTRAIT
      pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width());
      pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
      break;
    case 1:   //LANDSCAPE
      pixel_x = map(p.y, TS_TOP, TS_BOT, 0, tft.width());
      pixel_y = map(p.x, TS_RT, TS_LEFT, 0, tft.height());
      break;

adding this to my code solved it!

Bravo monsieurs, simply Bravo...

and yes I agree the touchscreen can be a pain to learn for a newby, but when you get them going... WOW... Simply WOW!

thanks again for your help!

Richard VE2DX