MCUfriend TFT 3,5'' won't let me calibrate/work

Hello all, i bought a 3,5'' TFT screen a long, long time ago online, but i never got used it. I found a neat project where i need to use my screen however, when i tried to calibrate it, it fails saying that was "unable to read the position of the press...". I've searched through this forum and ran all the exemples getting the following results: `e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A1, D7) = 24
ID = 0x0099
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

MISSING TOUCHSCREEN
ID = 0x0099

Read Special Registers on MCUFRIEND UNO shield
controllers either read as single 16-bit
e.g. the ID is at readReg(0)
or as a sequence of 8-bit values
in special locations (first is dummy)

T

diagnose any controller
reg(0x0000) 80 80 ID: ILI9320, ILI9325, ILI9335, ...
reg(0x0004) 00 00 80 00 Manufacturer ID
reg(0x0009) 00 00 61 00 00 Status Register
reg(0x000A) 00 08 Get Power Mode
reg(0x000C) 00 06 Get Pixel Format
reg(0x0030) B0 B0 B0 B0 B0 PTLAR
reg(0x0033) B3 B3 B3 B3 B3 B3 B3 VSCRLDEF
reg(0x0061) E1 E1 RDID1 HX8347-G
reg(0x0062) E2 E2 RDID2 HX8347-G
reg(0x0063) E3 E3 RDID3 HX8347-G
reg(0x0064) E4 E4 RDID1 HX8347-A
reg(0x0065) E5 E5 RDID2 HX8347-A
reg(0x0066) E6 E6 RDID3 HX8347-A
reg(0x0067) E7 E7 RDID Himax HX8347-A
reg(0x0070) 00 B6 Panel Himax HX8347-A
reg(0x00A1) 00 00 00 00 00 RD_DDB SSD1963
reg(0x00B0) B0 B0 RGB Interface Signal Control
reg(0x00B3) B3 B3 B3 B3 B3 Frame Memory
reg(0x00B4) B4 B4 Frame Mode
reg(0x00B6) B6 B6 B6 B6 B6 Display Control
reg(0x00B7) B7 B7 Entry Mode Set
reg(0x00BF) BF BF BF BF BF BF ILI9481, HX8357-B
reg(0x00C0) C0 C0 C0 C0 C0 C0 C0 C0 C0 Panel Control
reg(0x00C1) C1 C1 C1 C1 Display Timing
reg(0x00C5) C5 C5 Frame Rate
reg(0x00C8) C8 C8 C8 C8 C8 C8 C8 C8 C8 C8 C8 C8 C8 GAMMA
reg(0x00CC) CC CC Panel Control
reg(0x00D0) D0 D0 D0 D0 Power Control
reg(0x00D1) D1 D1 D1 D1 VCOM Control
reg(0x00D2) D2 D2 D2 Power Normal
reg(0x00D3) D3 D3 D3 D3 ILI9341, ILI9488
reg(0x00D4) D4 D4 D4 D4 Novatek
reg(0x00DA) 00 00 RDID1
reg(0x00DB) 00 80 RDID2
reg(0x00DC) 00 00 RDID3
reg(0x00E0) E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 GAMMA-P
reg(0x00E1) E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 E1 GAMMA-N
reg(0x00EF) EF EF EF EF EF EF ILI9327
reg(0x00F2) F2 F2 F2 F2 F2 F2 F2 F2 F2 F2 F2 F2 Adjust Control 2
reg(0x00F6) F6 F6 F6 F6 Interface Control

