Problem with ILI9341 TFT + XPT2046 Touch + SD-CARD

Hello guys and thank you in advance for taking your timing dealing with my silly problems.

The problem:
I'm trying to get a touch TFT module with integrated SD-card to work.
The display and touch on their own are working just fine but as soon as I want to include the SD-card functionality the touch does not respond anymore and the initialization fails.

TFT driver: ILI9341
Touch controller: XPT2046ä

Can you guys figure it out?

#include <stdlib.h>
#include <SPI.h>
#include "SdFat.h"
#include "Adafruit_GFX.h"     
#include "Adafruit_ILI9341.h" 
#include "URTouch.h"

// SD-Card
        
SdFat SD;
#define SD_CS_PIN 2   // Select Pin D2 as the chip select pin for the SD-Card
File myFile;

// TFT-Screen Pin Belegung & Initialisierung
// 320x240

#define TFT_DC 9              
#define TFT_CS 10            
#define TFT_RST 8
#define TFT_MISO 12         
#define TFT_MOSI 11           
#define TFT_CLK 13            

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);


// Touch-Controller Pin Belegung & Initialisierung
// xmin = 7, xmax = 326
// ymin = 0, ymax = 232

#define t_SCK 3              
#define t_CS 4                
#define t_MOSI 5              
#define t_MISO 6             
#define t_IRQ 7              

URTouch ts(t_SCK, t_CS, t_MOSI, t_MISO, t_IRQ);


// Numpad Konstanten

const char numpadchars[12] = {'7', '8', '9', '4', '5', '6', '1', '2', '3', '<', '0', 'E'};
const unsigned int rim = 5;
const unsigned int x0 = 162;   // max 320
const unsigned int y0 = 31;    // max 240
const unsigned int height = 46;
const unsigned int width = 46; 
const int textcolor = ILI9341_BLACK;
const int bgcolor = ILI9341_WHITE;
const unsigned int textsize = 2;

int setnumber[5] = {0, 0, 0, 0, 0};
int setcursor = 0;
bool numpadtoggle = false;

void setup()
{
  tft.begin();                     
  tft.setRotation(1);           
 
  ts.InitTouch();                   
  ts.setPrecision(PREC_EXTREME);
  tft.fillScreen(ILI9341_BLACK);

  tft.fillRect(5, 5, 86, 46, bgcolor);
  tft.setTextColor(ILI9341_BLACK);  
  tft.setTextSize(2);               
  tft.setCursor(7,17);              
  tft.print("Eingabe");
  
  drawnumber();
   
  Serial.begin(9600);
  pinMode(SD_CS_PIN, OUTPUT);
  Serial.print("Initializing SD card...");

  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}
 
void loop()
{     
  int xtouch, ytouch;  
                 
  while(ts.dataAvailable())        
  {
    ts.read();
    xtouch = ts.getX();                 
    ytouch = ts.getY();                  
    if((xtouch != -1) && (ytouch != -1))    // to make sure there is no funny business going on
    {
      xtouch = 326 - xtouch; 

      if((xtouch >= 5) && (ytouch >= 5) && (xtouch <= 86) && (ytouch <= 46)) 
      {
        numpad();
      }

      if(numpadtoggle)
      {
        int num = numpadtouch(xtouch, ytouch);
        
        if(num == 10)    // delete
        {
          if(setcursor != 0)
            setcursor--;
            
          setnumber[setcursor] = 0;
        }
        else if(num == 11)   // enter
        {
          numpad();
          setcursor = 0;
        }
        else if (num != -1)   // normal input
        {
          if(setcursor < 5)
          {
            setnumber[setcursor] = num;
            setcursor++;
          }          
        }
        //drawnumber();

        for(int i = 0; i < 5; i++)
        {
          char temp[1];
          itoa(setnumber[i], temp, 10);
          tft.drawChar(10 + (i * (textsize * 6)), 60, temp[0], ILI9341_WHITE, ILI9341_BLACK, textsize);
        }
      }
    }
  }
}

void drawnumber()
{
  for(int i = 0; i < 5; i++)
  {
    char temp[1];
    itoa(setnumber[i], temp, 10);
    tft.drawChar(10 + (i * (textsize * 6)), 60, temp[0], ILI9341_WHITE, ILI9341_BLACK, textsize);
  }
}

