ILI9341 TFT Touch Problem

Hello, everyone.
I am very enthusiastic about Squareline Studio and finally managed to export the project for Arduino and run it successfully on my ESP32 Dev Module with ILI9341 display.

Unfortunately, the touch doesn’t work and I can’t click any buttons.
Then I got the Touch X,
Read Y and Z positions and that works.
The Test_Touch_Controller example also works perfectly, just not on my Squareline Studio project.

Can someone help me why it doesn’t work with the touch?


#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
#define TOUCH_CS 21     // Chip select pin (T_CS) of touch screen

Edit: The touch already shows a value over 300 at the edge, could this be the problem?

I thank you in advance.


Did you calibrate your display with example from TFT_eSPI?

Thanks for the answer.
I’ve been trying to do this with Espressif for a few days now, but my ESP32 board isn’t included in Squareline Studio. Are there ready board packages for ESP32 Dev Kit C V4?


I think @dronecz meant this example to calibrate the touchpad.

The goal is to get values from TP read between 0..horizontal resolution and 0..vertical resolution.

I thank you.
Touch works, but I can’t click anything. I calibrated my screen and took the values, but unfortunately I still can’t click anything.

Why is that?


I just can’t get any further and I still have this touch problem.

Here’s the Arduino sketch:

#include <lvgl.h>
#include <TFT_eSPI.h>
#include "ui.h"

/*If you want to use the LVGL examples,
  make sure to install the lv_examples Arduino library
  and uncomment the following line.
#include <lv_examples.h>

/*Change to your screen resolution*/
static const uint16_t screenWidth  = 240;
static const uint16_t screenHeight = 320;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * screenHeight / 10 ];

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char * buf)

/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
    uint32_t w = ( area->x2 - area->x1 + 1 );
    uint32_t h = ( area->y2 - area->y1 + 1 );

    tft.setAddrWindow( area->x1, area->y1, w, h );
    tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );

    lv_disp_flush_ready( disp );

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
    uint16_t touchX = 0, touchY = 0;

    bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );

    if( !touched )
        data->state = LV_INDEV_STATE_REL;
        data->state = LV_INDEV_STATE_PR;

        /*Set the coordinates*/
        data->point.x = touchX;
        data->point.y = touchY;

        Serial.print( "Data x " );
        Serial.println( touchX );

        Serial.print( "Data y " );
        Serial.println( touchY );

void setup()
    Serial.begin( 115200 ); /* prepare for possible serial debug */

    String LVGL_Arduino = "Hello Arduino! ";
    LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();

    Serial.println( LVGL_Arduino );
    Serial.println( "I am LVGL_Arduino" );


#if LV_USE_LOG != 0
    lv_log_register_print_cb( my_print ); /* register print function for debugging */

    tft.begin();          /* TFT init */
    tft.setRotation( 0 ); /* Landscape orientation, flipped */
    uint16_t coords[5] = { 323, 3474, 412, 3442, 4 };

    lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * screenHeight / 10 );

    /*Initialize the display*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init( &disp_drv );
    /*Change the following line to your display resolution*/
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_drv_register( &disp_drv );

    /*Initialize the (dummy) input device driver*/
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init( &indev_drv );
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register( &indev_drv );


    Serial.println( "Setup done" );

void loop()
    lv_timer_handler(); /* let the GUI do its work */

    uint16_t x, y;

    tft.getTouchRaw(&x, &y);

    String s = "X: "+String(x)+"    Y: "+String(y)+"    Z: "+String(tft.getTouchRawZ());
    lv_label_set_text(ui_Screen1_Label1, s.c_str());
    Serial.println("x: "+ String(x)+"        y: "+ String(y)+"        z: "+ tft.getTouchRawZ());


And here the user setup:

// See SetupX_Template.h for all options available
#define USER_SETUP_ID 42

#define ILI9341_DRIVER

//#define TFT_MISO 19  // (leave TFT SDO disconnected if other SPI devices share MISO)
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Optional touch screen chip select
#define TOUCH_CS 5 // Chip select pin (T_CS) of touch screen

#define LOAD_GLCD    // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2   // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4   // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6   // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7   // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8   // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF   // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts


// TFT SPI clock frequency
// #define SPI_FREQUENCY  20000000
// #define SPI_FREQUENCY  27000000
#define SPI_FREQUENCY  40000000
// #define SPI_FREQUENCY  80000000

// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY  16000000

// SPI clock frequency for touch controller
#define SPI_TOUCH_FREQUENCY  2500000

It just doesn’t work for me to click on the components.
Did I do something wrong?

Finally got it.
In this line:

bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );

is touched to false and have now replaced it like this:

bool touched = tft.getTouch( &touchX, &touchY, 600 );

Nevertheless thanks for the help.

Edit: Only the touch is offset by a few pixels when I have rotation set to 3, how can I fix this?
I calibrated it again but it has no effect.
Edit2: I swapped the width and height and now it works.

TFT_eSPI tft = TFT_eSPI(screenHeight, screenWidth); /* TFT instance */



Thank you for this! I was struggling!

Curious if you have a solution for when the touch coordinates are flipped?
The display is oriented correctly yet the touch areas seemed to be 180 degrees flipped.

Thanks again!

My mistake. The display was flipped!

 tft.setRotation( 1 ); /* Landscape orientation, non-flipped */

Sorry to re-open this thread, but I had the same issue of the flipped coordinates, I mean that the Y coordinates are flipped…if I press on left the button on the right screen will be pressed and viceversa…what is the issue?
Thanks in advance!

You can easily flip the coordinates in read_cb. E.g.:

bool touched = tft.getTouch( &touchX, &touchY, 600 );
if(touched) {
    touchX = hor_res - touchX;
    touchY = hor_res - touchY;
1 Like