ESP32: TFT LCD Touchscreen Display – 2.8 inch ILI9341 240×320 (Arduino IDE)

In this guide, you’ll learn how to get started with the TFT LCD Touchscreen Display with the ESP32 board. This TFT Touchscreen with 2.8 inch display (240×320 px) comes with the ILI9341 driver. This display is a great option to build graphical user interfaces (GUI) for your IoT projects.

ESP32 TFT LCD Touchscreen Display  2.8 inch ILI9341 240×320 Arduino IDE

We recommend an ESP32 board that has an on-board TFT display, read our Getting Started with ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R)

Introducing the TFT LCD Touchscreen Display

The display we’re using in this guide is the 2.8. inch TFT LCD that also comes with a touchscreen. The display communicates via SPI communication protocol and uses the ILI9341 driver. You can write text, draw shapes, and display images. The touchscreen also uses the SPI communication protocol.

The TFT LCD touchscreen also comes with an SD card interface if you need to load files for your specific project. This display is also available with different screen sizes.

Parts Required

For this project, you need to wire the TFT display and touchscreen pins to the ESP32. Here’s a list of parts you need:

Wiring TFT LCD Touchscreen display to ESP32

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Wiring the TFT LCD Touchscreen Display to the ESP32 Board

Wiring the TFT LCD Touchscreen Display to the ESP32 Board

Wire the TFT LCD and touchscreen pins to the following ESP32 GPIOs (you must use these exact pins, otherwise the project will not work).

TFT LCD TouchscreenESP32
T_IRQGPIO 36
T_OUTGPIO 39
T_DINGPIO 32
T_CSGPIO 33
T_CLKGPIO 25
SDO(MISO)GPIO 16
LEDGPIO 21
SCKGPIO 14
SDI(MOSI)GPIO 13
D/CGPIO 2
RESETGPIO 12
CSGPIO 15
GNDGND
VCC5V (or 3.3V)*

* In the VCC pin, you can either use 5V or 3.3V depending if your J1 connection is open or closed (by default it’s usually open as you can see in the figure below).

VCC = 5V | J1=OPEN
VCC = 3.3V | J1=CLOSE
TFT LCD Touchscreen display J1 connection

Recommended reading: ESP32 Pinout Reference: Which GPIO pins should you use?

Installing Arduino Libraries

The ESP32 communicates with the TFT Display and Touchscreen using SPI communication protocol. We’ll be using the TFT_eSPI and XPT2046_Touchscreen libraries.

Installing the TFT_eSPI Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for TFT_eSPI. Select the TFT_eSPI library by Bodmer and install it.

Installing TFT_eSPI library Bodmer Arduino IDE 2

Installing the XPT2046_Touchscreen Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for XPT2046_Touchscreen. Select the XPT2046_Touchscreen library by Paul Stoffregen and install it.

Installing XPT2046_Touchscreen Library by Paul Stoffregen Arduino IDE 2

Prepare User_Setup.h Config File for TFT_eSPI Library

To properly use the TFT_eSPI library, you need a configuration file called User_Setup.h with the right definitions. We’ve already prepared that file so that you don’t have any configuration issues following our examples. You just need to download it and move it to the right folder. Follow the next instructions to learn how to do it.

a) Preparing the Config File – Windows PC

b) Preparing the Config File – Mac OS

a) Preparing the Config File – Windows PC

Having both libraries installed (TFT_eSPI and XPT2046_Touchscreen), download the User_Setup.h configuration file.

User_Setup.h file for TFT_eSPI library Bodmer Arduino IDE 2

In your Arduino IDE, go to File and open the Preferences menu.

Open Arduino IDE 2 Preferences Menu Windows PC

Copy the Arduino IDE “Sketchbook location” path. In my case it’s:

C:\Users\rui_s\Documents\Arduino
Open Sketchbook Location Arduino IDE 2 Browse

Then, in your Windows PC File Explorer tab enter the sketchbook location path to open the Arduino folder (it’s usually under the Documents folder).

Browse to Arduino libraries folder to copy lv_conf.h file Arduino IDE 2

Open the libraries folder:

Open the Arduino IDE 2 Libraries Folder Windows PC

You should see the TFT_eSPI library folder there. Open it.

Open TFT_eSPI folder libraries Arduino IDE 2

You should be in a similar folder path as shown below:

C:\Users\rui_s\Documents\Arduino\libraries\TFT_eSPI

Copy the User_Setup.h file provided earlier and replace the existing file.

Move copy User_Setup.h file to TFT_eSPI library folder Arduino IDE 2