void numpad()   // Zeichnet ein statisches Numpad
{   
  for(int i = 0; i < 4; i++)
  {
    int x = x0 + rim;
    int y = y0 + i * height + (i+1) * rim;
    
    for(int k = 0; k < 3; k++)
    {
      if(!numpadtoggle)
      {
        tft.fillRect(x, y, width, height, bgcolor); 
        tft.drawChar(x + ((width / 2) - ((5 * textsize) / 2)), y + ((height / 2) - ((8 * textsize) / 2)), numpadchars[k + (3 * i)], textcolor, bgcolor, textsize);          
      }
      else if (numpadtoggle)
      {
        tft.fillRect(x, y, width, height, textcolor);
      }
      x = x + width + rim;
    }
  }
  numpadtoggle = !numpadtoggle; 
}

int numpadtouch(int x, int y)   // Kümmert sich um die Interaktion mit dem zuvor initalisiertem Numpad 
{
  int xcalc = x0 + rim;
  int ycalc = y0 + rim;
  int xid = -1;
  int yid = -1;
   
  if((x > xcalc) && (y > ycalc))    // check if coordinates are smaller than the numpad 
  {
    xid++;
    yid++;
    
    while(x > xcalc + width + rim)
    {
       xcalc = xcalc + width + rim;
       xid++;
    }
    while(y > ycalc + height + rim)
    {
      ycalc = ycalc + height + rim;
      yid++;
    }
  }

  if((xid < 0) || (yid < 0) || (xid > 2) || (yid > 3))    // check if coordinates lay withing the area of the touchpad
  {
    delay(100);
    return -1;
  }

  int xpos = x0 + ((xid + 1) * rim) + (xid * width);    // x coordinate used to draw the animation
  int ypos = y0 + ((yid + 1) * rim) + (yid * width);    // y coordinate used to draw the animation

  tft.fillRect(xpos, ypos, width, height, ILI9341_GREEN);
  tft.drawChar(xpos + ((width / 2) - (5 * textsize / 2)), ypos + ((height / 2) - 8 * textsize / 2), numpadchars[xid + (3 * yid)], textcolor, ILI9341_GREEN, textsize);

  delay(100);

  tft.fillRect(xpos, ypos, width, height, ILI9341_WHITE);
  tft.drawChar(xpos + ((width / 2) - (5 * textsize / 2)), ypos + ((height / 2) - 8 * textsize / 2), numpadchars[xid + (3 * yid)], textcolor, bgcolor, textsize);

  if(yid == 3)
  {
    if(xid == 0)
      return 10;
    else if(xid == 1)
      return 0;
    else
      return 11;  
  }
  else
  {
    return (7 + xid) - (3 * yid);
  }
}

unsigned long numpadoutput(int x, int y)
{
  unsigned int count = 10000;
  unsigned long number = 0;

  while(count >= 1)
  {
    long inputL = numpadtouch(x, y);

    if((inputL >= 0) && (inputL < 10) &&(count >= 1))
    {
      number = number + (inputL * count);
      count = count / 10;
    }
    else if ((inputL = 10)&& (number > 0)) 
    {
      number = number / (count * 100);
      number = number * (count * 100);
      count = count * 10;
    }
    else if(inputL = 11)
    {
      return number;
    }
  }
}

If you connect a device, in your case an SD card controller, to an SPI bus, you must hold that device's CS (chip select pin) high except when you want that device to have control of the bus.

You've got this far:

#define SD_CS_PIN 2   // Select Pin D2 as the chip select pin for the SD-Card

but nothing else from the SD card library so the chances are that nothing else is holding the pin high.

You can check this by adding

pinMode( SD_CS_PIN, INPUT_PULLUP ) ; // temporary test

in setup(), or maybe even setting it as an output pin and then setting it high.

Hello 6v6gt and thank you for taking your time.
The pulling high action of the !CS pin should be handled by the SPI library.
Neither the less I tried your suggestion and added

digitalWrite(SD_CS_PIN, HIGH);

at the start of the setup.
It did not change the problem.

I also have a logic analyzer here which confirms this.
Please view the attached pictures.
(the first one is with all the code referring to the SD-card uncommented, and it works)
I also added one which has all the SPI lines in it.

Oops. I was caught out by the search function in Windows Notepad (stuck in the search up mode) which I used to scan your code and did not see definitions.

The SD.begin( SD_CS_PIN ) statement should correctly handle the pin as you have said.

Which Arduino are you using ?
I've used a 2.8" SPI screen with with the same controllers as you, and I put the touch screen and the tft screen on the same (hardware) SPI bus. I Didn't use the SD card though. It appears that you are using multiple "SPI" buses. What have you gor the SD card connected to ?