graphic test:
Serial took 0ms to start
ID = 0x99
`
This is my first true project and thus im very new at this so please don't get too technical (although i know that sometimes it's necessary) but from what i could understand, my screen has the ILI9488 controller however. Im also able to run all codes from the examples except the SD card ones and when i upload the buttons exemple, i can use the button however, far down from the button rectangle. Any idea how can i fix this?

PS: i forgot to mention, but im using and Arduino MEGA
Thank you all!

what sketch are you using to do this ?

That makes sense, on a Mega the SPI pins are different than on an UNO and the SD card uses them
UNO | MEGA
MISO 12 | 50
MOSI 11 | 51
SCK 13 | 52
SS 10 | 53

you will need to disconnect those pins on the shield from pins 10 - 13 and connect them to pins 50 - 53

here is a link to someone who had calibration issues before and the calibration program i use.

Hello @Deva_Rishi, thanks for dedicate some of your time to my problem. I get that error when i run the "TouchScreen_Calibr_native under the MCUFRIEND_kbv library. Regarding the SD card exemple, i though it didn't run since i had no SDcard inserted to begin with (and my project doesn't need one).

So in the comments it says

// It is assumed that the display module is connected to an
// appropriate shield or that you know how to change the pin
// numbers in the setup.

and

#define YP A1   //[A1], A3 for ILI9320, A2 for ST7789V 
#define YM 7    //[ 7], 9             , 7
#define XM A2   //[A2], A2 for ILI9320, A1 for ST7789V
#define XP 6    //[ 6], 8             , 6

what are your settings ?
oh yes and

#include <UTFTGLUE.h>            //we are using UTFT display methods
UTFTGLUE myGLCD(0x9341, A2, A1, A3, A4, A0);

I never use that, what was the result when you run my sketch ?

Hello Deva, running the GLUE code (480x320), i use the following configuration

UTFTGLUE myGLCD(0,A2,A1,A3,A4,A0);

I also tried

`UTFTGLUE myGLCD(0x99,A2,A1,A3,A4,A0);`

which seems to work aswell

Regarding the plus and minus points, i don't know which i should use since i cannot run the calibration and i think that's one of the main reasons that sketch exists, to get those points. Finally, i can't find that commentary you've repplied, i thought it was under the calibration sketch, but i couldn't find it. Could the failed calibration be caused by my controller?

Thanks!

i found only the 'TouchScreen_Calibr_kbv' in my examples, but i am probably running an outdated version of the library.

Those shields are made of leftover old TFT screens usually (unless you get adafruit originals) and the orientation may differ per batch, and also the touchscreen orientation may differ (and differ from the tft screen) and mainly the edges of the TS screen are different per particular screen (not just per batch) that is what the calibration sketch is for, so the TFT screen and the TS screen are matched and pressing the TS on the spot where you do relates to what is printed on the TFT.

what controller ?

Hello again, thanks for the explanation about how those TFT's came to be, so, ignoring the fact that the calibration sketch doesn't work, is it possible to, by trial and error, get calibration's info? IF not, what may be wrong with my calibration? ILI9488 controller, could it be corrupted or something?
I forgot to mention, but looking at the TFT screen and where each pin connect into the arduino, i got this: LCD_RD = A0 LCD_WR = A1 LCD_RS = A2 LCD_CS = A3 LCD_RST = A4
And also, there was one time when i left him alone and he got into the calibration points, but that never happened again.

I noticed, right now that, when i press that ribbon cable, the code works. I cannot see any damage whatsoever, what could it be?


Thanks.

It is possible, basically you will be looking for the edge of the TS and match that to the TFT. This will provide you with the TS orientation in relation to the TFT. As stated before i use a sketch that let's you swipe to the edges and then store these values in EEPROM so you can read them later when you upload a different sketch.

Most important is that you get these pins correctly

const uint8_t YP = A1;  // must be an analog pin, use "An" notation!
const uint8_t XM = A2;  // must be an analog pin, use "An" notation!
const uint8_t YM = 7;   // can be a digital pin
const uint8_t XP = 6;   // can be a digital pin

since these pins need to be switched back to OUTPUT after a TS.getPoint() or the TFT screen will crash.

poor quality.

also in the ts constructor there is a 5th value which is actually a resistance you should measure between (pff i hardly remember it says somewhere in one of the examples) 2 points and is screen specific, and usually somewhere between 300 & 500 Ohms. you measure this when the shield not connected to the Arduino.

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

It's not all the important, but it does make the TS work better.

Hello Deva, Do you think the screen will work just fine or should i try to put a small piece of cotton to help with the ribbon contact?

Also, i know that the nature of this topic is solely related to a error/"malfunction", but i have a code in which i have to adapt a code to be used with an TFT, maybe you could give me some hints on what should i look/learn in order to get the code working. The code i have is to be ran with an ESP8266 and a XPT2046 screen and i plan to use a MEGA and the screen we've been talking about. Were's the sketch i want to adapt

#include <Arduino.h>
#include <EEPROM.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include "Adafruit_ILI9341.h"
#include <XPT2046_Touchscreen.h>
#define CS_PIN D2
XPT2046_Touchscreen ts(CS_PIN);

#define TS_MINX 250
#define TS_MINY 200 // calibration points for touchscreen
#define TS_MAXX 3800
#define TS_MAXY 3750

#define TFT_DC D4
#define TFT_CS D8

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

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Since i don't know much about coding, i've been looking around and trying different things and i came to this:

#include <TouchScreen.h>

MCUFRIEND_kbv tft(ILI9488, A3, A2, A1, A0, A4);

#define CS=A3
#define RS=A2
#define WR=A1
#define RD=A0
#define RST=A4

const uint8_t YP = A1;  // must be an analog pin, use "An" notation!
const uint8_t XM = A2;  // must be an analog pin, use "An" notation!
const uint8_t YM = 7;   // can be a digital pin
const uint8_t XP = 6;  

TouchScreen ts = ts(pinXP, pinYP, pinXM, pinYM, 300) // still have to measure the resistance and i still need to add the limit (x,y) points

But i still don't know what does the following line does nor how to adapt it:

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Finally, i would like to ask if you could explain what the line you mentioned does or, if possible, give me some bibliography, the line:

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

This is my final iteration:

#include <Arduino.h>
#include <EEPROM.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include "Adafruit_ILI9341.h"
#include <XPT2046_Touchscreen.h>
#include <TouchScreen.h>  
#include <MCUFRIEND_kbv.h>
// Map ESP8266 pin names to rduino pins

const byte D0 = 2;
const byte D1 = 3;
const byte D2 = 4;
const byte D3 = 5;
const byte D4 = 6;
const byte D5 = 7;
const byte D6 = 8;
const byte D7 = 9;
const byte D8 = 10;


#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
//const uint8_t YP = A1;  // must be an analog pin, use "An" notation!
//const uint8_t XM = A2;  // must be an analog pin, use "An" notation!
//const uint8_t YM = 6;   // can be a digital pin
//const uint8_t XP = 7;

#define XP 250
#define YP 200 // calibration points for touchscreen
#define XM 3800
#define YM 3750


MCUFRIEND_kbv tft( A3, A2, A1, A0, A4);
TouchScreen ts = ts(XP, YP, XM, YM, 300) //have to change each point


#define TFT_DC A4
#define TFT_CS A3

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

//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

Thanks!

That line declares the object 'tft' of the screen type you have, including some of the pins that have been defined.

That declares the Touchscreen. You must understand that the screen you have actually consists of 2 parts, the TFT to which you write date to make it visible, and the Touchscreen that reads where and how much pressure is applied to a point. Again the first 4 parameters are pin numbers, and the fifth is the amount of resistance between XM & XP that you need to measure with a multimeter. Most of the screens will work with inaccurate values already, it is the least important of the parameters.

That makes no sense at all.

const byte D0 = 2;
const byte D1 = 3;
const byte D2 = 4;
const byte D3 = 5;
const byte D4 = 6;
const byte D5 = 7;
const byte D6 = 8;
const byte D7 = 9;
const byte D8 = 10;

you can't just do some mapping !

No they are not, they are pin numbers.

Just a simple question before we continue,
can you upload my calibration sketch ?
i will post it here again.

/*  TFT Touchscreen Calibrateter

 */
#include <EEPROM.h>        // for storage of the settings
#include <Adafruit_GFX.h>    // Core graphics library

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;       // hard-wired for UNO shields anyway.
#include <TouchScreen.h>

#if defined(__SAM3X8E__)
#undef __FlashStringHelper::F(string_literal)
#define F(string_literal) string_literal
#endif


// most mcufriend shields use these pins and Portrait mode:
const uint8_t YP = A1;  // must be an analog pin, use "An" notation!
const uint8_t XM = A2;  // must be an analog pin, use "An" notation!
const uint8_t YM = 7;   // can be a digital pin
const uint8_t XP = 6;   // can be a digital pin


uint8_t SwapXY = 1; // depends on the TFT shield

uint16_t TS_LEFT = 930;
uint16_t TS_RT = 175;
uint16_t TS_TOP = 175;  // this is actually the usb end at the start of the program
uint16_t TS_BOT = 920;

volatile uint16_t TFT_X_RANGE = 240;  // making these variables volatile solves the issue that when changing
volatile uint16_t TFT_Y_RANGE = 320;  // their value (or even keeping it the same but writing to them)
                                      // caused an incorrect memory write with black area's on screen.


// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 455);
TSPoint tp;

#define MINPRESSURE 5
#define MAXPRESSURE 1000
#define RELEASECYCLES 200

#define EEPROM_OFFSET 448  // set this to a matching value in the program 
                          // depending on the calibrated values, do not use 
                          // the low Eeprom adddresses since the graphics library
                          // appears to be using them.

#define SWAP(a, b) {uint16_t tmp = a; a = b; b = tmp;}

uint16_t identifier;
uint8_t orientation = 0;    //Portrait



// Assign human-readable names to some common 16-bit color values:
#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() {
  tft.begin(9600);
  tft.reset();
  identifier = tft.readID();
  tft.begin(identifier);
  tft.setRotation(orientation);  // we use orientation here to set the TFT rotation

//  TS_Rotation(orientation);  
  ts = TouchScreen(XP, YP, XM, YM, 455);     //  call the constructor 
  while (!TitleScreen()) Change_TFTXY_Settings(); 
  CalibrationScreen();
}

void loop() {
}

void CalibrationScreen() {
  tft.fillScreen(BLUE);
  tft.setTextSize(2);
  tft.setTextColor(BLACK);
  const char * title = "TFT Calibrater";            // header text
  tft.setCursor((TFT_X_RANGE/2) - strlen(title)*6,20);
  tft.print(title);

  tft.setCursor((TFT_X_RANGE/2) - 54,40);
  tft.print(String(TFT_X_RANGE)+" X "+String(TFT_Y_RANGE));
  tft.fillRect(TFT_X_RANGE/4,TFT_Y_RANGE/4,TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);
  tft.setTextSize(1);
  const char * order = "Press the red rectangle";
  tft.setCursor((TFT_X_RANGE/2) - strlen(order)*3,TFT_Y_RANGE-50);
  tft.print(order);
  tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,RED);
  WaitReleaseReadPress(true);
  tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,YELLOW);
  while (!ConfirmRelease());
  tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,RED);
  
  uint16_t minx=500,miny=500,maxx=500,maxy=500;
  uint8_t minxq=4,minyq=4,maxxq=4,maxyq=4,i=0;
  tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,BLUE);
  tft.fillRect(0,  0,  TFT_X_RANGE,  TFT_Y_RANGE/4,  BLUE);
  tft.fillRect(0,  (TFT_Y_RANGE/4)*3  ,TFT_X_RANGE,  TFT_Y_RANGE/4,  BLUE);
  tft.fillRect((TFT_X_RANGE/8),(TFT_Y_RANGE/8),(TFT_X_RANGE/4)*3,(TFT_Y_RANGE/4)*3,RED);
  EdgeLookText();
  WaitReleaseReadPress(true);
  tft.fillScreen(BLUE);
  tft.fillRect(TFT_X_RANGE/4,TFT_Y_RANGE/4,TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);  
  
  DrawArrow(0);
  FillQuad(i,CYAN);

  while (i<4) {
    tp = ts.getPoint();
    ResetPins();
    if (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) continue;

    tft.setTextColor(YELLOW,BLUE);
    tft.setTextSize(2);
    tft.setCursor((TFT_X_RANGE/4)+20,(TFT_Y_RANGE/4)*(3-(i/2)*3)+20);
    tft.print("tp.x=" + String(tp.x));
    tft.setCursor((TFT_X_RANGE/4)+20,(TFT_Y_RANGE/4)*(3-(i/2)*3)+50);
    tft.print("tp.y=" + String(tp.y));
    tft.setTextSize(1);
    
    if (tp.x>maxx) {
      maxx=tp.x;
      maxxq=i;
      tft.setCursor((TFT_X_RANGE/4)*3+10,40);
      tft.print("MaxX="+String(maxx));
    }
    if (tp.x<minx) {
      minx=tp.x;
      minxq=i;
      tft.setCursor(10,40);
      tft.print("MinX="+String(minx));
    }
    if (tp.y>maxy) {
      maxy=tp.y;
      maxyq=i;
      tft.setCursor((TFT_X_RANGE/4)*3+10,(TFT_Y_RANGE/4)*3+40);
      tft.print("MaxY="+String(maxy));
    }
    if (tp.y<miny) {
      miny=tp.y;
      minyq=i;
      tft.setCursor(10,(TFT_Y_RANGE/4)*3+40);
      tft.print("MinY="+String(miny));
    }
    if (tp.x > 450 && tp.x < 570  && tp.y > 450 && tp.y < 570) { // exit
      FillQuad(i,BLUE);
      i++;
      tft.fillRect((TFT_X_RANGE/8)*3,(TFT_Y_RANGE/8)*3,TFT_X_RANGE/4,TFT_Y_RANGE/4,YELLOW);
      while (!ConfirmRelease());
      tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,RED);
      DrawArrow(i);
      FillQuad(i,CYAN);
    }
  }
  tft.fillScreen(YELLOW);
  tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,BLUE);
  tft.setTextColor(BLACK,YELLOW);
  tft.setTextSize(2);
  SetCursorInQuad(minxq,0); 
  tft.print("MinX");
  SetCursorInQuad(minxq,2);
  tft.print(String(minx));
  SetCursorInQuad(maxxq,0); 
  tft.print("MaxX");
  SetCursorInQuad(maxxq,2);
  tft.print(String(maxx));
  SetCursorInQuad(minyq,0); 
  tft.print("MinY");
  SetCursorInQuad(minyq,2);
  tft.print(String(miny));
  SetCursorInQuad(maxyq,0); 
  tft.print("MaxY");
  SetCursorInQuad(maxyq,2);
  tft.print(String(maxy));

  EepromSaveScreen();
  WaitReleaseReadPress(true);
  StoreInVar(minxq,minx-3);
  StoreInVar(maxxq,maxx+3);
  StoreInVar(minyq,miny-3);
  StoreInVar(maxyq,maxy+3);
  StoreValues();
  ReadValues();
  PrintValues();
}

void StoreInVar(uint8_t side,uint16_t value) {
  switch(side) {
    case 0: 
      TS_TOP=value;
      break;
    case 1:
      TS_RT=value;
      break;
    case 2:
      TS_BOT=value;
      break;
    case 3:
      TS_LEFT=value;
      break;
  }
}

void EepromSaveScreen() {
  tft.setTextColor(YELLOW,BLUE);
  tft.setTextSize(1);
  const char * line1 = "The Values found";
  const char * line2 = "Will be stored in";
  const char * line3 = "The Eeprom as 16";
  const char * line4 = "bit U-integers";
  const char * line5 = "Press to continue";
  tft.setCursor((TFT_X_RANGE/2) - strlen(line1)*3,((TFT_Y_RANGE/2)-24));
  tft.print(line1);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line2)*3,((TFT_Y_RANGE/2)-12));
  tft.print(line2);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line3)*3,((TFT_Y_RANGE/2)));
  tft.print(line3);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line4)*3,((TFT_Y_RANGE/2)+12));
  tft.print(line4);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line5)*3,((TFT_Y_RANGE/2)+30));
  tft.print(line5); 
}

void StoreValues() {
  Write16bitEeprom(EEPROM_OFFSET,TFT_X_RANGE);
  Write16bitEeprom(EEPROM_OFFSET+2,TFT_Y_RANGE);
  Write16bitEeprom(EEPROM_OFFSET+4,TS_TOP);
  Write16bitEeprom(EEPROM_OFFSET+6,TS_RT);
  Write16bitEeprom(EEPROM_OFFSET+8,TS_BOT);
  Write16bitEeprom(EEPROM_OFFSET+10,TS_LEFT);
}

void Write16bitEeprom(uint16_t location, uint16_t uinteg) {
  EEPROM.write(location,lowByte(uinteg));
  EEPROM.write(location+1,highByte(uinteg));
}

void ReadValues() {     //copy the following 2 functions into your program
  TFT_X_RANGE=Read16bitEeprom(EEPROM_OFFSET);
  TFT_Y_RANGE=Read16bitEeprom(EEPROM_OFFSET+2);
  TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
  TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
  TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
  TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}

uint16_t Read16bitEeprom(uint16_t location) {
  return( ((uint16_t) EEPROM.read(location+1)<<8) | (uint16_t) EEPROM.read(location));
}

void PrintValues() {
  tft.fillScreen(GREEN);
  tft.fillRect((TFT_X_RANGE/4),(TFT_Y_RANGE/4),TFT_X_RANGE/2,TFT_Y_RANGE/2,WHITE);
  tft.setTextColor(BLACK);
  tft.setTextSize(2);
  SetCursorInQuad(0,1); 
  tft.print(String(TS_TOP));
  SetCursorInQuad(1,1); 
  tft.print(String(TS_RT));
  SetCursorInQuad(2,1); 
  tft.print(String(TS_BOT));
  SetCursorInQuad(3,1); 
  tft.print(String(TS_LEFT));
  tft.setCursor(TFT_X_RANGE/2-15,TFT_Y_RANGE/2-24);
  tft.print(String(TFT_X_RANGE));
  tft.setCursor(TFT_X_RANGE/2-3,TFT_Y_RANGE/2-6);
  tft.print("X");
  tft.setCursor(TFT_X_RANGE/2-15,TFT_Y_RANGE/2+12);
  tft.print(String(TFT_Y_RANGE));
}


void SetCursorInQuad(uint8_t quad, uint8_t line) {
  switch(quad) {
    case 0:
      tft.setCursor((TFT_X_RANGE/8)*3+line*7,20+line*15);
      break;
    case 1:
      tft.setCursor((TFT_X_RANGE/4)*3+5+line*7,(TFT_Y_RANGE/8)*3+20+line*15);
      break;
    case 2:
      tft.setCursor((TFT_X_RANGE/8)*3+line*7,(TFT_Y_RANGE/4)*3+20+line*15);
      break;
    case 3:
      tft.setCursor(5+line*7,(TFT_Y_RANGE/8)*3+20+line*15);
      break;
  }
  return;
}


void FillQuad(uint8_t quad,uint16_t color) {
  switch (quad) {
    case 0:
      tft.fillRect(TFT_X_RANGE/4,0,TFT_X_RANGE/2,TFT_Y_RANGE/4,color);
      break;
    case 1:
      tft.fillRect((TFT_X_RANGE/4)*3,TFT_Y_RANGE/4,TFT_X_RANGE/4,TFT_Y_RANGE/2,color);
      break;
    case 2:
      tft.fillRect(TFT_X_RANGE/4,(TFT_Y_RANGE/4)*3,TFT_X_RANGE/2,TFT_Y_RANGE/4,color);
      break;
    case 3:
      tft.fillRect(0,TFT_Y_RANGE/4,TFT_X_RANGE/4,TFT_Y_RANGE/2,color);
  }
}


void DrawArrow(uint8_t direct) {
  if (direct>3) return;
  if (direct%2) {  // horizontal
    for (uint8_t i=0; i<10; i++) {
      if ((i) && (i<9))  tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i, 
                          TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i, BLACK);
      if (direct/2) { // to left
        tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
                    TFT_X_RANGE/2,    TFT_Y_RANGE/2-5+i-(TFT_Y_RANGE/16)*2,BLACK);
        tft.drawLine(TFT_X_RANGE/2-(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
                    TFT_X_RANGE/2,    TFT_Y_RANGE/2-5+i+(TFT_Y_RANGE/16)*2,BLACK);                    
      }
      else {  // to right
        tft.drawLine(TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
                    TFT_X_RANGE/2,    TFT_Y_RANGE/2-5+i-(TFT_Y_RANGE/16)*2,BLACK);
        tft.drawLine(TFT_X_RANGE/2+(TFT_X_RANGE/16)*3, TFT_Y_RANGE/2-5+i,
                    TFT_X_RANGE/2,    TFT_Y_RANGE/2-5+i+(TFT_Y_RANGE/16)*2,BLACK);        
      }
    }
  }
  else {  // vertical
  for (uint8_t i=0; i<10; i++) {
    if ((i) && (i<9))  tft.drawLine(TFT_X_RANGE/2-5+i,  TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3,  
                          TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3, BLACK);
      if (!(direct/2)) { // to Bottom
        tft.drawLine(TFT_X_RANGE/2-5+i, TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3, 
                    TFT_X_RANGE/2-5+i-(TFT_X_RANGE/16)*2,  TFT_Y_RANGE/2,    BLACK);
        tft.drawLine(TFT_X_RANGE/2-5+i,  TFT_Y_RANGE/2-(TFT_Y_RANGE/16)*3, 
                    TFT_X_RANGE/2-5+i+(TFT_X_RANGE/16)*2,  TFT_Y_RANGE/2,    BLACK);                    
      }
      else {  // to Top
        tft.drawLine(TFT_X_RANGE/2-5+i,  TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3, 
                    TFT_X_RANGE/2-5+i-(TFT_X_RANGE/16)*2,  TFT_Y_RANGE/2,    BLACK);
        tft.drawLine(TFT_X_RANGE/2-5+i,  TFT_Y_RANGE/2+(TFT_Y_RANGE/16)*3, 
                    TFT_X_RANGE/2-5+i+(TFT_X_RANGE/16)*2,  TFT_Y_RANGE/2,    BLACK);
      }        
    }
  }
}

void EdgeLookText() {
  tft.setTextColor(BLACK,RED);
  tft.setTextSize(1);
  const char * line1 = "Look for the edge's";
  const char * line2 = "extreme value in the";
  const char * line3 = "lightblue area, using";
  const char * line4 = "a toothpick, and when";
  const char * line5 = "done press the center";
  const char * line6 = "of this red square for";
  const char * line7 = "the next edge.";
  const char * line8 = "Press to continue";
  tft.setCursor((TFT_X_RANGE/2) - strlen(line1)*3,((TFT_Y_RANGE/2)-48));
  tft.print(line1);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line2)*3,((TFT_Y_RANGE/2)-36));
  tft.print(line2);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line3)*3,((TFT_Y_RANGE/2)-24));
  tft.print(line3);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line4)*3,((TFT_Y_RANGE/2)-12));
  tft.print(line4);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line5)*3,((TFT_Y_RANGE/2)));
  tft.print(line5); 
  tft.setCursor((TFT_X_RANGE/2) - strlen(line6)*3,((TFT_Y_RANGE/2)+12));
  tft.print(line6);  
  tft.setCursor((TFT_X_RANGE/2) - strlen(line7)*3,((TFT_Y_RANGE/2)+24));
  tft.print(line7);
  tft.setCursor((TFT_X_RANGE/2) - strlen(line8)*3,((TFT_Y_RANGE/2)+48));
  tft.print(line8);
}

bool TitleScreen() {
  tft.fillScreen(WHITE);
  tft.setTextSize(2);
  tft.setTextColor(BLACK);
  const char * title = "TFT Calibrater";
  tft.setCursor((TFT_X_RANGE/2) - strlen(title)*6,20);
  tft.print(title);
  delay(1000);
  tft.setTextSize(1);
  const char * story1 = "Your screen should be";
  const char * story2 = "in Portait mode, where";
  const char * story3 = "the USB-end is the top.";
  const char * story4 = "And this text should be";
  const char * story5 = "centered, left to right,";
  const char * story6 = "and top to bottom, with";
  const char * story7 = "a frame around it.";
  const char * story8 = "If so, press the screen,";
  const char * story9 = "if not, press and hold";
  const char * story10 = "for 3 seconds";
  tft.setCursor((TFT_X_RANGE/2) - strlen(story1)*3,((TFT_Y_RANGE/2)-54));
  tft.print(story1);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story2)*3,((TFT_Y_RANGE/2)-42));
  tft.print(story2);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story3)*3,((TFT_Y_RANGE/2)-30));
  tft.print(story3);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story4)*3,((TFT_Y_RANGE/2)-18));
  tft.print(story4);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story5)*3,((TFT_Y_RANGE/2)-6));
  tft.print(story5); 
  tft.setCursor((TFT_X_RANGE/2) - strlen(story6)*3,((TFT_Y_RANGE/2)+6));
  tft.print(story6);  
  tft.setCursor((TFT_X_RANGE/2) - strlen(story7)*3,((TFT_Y_RANGE/2)+18));
  tft.print(story7);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story8)*3,((TFT_Y_RANGE/2)+30));
  tft.print(story8);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story9)*3,((TFT_Y_RANGE/2)+42));
  tft.print(story9);
  tft.setCursor((TFT_X_RANGE/2) - strlen(story10)*3,((TFT_Y_RANGE/2)+54));
  tft.print(story10);
  tft.drawRect(2,2,TFT_X_RANGE-4,TFT_Y_RANGE-4,BLACK);
  WaitReleaseReadPress(true);
  uint32_t moment=millis();
  while (!ConfirmRelease()) if ((millis()-moment)>3000) return false;
  return true;
}

void Change_TFTXY_Settings() {
  tft.fillScreen(RED);
  delay(3000);
}

bool ConfirmRelease() {
  uint8_t prs=0;
  while (prs<RELEASECYCLES) {
    tp = ts.getPoint();
    ResetPins();
    if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) return false ;
    delay(1);
    prs++;
  }
  return true;
}

void WaitReleaseReadPress(bool waitrelease) {
  if (waitrelease) {
    while (!ConfirmRelease());
  }
  while (tp.z < MINPRESSURE || tp.z > MAXPRESSURE) {
    tp = ts.getPoint();
    ResetPins();
  }
  delay (100);
}

void ResetPins(){
  pinMode(XM, OUTPUT);  // reset the pins after use.
  pinMode(YP, OUTPUT);
  pinMode(XP, OUTPUT);
  pinMode(YM, OUTPUT);
}

Now could you also remove the shield from the MEGA, turn it over and take a picture of the bottom, where hopefully there will be some silk-print of the pinout for your particular shield ?

Hello Deva,

I ran your code and got the above results:

the silk print:

Regarding what you wrote about "my"code, i still need it to read carefully since i never programmed with an Arduino + C (i had python in my Bsc degree and im currently using learning how to model with it).

Thank you so much :slight_smile:

Well great, that means that the declarations for the TFT i used, match the ones for your screen, and that goes for the TS as well.
Now to get the correct 5th value for the TS declaration (455 in the calibration sketch) measure the resistance between the XM & XP pins of the TS, that is pin 7 & A2. I'll come back to this later, gotta go to work now.

Hello Deva, i got 644-643 Ohms, but i had to softly press the screen down in order to get the measurement.

that sounds like a lot, thoiugh on the 1 shield i still have unused in my box, it also had 614 Ohms (though i didn't have to press it all. Just to confirm the pins are marked LCD_RS & LCD_D7

anyway, that means that the declaration for the touchscreen would be

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

Now the we have the calibration values, and they are actually stored in EEPROM as well, and you can read them from it within the sketch that you want to create to use the TFT-TS.

Still it might be better to run the calibration sketch one more time with that resistance value.

Regardless, you now have the edges of the Touchscreen and you can relate these to the edges of the TFT , which are ranging from 0 - 240 & 0 - 320. You can now use the map() function to convert the readings from the ts point to what you have printed on screen, so you can display a button and see if it is being pressed.

a few notes on the code.
the ConfirmRelease() is a function that deals with the small dropouts of the TS results, basically it checks 200 times to make sure that there is no press. Some shields may work with a smaller amount of cycles. I use my shield to drag faders across the screen, so any incorrect release of the screen will cause issues, as it will regardless.

every time you call

tp = ts.getPoint();

you will need to switch the pins back to output mode, i do that using

void ResetPins(){
  pinMode(XM, OUTPUT);  // reset the pins after use.
  pinMode(YP, OUTPUT);
  pinMode(XP, OUTPUT);
  pinMode(YM, OUTPUT);
}

these 2 functions read the values back from the EEPROM, although you can also manually copy them to your own sketch

void ReadValues() {     //copy the following 2 functions into your program
  TFT_X_RANGE=Read16bitEeprom(EEPROM_OFFSET);
  TFT_Y_RANGE=Read16bitEeprom(EEPROM_OFFSET+2);
  TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
  TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
  TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
  TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}

uint16_t Read16bitEeprom(uint16_t location) {
  return( ((uint16_t) EEPROM.read(location+1)<<8) | (uint16_t) EEPROM.read(location));
}

Oh yeah is that the correct orientation for the screen you have in mind ? or do you want to change that ?

Any other questions ?

Hello Deva, thanks for taking some of your time for helping me. I have a lot to digest, thus give me some time to learn what those lines do so i can adapt them to "my" code.
Thanks!

Hello Deva,

2 things, do i need to define "TFT_RANGE" for x and y. And, what does this function do:

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

im trying to get rid of it but im finding hard to understand it thus, i cannot replace it.

Thanks!

right now, the screen part looks like this (i have everything disorganized because im trying to understand how everything works):


#include <Arduino.h>
#include <MCUFRIEND_kbv.h>
#include <EEPROM.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include "Adafruit_ILI9341.h"
#include <TouchScreen.h>

const uint8_t YP = A1;  // must be an analog pin, use "An" notation!
const uint8_t XM = A2;  // must be an analog pin, use "An" notation!
const uint8_t YM = 7;   // can be a digital pin
const uint8_t XP = 6;   // can be a digital pin


TouchScreen ts = TouchScreen(XP, YP, XM, YM, 644);
MCUFRIEND_kbv tft(A2, A1, A0, A4);

//#define CS_PIN D2
void ResetPins(){
  pinMode(XM, OUTPUT);  // reset the pins after use.
  pinMode(YP, OUTPUT);
  pinMode(XP, OUTPUT);
  pinMode(YM, OUTPUT);
}
void ReadValues() {     //copy the following 2 functions into your program
  TFT_X_RANGE=Read16bitEeprom(EEPROM_OFFSET);
  TFT_Y_RANGE=Read16bitEeprom(EEPROM_OFFSET+2);
  TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
  TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
  TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
  TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}

uint16_t Read16bitEeprom(uint16_t location) {
  return( ((uint16_t) EEPROM.read(location+1)<<8) | (uint16_t) EEPROM.read(location));
}

#define TS_MINX 250
#define TS_MINY 200 // calibration points for touchscreen
#define TS_MAXX 3800
#define TS_MAXY 3750

//#define TFT_DC D4
//#define TFT_CS D8

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

//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

I can, if you want, upload all code. I haven't done it here because the code is quite extense.

Thanks.

Yes i do, since that is the TFT X & Y range , either 320 x 240 or 240 x 320 or for bigger size screens 320 x 480 etc.

It declares the 'tft' object that you use to write to the tft screen with.
All the calls to tft.setTextSize(2); and any other calls to functions depends on it.
Does python not use any object oriented programming ?

get rid of this

MCUFRIEND_kbv tft(A2, A1, A0, A4);

and just use

MCUFRIEND_kbv tft;  

the default values work for you.

and get rid of this

#define TS_MINX 250
#define TS_MINY 200 // calibration points for touchscreen
#define TS_MAXX 3800
#define TS_MAXY 3750

because those are not the correct values, and we are loading the correct values into these variables

TS_TOP=Read16bitEeprom(EEPROM_OFFSET+4);
  TS_RT=Read16bitEeprom(EEPROM_OFFSET+6);
  TS_BOT=Read16bitEeprom(EEPROM_OFFSET+8);
  TS_LEFT=Read16bitEeprom(EEPROM_OFFSET+10);
}

you may need to rename the variables in your sketch to match what you intend to use as a name

Hello Deva thanks for your time, my rodeo with python is more related to find roots or fuctions aproximations using several methods (Newton, Runge-Kutta, Bisec, trapezoidal, etc...) which envolves quite "easy" codes, but indeed python has OOP (i've only scretch this surface by using some classes). Python at geology is more like a tool to help us analizing field data however, there is some colleges that use python on a more "hardcore" level but im more into geochemestry rather than tectonics, hence the Geiger.

I will rectify the code tomorow as soon as i have time.

Thank you again!

Yeah good. I mean the main thing to understand is that create a working tft-touch sketch, you create 2 objects, one for the tft and one for the ts.
you use the tft object to draw on the screen and you use the ts object to read if and where there is pressure applied to the screen.
unfortunately the X & Y resolutions of these 2 parts do not match, so whatever values you get from the ts, need to be converted to the values that relate to the tft.
if the tft Y range runs between 0 - 320 and the corresponding ts range is 1023 - 195 and coming in as an x coordinate, you will need to map the result using the map() function.
so it would be something like

Ypoint = map(TSX, 1023, 195, 0, 320);

and when i say something like that, i mean exactly that.
It all really depends on the orientation of the tft screen,, how you want it and on the orientation of the TS.

Of course this is not really a beginners project due to the nature of these screens (more like intermediate) and there are some anomalies with the library. The best thing you can do to make sure you understand what you are doing is to create a sketch yourself, that reads a touch and draws a smal object (dop or circle or square) where you have read that touch on the screen. Then you know you have done the conversion correctly.

Hello Deva, you said that the X/Y resolutions don't match, would they match if the screen was a square (it's obvious in terms of lenghts but don't know in terms of resolution). I pretend to use the screen in a portrait/vertical orientation. I've googled the function map() and i found it depends on 5 parameters, value, Fromlow, Fromhigh, Tolow, Tohigh, but i can't understand where you got those values from and you use that particular function to correct the screen true (x,y) coordenates with the ones you get by touching, correct? And that function corresponds to the value of TFT_X/Y_Range, right?

Also, do i need to run the void comands you've wrote a few repplies ago inside the void loop or can i leave it "outside"?

Thanks!