IMPORTANT: other User_Config.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials. You must use the exact User_Config.h file provided in this article.

b) Preparing the Config File – Mac OS

Having both libraries installed (TFT_eSPI and XPT2046_Touchscreen), download the User_Setup.h configuration file.

Download User_Setup.h file for TFT_eSPI library Bodmer Arduino IDE 2

In your Arduino IDE, open the Settings menu.

Open Arduino IDE 2 Preferences Menu Mac OS

Copy the Arduino IDE “Sketchbook location” path. In my case, it’s:

/Users/rui/Documents/Arduino
Open Sketchbook Location Arduino IDE 2 Browse Mac OS

In Finder, type ~/.arduinoIDE/ and open that directory.

Open the Arduino IDE 2 Folder Mac OS

Open the libraries folder.

Open the Arduino IDE 2 Libraries Folder Mac OS

You should see the TFT_eSPI library folder there. Open it.

Open TFT_eSPI folder libraries Arduino IDE 2 Mac OS

You should be in a similar folder path as shown below:

/Users/rui/Documents/Arduino/libraries/TFT_eSPI

Copy the User_Setup.h file provided earlier and replace the existing file.

Move copy User_Setup.h file to TFT_eSPI library folder Arduino IDE 2 Mac OS

You should now have the User_Setup.h file provided on that path.

Move User_Setup.h file to TFT_eSPI library folder Arduino IDE 2 Mac OS

IMPORTANT: other User_Config.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials. You must use the exact User_Config.h file provided in this article.

Code – Display Text and Testing the Touchscreen

The following code displays a simple text in your TFT display and allows you to test the touchscreen. When you press the touchscreen with your finger or pen, it should print the coordinates and pressure.

Copy the following code to the Arduino IDE and upload it to your board.

/*  Rui Santos & Sara Santos - Random Nerd Tutorials
    THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE:
    1) ESP32-2432S028R 2.8 inch 240×320 also known as the Cheap Yellow Display (CYD): https://makeradvisor.com/tools/cyd-cheap-yellow-display-esp32-2432s028r/
      SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/cyd/
    2) REGULAR ESP32 Dev Board + 2.8 inch 240x320 TFT Display: https://makeradvisor.com/tools/2-8-inch-ili9341-tft-240x320/ and https://makeradvisor.com/tools/esp32-dev-board-wi-fi-bluetooth/
      SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/esp32-tft/
    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/

#include <SPI.h>

/*  Install the "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI
    *** IMPORTANT: User_Config.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***
    *** YOU MUST USE THE User_Config.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***
    FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd/ or https://RandomNerdTutorials.com/esp32-tft/   */
#include <TFT_eSPI.h>

// Install the "XPT2046_Touchscreen" library by Paul Stoffregen to use the Touchscreen - https://github.com/PaulStoffregen/XPT2046_Touchscreen
// Note: this library doesn't require further configuration
#include <XPT2046_Touchscreen.h>

TFT_eSPI tft = TFT_eSPI();

// Touchscreen pins
#define XPT2046_IRQ 36   // T_IRQ
#define XPT2046_MOSI 32  // T_DIN
#define XPT2046_MISO 39  // T_OUT
#define XPT2046_CLK 25   // T_CLK
#define XPT2046_CS 33    // T_CS

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 2

// Touchscreen coordinates: (x, y) and pressure (z)
int x, y, z;

// Print Touchscreen info about X, Y and Pressure (Z) on the Serial Monitor
void printTouchToSerial(int touchX, int touchY, int touchZ) {
  Serial.print("X = ");
  Serial.print(touchX);
  Serial.print(" | Y = ");
  Serial.print(touchY);
  Serial.print(" | Pressure = ");
  Serial.print(touchZ);
  Serial.println();
}

// Print Touchscreen info about X, Y and Pressure (Z) on the TFT Display
void printTouchToDisplay(int touchX, int touchY, int touchZ) {
  // Clear TFT screen
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_BLACK, TFT_WHITE);

  int centerX = SCREEN_WIDTH / 2;
  int textY = 80;
 
  String tempText = "X = " + String(touchX);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);

  textY += 20;
  tempText = "Y = " + String(touchY);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);

  textY += 20;
  tempText = "Pressure = " + String(touchZ);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);
}