I'm using an Arduino nano 328P with the old bootloader.
This display: LCD-Anzeigemodule online kaufen | eBay

I connected everthing according to this schematic. The SD-card is simply attached to the hardware SPI lines in parallel with ili9341 as cs pin I chose D2.

Your suggestion about using the hardware SPI for the XPT2046 (touch controller) seems like a good idea to me and I already thought about doing so myself, but I was scared away by it's datasheet, not mentioning that the chip is spi compatible.

Anyways I will try that and report in as soon as I'm done.
Thank you.

Which touch library did you use? Also URTouch?
Would you like to post your code?

I used this library: GitHub - PaulStoffregen/XPT2046_Touchscreen: Touchscreen Arduino Library for XPT2046 Touch Controller Chip

The whole project including software is here: Esp8266 Arduino Telephone Caller ID system with anti-spam feature - Exhibition / Gallery - Arduino Forum

The screen handling is in screen.h/.cpp and a pin usage summary is in the .ino file. I had to hack the touch screen library to handle some low quality touch screens I got. Hopefully you can use the standard one directly from github.

I'm back.
I tested some of the xpt2046 library provided examples, didn't let me upload, said my nano was a teensy.
Tested, just changing the SPI (SCK, MOSI, MISO) pins in my old programme, nope.

Wrote this new small test programme with the xpt2046 lib, TFT check, touch nope.

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>

//SPI Config

#define SCK 13        // Serial Clock
#define MISO 12       // Master In Slave Out
#define MOSI 11       // Master Out Slave In
#define TFT_SS 10     // TFT (ILI9341) Slave Select
#define Touch_SS 4    // Touch (XPT2046) Slave Selet
#define SD_SS 2       // SD-card Slave Select

#define TFT_DC 9      // TFT Data / Command
#define TFT_RST 8     // TFT Reset

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, MOSI, SCK, TFT_RST, MISO);


#define Touch_IRQ 7   // Touch Interrupt Request

XPT2046_Touchscreen ts(Touch_SS, Touch_IRQ);

void setup() {    
  tft.begin();                     
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);

  tft.fillRect(5, 5, 86, 46, ILI9341_WHITE);
  tft.setTextColor(ILI9341_BLACK);  
  tft.setTextSize(2);               
  tft.setCursor(7,17);              
  tft.print("Eingabe");

  Serial.begin(9600);
  
  ts.begin();
  ts.setRotation(1);    

  while (!Serial && (millis() <= 1000));  
}

void loop() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();
    Serial.print("Pressure = ");
    Serial.print(p.z);
    Serial.print(", x = ");
    Serial.print(p.x);
    Serial.print(", y = ");
    Serial.print(p.y);
    delay(30);
    Serial.println();
  }
}

Touch does not respond to my inputs in any meaningful way.
What it does, however, is periodically sending weird data, like this until it just stops.

Pressure = 4032, x = 63, y = 63
Pressure = 4032, x = 15, y = 31
Pressure = 3999, x = 15, y = 31
Pressure = 4032, x = 63, y = 63
Pressure = 4032, x = 31, y = 0
Pressure = 4048, x = 15, y = 0
Pressure = 3999, x = 63, y = 63
Pressure = 4032, x = 15, y = 31
Pressure = 4032, x = 63, y = 127
Pressure = 4032, x = 63, y = 63
Pressure = 4032, x = 63, y = 63
Pressure = 4033, x = 7951, y = 0
Pressure = 3999, x = 63, y = 63
Pressure = 4032, x = 63, y = 63
Pressure = 4032, x = 31, y = 0
Pressure = 3999, x = 28, y = 127
Pressure = 3999, x = 15, y = 0
Pressure = 3999, x = 31, y = 0
Pressure = 3999, x = 15, y = 31
Pressure = 4032, x = 31, y = 31
Pressure = 4032, x = 12, y = 63
Pressure = 3999, x = 63, y = 63
Pressure = 4067, x = 12, y = 32
Pressure = 4033, x = 31, y = 0
Pressure = 4033, x = 0, y = 15
Pressure = 4048, x = 31, y = 31
Pressure = 4033, x = 0, y = 63
Pressure = 4111, x = 7711, y = 0
Pressure = 4065, x = 62, y = 15
Pressure = 4065, x = 31, y = 31
Pressure = 4111, x = 31, y = 0
Pressure = 4063, x = 32, y = 34
Pressure = 3999, x = 31, y = 0
Pressure = 3999, x = 47, y = 0
Pressure = 4032, x = 63, y = 63
Pressure = 4048, x = 15, y = 63
Pressure = 3999, x = 27, y = 0
Pressure = 3999, x = 31, y = 0
Pressure = 3999, x = 31, y = 31
Pressure = 4032, x = 31, y = 0
Pressure = 3999, x = 47, y = 31
Pressure = 4037, x = 31, y = 0
Pressure = 4032, x = 15, y = 32

I also checked it with the logic analyzer which shows these data packages.

I suspect that, just like your screen, mine also is kinda crappy and I might have to mod the library.
Would you show me how you fixed this issue?

OK. But did the URTouch library give acceptable results (with the SD reader NOT activated) with the touch screen ?
If it did, then there is probably no point in looking further at the XPT2046 library if it fails to give good results here unless the XPT2046 library does work together with your SD card reader.

To get the changes I made, you could use the library which I incorporpated into my program folder instead of the original. Basically, I changed this definition:

#define Z_THRESHOLD

to lower the touch sensitivity.

and this function:

void XPT2046_Touchscreen::update()

to make multiple repeated reads (commands 0xD1 and 0X91 )

You know that you can just copy a library into the sketch folder and then use:

#include "XPT2046_Touchscreen.h"   // double quotes

instead of

#include <XPT2046_Touchscreen.h>

Useful if you hack a standard library.

I've just looked at the schematic and I'm not sure about the 10K series resistors which are clearly intended to drop MCU output signals from 5 volts to 3 volts.
If only the SD card reader gives a problem, you can get a separate one with a built in level shifter e.g.
https://www.ebay.com/itm/New-Micro-SD-TF-Card-Storage-Memory-Module-SPI-Level-conversion-For-Arduino/201128314754

Well I tried your modded library in this sketch:

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <Adafruit_ILI9341.h>
#include "XPT2046_Touchscreen.h"

//SPI Config

#define SCK 13        // Serial Clock
#define MISO 12       // Master In Slave Out
#define MOSI 11       // Master Out Slave In
#define TFT_SS 10     // TFT (ILI9341) Slave Select
#define Touch_SS 4    // Touch (XPT2046) Slave Selet
#define SD_SS 2       // SD-card Slave Select

#define TFT_DC 9      // TFT Data / Command
#define TFT_RST 8     // TFT Reset

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, MOSI, SCK, TFT_RST, MISO);


#define Touch_IRQ 7   // Touch Interrupt Request

XPT2046_Touchscreen ts(Touch_SS, Touch_IRQ);

void setup() {    
  tft.begin();                     
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);

  tft.fillRect(5, 5, 86, 46, ILI9341_WHITE);
  tft.setTextColor(ILI9341_BLACK);  
  tft.setTextSize(2);               
  tft.setCursor(7,17);              
  tft.print("Eingabe");

  Serial.begin(9600);
  
  ts.begin();
  ts.setRotation(1);    

  while (!Serial && (millis() <= 1000));  
}

void loop() {
  if (ts.touched()) {
    TS_Point p = ts.getPoint();
    Serial.print("Pressure = ");
    Serial.print(p.z);
    Serial.print(", x = ");
    Serial.print(p.x);
    Serial.print(", y = ");
    Serial.print(p.y);
    delay(30);
    Serial.println();
  }
}

Unfortunately, no matter how low or high I set the threshold it keeps sending coordinates and does not respond when I actually touch it.

I guess that test in post #9 was without any physical connections to any of the SD reader pins ?
So it looks like your experience with the URtouch library was better than with the XPT2046 library and previously the only problem appeared to be with the integration of the SD card reader.

I suppose the next test would be to connect only the pins for the touch screen and see if you get any further.

With the screen I used, I was using only 3.3 volts so I had no series resistors in the connections and the jumper marked J1 on screen was closed to bypass the regulator, but I'm not sure that makes a significant difference.

In your sketch, you should not have these definitions because these are already defined in pins_arduino.h as static constants and there may be a conflict:

#define SCK 13 // Serial Clock
#define MISO 12 // Master In Slave Out
#define MOSI 11 // Master Out Slave In

And this constructor:

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, MOSI, SCK, TFT_RST, MISO);

could be reduced to this alternative form:

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, TFT_RST );

Other than that, I can't suggest much more to try.