void setup() {
  Serial.begin(115200);

  // Start the SPI for the touchscreen and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  // Set the Touchscreen rotation in landscape mode
  // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 3: touchscreen.setRotation(3);
  touchscreen.setRotation(1);

  // Start the tft display
  tft.init();
  // Set the TFT display rotation in landscape mode
  tft.setRotation(1);

  // Clear the screen before writing to it
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_BLACK, TFT_WHITE);
  
  // Set X and Y coordinates for center of display
  int centerX = SCREEN_WIDTH / 2;
  int centerY = SCREEN_HEIGHT / 2;

  tft.drawCentreString("Hello, world!", centerX, 30, FONT_SIZE);
  tft.drawCentreString("Touch screen to test", centerX, centerY, FONT_SIZE);
}

void loop() {
  // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z) info on the TFT display and Serial Monitor
  if (touchscreen.tirqTouched() && touchscreen.touched()) {
    // Get Touchscreen points
    TS_Point p = touchscreen.getPoint();
    // Calibrate Touchscreen points with map function to the correct width and height
    x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    z = p.z;

    printTouchToSerial(x, y, z);
    printTouchToDisplay(x, y, z);

    delay(100);
  }
}

View raw code

How the Code Works

Let’s take a quick look at the parts of the code that are relevant to this example.

Libraries

Include the SPI, TFT_eSPI and XPT2046_Touchscreen libraries.

#include <SPI.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>

Initialize TFT

Create a TFT_eSPI instance:

TFT_eSPI tft = TFT_eSPI();

Initialize Touchscreen

The following lines set the touchscreen pinout:

#define XPT2046_IRQ 36
#define XPT2046_MOSI 32
#define XPT2046_MISO 39
#define XPT2046_CLK 25
#define XPT2046_CS 33

Create a touchscreenSPI and touchscreen instances:

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

Other Variables

Set the screen width, screen height, and font size:

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 2

Variables to store the coordinates: (x, y) and pressure (z).

int x, y, z;

setup()

Start a serial communication with the Serial Monitor at a baud rate of 115200:

Serial.begin(115200);

Start the SPI for the touchscreen and initialize the touchscreen.

touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
touchscreen.setRotation(1);

Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 3: touchscreen.setRotation(3);

Start the TFT display and set the TFT display rotation in landscape mode.

tft.init();
tft.setRotation(1);

Set the TFT screen background to white. Then, set the text color to black with white background.

tft.fillScreen(TFT_WHITE);
tft.setTextColor(TFT_BLACK, TFT_WHITE);

Set X and Y coordinates for the center of the display.

int centerX = SCREEN_WIDTH / 2;
int centerY = SCREEN_HEIGHT / 2;

Display two centered welcome messages in the TFT display:

tft.drawCentreString("Hello, world!", centerX, 30, FONT_SIZE);
tft.drawCentreString("Touch screen to test", centerX, centerY, FONT_SIZE);

loop()

In the loop(), it constantly checks if the touchscreen was touched.

if (touchscreen.tirqTouched() && touchscreen.touched()) {

When it detects that the touchscreen was touched, it will get the (x,y) coordinates and the pressure (z) from the point.

TS_Point p = touchscreen.getPoint();
// Calibrate Touchscreen points with map function to the correct width and height
x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
z = p.z;

Call the printTouchToSerial and printTouchToDisplay functions to print the touchscreen info in the Serial Monitor and TFT display.

printTouchToSerial(x, y, z);
printTouchToDisplay(x, y, z);

printTouchToSerial()

The printTouchToSerial() function prints touchscreen info about X, Y, and Pressure (Z) on the Serial Monitor.

void printTouchToSerial(int touchX, int touchY, int touchZ) {
  Serial.print("X = ");
  Serial.print(touchX);
  Serial.print(" | Y = ");
  Serial.print(touchY);
  Serial.print(" | Pressure = ");
  Serial.print(touchZ);
  Serial.println();
}

printTouchToDisplay()

The printTouchToDisplay() function prints touchscreen info about X, Y, and Pressure (Z) on the TFT Display.

void printTouchToDisplay(int touchX, int touchY, int touchZ) {
  // Clear TFT screen
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_BLACK, TFT_WHITE);

  int centerX = SCREEN_WIDTH / 2;
  int textY = 80;
 
  String tempText = "X = " + String(touchX);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);

  textY += 20;
  tempText = "Y = " + String(touchY);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);

  textY += 20;
  tempText = "Pressure = " + String(touchZ);
  tft.drawCentreString(tempText, centerX, textY, FONT_SIZE);
}

Demonstration

Upload the code to your board. Go to Tools > Board and select ESP32 > ESP32 Dev Module. Then, select the right COM port in Tools > Port. Finally, click the upload button.

Arduino IDE 2 Upload Button

After uploading the code to your board, it should display the sample “Hello, world!” text centered at the top. Press the touchscreen with your finger to test it.

ESP32 with TFT Touchscreen LCD Write Text

It should print the coordinates: (x, y) and pressure (z) in the TFT display. You should note that this is a 240x320px resistive touchscreen.

Testing TFT LCD Touchscreen with the ESP32

The coordinates and pressure are also printed on your Arduino IDE serial monitor:

ESP32 TFT LCD Touchscreen Display 2.8 inch ILI9341 240×320 Testing Arduino IDE Serial Monitor

Wrapping Up

In this tutorial, you learned how to use the TFT touchscreen LCD display with the ILI9341 driver using an ESP32. This setup is useful for creating dashboards and GUIs for your DIY projects.

If you prefer to use an ESP32 dev board with a built-in TFT display, read our Getting Started with ESP32 Cheap Yellow Display Board.

We hope you found this tutorial useful. We’ll be posting more guides, so stay tuned.

To learn more about the ESP32, make sure to take a look at our resources:



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

16 thoughts on “ESP32: TFT LCD Touchscreen Display – 2.8 inch ILI9341 240×320 (Arduino IDE)”

  1. This, and the recent tutorial on the CYD, ‘Cheap Yellow Display’ are great. I’ve been trying to sort this out for a while. Other resources didn’t handle the ‘setup.h’ file at all well and yours just works.
    For a future tutorial idea, getting started with the CYD and Squareline Studio would be very useful?

    Reply
  2. Dear Rui,
    Very interesting project. As I have a Wemos Di R32 board (Arduino Uno – based) with Esp32 functionality, my question: Can I use and click-on the TFT- screen on my Wemos- board? And how do I have to take care for the 5V/ 3.3V jumper setting on the board?
    Many thanks for your reply,

    Alex

    Reply
  3. I gave up trying to get TFT to work with esp32 so I bout 5″elecrow display same as in your post display & esp32 in one package. Since it seem easier to use with Square line studio to create GUI but I don’t understand how to Read in analog sensor and display on the squareline Gui gauges using this TFT screen if you could do a write-up on it would greatly appreciate it.

    Reply
  4. I hope you do a more longer tutorial like the one you did on ssd1306 oled display , I mean not describing who each chunk of code works but rather explaining each function alone outside of a program (see the tutorial to understand what I am saying)

    Reply
    • Hello Osmax,
      Yes, we definitely have many guides lined up for this display… This is just a basic getting started to prepare the libraries correctly and ensure you can run the code with out display

      Reply
  5. This is the only code that actually worked for me. I am using an ILI9486 so I only had to change a couple of settings. I had trouble with finding a setup that included touchscreen settings for the touch pins.
    Maybe you could write a GUI application using this setup.
    Anyway thank you for writings this.

    James

    Reply
  6. Great Guide.
    Quick question Is there a reason you used the Default SDA (GPIO21) for LED CS?
    Which presents a Idea for a project using both the TFT touch and a I2C LCD display & a DS18B20 temp sensor. This would be a great learning tool on interfacing multiple diferent I2C devices. Granted using both a TFT and a LCD is not common (I use it in model railroading TFT is the GUI LCD status display) but it does demo multiple I2C nicely.

    Another Guide would be a series of guides with the TFT & WiFi enabled and a simple TX PLC/message control protocal allowing remote ESP 32’s to send say temp data to a central TFT/LCD display and allow the Central TFT to send commands to say ESP 32 4 relay devices and retrieve status basicly creating a multi node Home automation system. (Again I use this in Model Railroading)

    Reply
  7. Hey please help I am not able to get the output or see anything on my 3.5 inch LCD TFT touch screen display with ILI9341 DRIVER when interfaced with Esp wroom 32 with 38 pin .I tried to make changes in the code by changing the resolution in code to 480 x 320 and many more changes tried trouble shooting .
    Here are the related documents to support my statement and get a better understanding aboout my components.
    drive.google.com/drive/folders/1zEo43EpFC_e7ijSBt-KvHDhuR-4aXnAP?usp=drive_link

    Please help me solve this issue and print the output in the tft display also. The connections are right as the touch have been detected by the esp 32 and output of the code and part of code is executed and obtained at Serial Monitor. Please Help.

    Reply
  8. As far as I can see, all of your excellent tutorials are written for the Arduino IDE. A very common alternative is VScode. Can you imagine writing tutorials for this IDE as well, or better yet, pointing out the differences. In my opinion, a key difference lies in the handling of the libraries to be integrated.
    The reason for my question: I was unable to port this tutorial to VScode. When compiling with your customized library there is an error when calling XPT2046_Touchscreen::begin (to many arguments)

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.