Thanks for the heads up about the SPI-pins but it doesn't change a thing (unfortunately).
I tried only connecting and only talking to the xpt2046, but it presented the same results.
I have now gone back to the UrTouch library and it's extra software SPI, not nice but it works.
Guess I'll need to wait for an extra SD-card reader and then try that one or on an STM32 or something.
Thank you for your help anyway.

Little Update here.

So I got myself a cheap stm32 dev board (blue pill) and got the TFT as well as the touch working using the xpt2046_Touchscreen.h and the Adafruit_ILI9341.h library.

So here is my code so far for anyone interested.

#include "Adafruit_ILI9341.h"
#include <stdlib.h>
#include "itoa.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <XPT2046_Touchscreen.h>
#include <SPI.h>


//////////////////////////////////////////////////
////////////////// TFT-Display ///////////////////
//////////////////////////////////////////////////
/////////////////// 320 x 240 ////////////////////
//////////////////////////////////////////////////

#define TFT_RST 2
#define TFT_DC 3              
#define TFT_SS 4  
//#define TFT_MISO 6         
//#define TFT_MOSI 7           
//#define TFT_SCK 5   

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_SS, TFT_DC, TFT_RST);


//////////////////////////////////////////////////
////////////////// Touch-Screen //////////////////
//////////////////////////////////////////////////
//////////// Xmin : 140   Xmax : 3930 ////////////
//////////// Ymin : 200   Ymax : 3920 ////////////
//////////////////////////////////////////////////

#define Touch_SS  0
#define Touch_IRQ  1

//XPT2046_Touchscreen ts(CS_PIN);
//XPT2046_Touchscreen ts(CS_PIN);  // Param 2 - NULL - No interrupts
//XPT2046_Touchscreen ts(CS_PIN, 255);  // Param 2 - 255 - No interrupts
XPT2046_Touchscreen ts(Touch_SS, Touch_IRQ);  // Param 2 - Touch IRQ Pin - interrupt enabled polling


// Numpad Konstanten

const char numpadchars[12] = {'7', '8', '9', '4', '5', '6', '1', '2', '3', '<', '0', 'E'};
const unsigned int rim = 5;
const unsigned int x_0 = 162;   // max 320
const unsigned int y_0 = 31;    // max 240
const unsigned int height = 46;
const unsigned int width = 46; 
const int textcolor = ILI9341_BLACK;
const int bgcolor = ILI9341_WHITE;
const unsigned int textsize = 2;

int setnumber[5] = {0, 0, 0, 0, 0};
int setcursor = 0;
bool numpadtoggle = false;

void setup() {
  //Serial.begin(38400);  
  //while (!Serial && (millis() <= 1000));
  
  ts.begin();
  ts.setRotation(1);
  
  tft.begin();                     
  tft.setRotation(1);
     
  tft.fillScreen(ILI9341_BLACK);
  tft.fillRect(5, 5, 86, 46, bgcolor);
  tft.setTextColor(ILI9341_BLACK);  
  tft.setTextSize(2);               
  tft.setCursor(7,17);              
  tft.print("Eingabe");
  
  drawnumber();
}

void loop() {
  if (ts.tirqTouched()) {
    if (ts.touched()) {
      TS_Point p = ts.getPoint();
      int x_t = (3931 - (p.x - 20)) / 11.2;
      int y_t = (p.y - 260) / 15.4;
      if((x_t >= 0) && (y_t >= 0)){
        if((x_t >= 5) && (y_t >= 5) && (x_t <= 86) && (y_t <= 46)) {
          numpad();
        }

        if(numpadtoggle) {
          int num = numpadtouch(x_t, y_t);
        
          if(num == 10) {         // delete
            if(setcursor != 0)
              setcursor--;
            
            setnumber[setcursor] = 0;
          }
          else if(num == 11) {    // enter
            numpad();
            setcursor = 0;
          }
          else if (num != -1) {   // normal input
            if(setcursor < 5) {
              setnumber[setcursor] = num;
              setcursor++;
            }          
          }
          //drawnumber();

          for(int i = 0; i < 5; i++) {
            char temp[1];
            itoa(setnumber[i], temp, 10);
            tft.drawChar(10 + (i * (textsize * 6)), 60, temp[0], ILI9341_WHITE, ILI9341_BLACK, textsize);
          }
        }
      }
      /*
      Serial.print("x = ");
      Serial.print(x);
      Serial.print(", y = ");
      Serial.print(y);
      delay(30);
      Serial.println();
      tft.fillCircle(x, y, 4, ILI9341_YELLOW);
      */      
    }
  }
}

void drawnumber()
{
  for(int i = 0; i < 5; i++)
  {
    char temp[1];
    itoa(setnumber[i], temp, 10);
    tft.drawChar(10 + (i * (textsize * 6)), 60, temp[0], ILI9341_WHITE, ILI9341_BLACK, textsize);
  }
}

void numpad()   // Zeichnet ein statisches Numpad
{   
  for(int i = 0; i < 4; i++)
  {
    int x = x_0 + rim;
    int y = y_0 + i * height + (i+1) * rim;
    
    for(int k = 0; k < 3; k++)
    {
      if(!numpadtoggle)
      {
        tft.fillRect(x, y, width, height, bgcolor); 
        tft.drawChar(x + ((width / 2) - ((5 * textsize) / 2)), y + ((height / 2) - ((8 * textsize) / 2)), numpadchars[k + (3 * i)], textcolor, bgcolor, textsize);          
      }
      else if (numpadtoggle)
      {
        tft.fillRect(x, y, width, height, textcolor);
      }
      x = x + width + rim;
    }
  }
  numpadtoggle = !numpadtoggle; 
}

int numpadtouch(int x, int y)   // Kümmert sich um die Interaktion mit dem zuvor initalisiertem Numpad 
{
  int xcalc = x_0 + rim;
  int ycalc = y_0 + rim;
  int xid = -1;
  int yid = -1;
   
  if((x > xcalc) && (y > ycalc))    // check if coordinates are smaller than the numpad 
  {
    xid++;
    yid++;
    
    while(x > xcalc + width + rim)
    {
       xcalc = xcalc + width + rim;
       xid++;
    }
    while(y > ycalc + height + rim)
    {
      ycalc = ycalc + height + rim;
      yid++;
    }
  }

  if((xid < 0) || (yid < 0) || (xid > 2) || (yid > 3))    // check if coordinates lay withing the area of the touchpad
  {
    delay(100);
    return -1;
  }

  int xpos = x_0 + ((xid + 1) * rim) + (xid * width);    // x coordinate used to draw the animation
  int ypos = y_0 + ((yid + 1) * rim) + (yid * width);    // y coordinate used to draw the animation

  tft.fillRect(xpos, ypos, width, height, ILI9341_GREEN);
  tft.drawChar(xpos + ((width / 2) - (5 * textsize / 2)), ypos + ((height / 2) - 8 * textsize / 2), numpadchars[xid + (3 * yid)], textcolor, ILI9341_GREEN, textsize);

  delay(100);

  tft.fillRect(xpos, ypos, width, height, ILI9341_WHITE);
  tft.drawChar(xpos + ((width / 2) - (5 * textsize / 2)), ypos + ((height / 2) - 8 * textsize / 2), numpadchars[xid + (3 * yid)], textcolor, bgcolor, textsize);

  if(yid == 3)
  {
    if(xid == 0)
      return 10;
    else if(xid == 1)
      return 0;
    else
      return 11;  
  }
  else
  {
    return (7 + xid) - (3 * yid);
  }
}

unsigned long numpadoutput(int x, int y)
{
  unsigned int count = 10000;
  unsigned long number = 0;

  while(count >= 1)
  {
    long inputL = numpadtouch(x, y);

    if((inputL >= 0) && (inputL < 10) &&(count >= 1))
    {
      number = number + (inputL * count);
      count = count / 10;
    }
    else if ((inputL = 10)&& (number > 0)) 
    {
      number = number / (count * 100);
      number = number * (count * 100);
      count = count * 10;
    }
    else if(inputL = 11)
    {
      return number;
    }
  }
}

OK. I'm pleased that you found a solution.
Did you drop the 10k resistors on the signal lines ?
If so, I guess the lesson is that the specified 3.3 working voltage of the screen components can not be so easily worked around.

in order to use it with 5v logic :

  1. you remove the "short" (if any) on pcb regulator, so VCC passes thru the regulator and powers the pcb locally with 3.3

  2. make a voltage divider (2 resistors) : 1K from each output (as seen from arduino) goes to 3k and TFT input, the other end of 3K ->GND. (so you have roughly 3/4 * 5V).

  3. Take care of backlight voltage. you need around 3.3v. Some pcbs have regulator and resistor, others hav a single resistor ~3r9 . So if you power backlight from 5V, either you must include the regulator for backlight, or you replace the 3r9 with ~22-27Ohm, or add in series a ~20-24.