In this tutorial you will learn how to configure the TFT_eSPI Library within the Arduino IDE for controlling TFT displays. I will show you several examples for different TFT displays.
The TFT_eSPI library simplifies the process of interfacing with TFT displays. It provides a straightforward API for drawing shapes, displaying text, and handling touch input.
The library is targeted at 32-bit processors and has been performance optimised for RP2040, STM32, ESP8266 and ESP32. It works with Arduino boards as well but it will be slower.
Furthermore, it supports a variety of TFT display controllers, including ILI9341, ST7735, ST7789, ST7796, and more. For a full list and more information see the Readme of the TFT_eSPI Library.
Installing the TFT_eSPI Library
To install the TFT_eSPI library open the Library Manager, search for “TFT_eSPI” and press “INSTALL”. After installation it should look like this:
Setting up TFT_eSPI library via User_Setup.h
Before you can use the TFT_eSPI Library you have configure it specifically to the TFT display you want to draw on. That includes the driver IC for the display, the interface pins, and properties of the display such as dimensions or order of RGB channels.
These configuration parameters are stored in a file named User_Setup.h
, which is part of the TFT_eSPI library folder. Typically, on Windows it will be located under a path similar to the following
C:\Users\stefa\OneDrive\Documents\Arduino\libraries\TFT_eSPI
The exact path depends on your user name (in my case “stefa
“) and your operating system and whether you are using OneDrive or not. You will have to search for it but it will be where all your Arduino libraries are stored.
If you open the User_Setup.h
file you will see many parameters that need to be set correctly to make a specific TFT display work:
You can edit this file but any change will be affect all your Arduino projects that use the TFT_eSPI library since the library and User_Setup.h
is shared across projects. Also installing a new version of the TFT_eSPI library will overwrite your changes to User_Setup.h
.
Instead, I suggest you create a file named tft_setup.h that is local to a project and will affect only that project. How that is done, is the topic of the following section.
Setting up TFT_eSPI library via tft_setup.h
Any change to User_Setup.h
will affects all projects. However, if the project contains a file with the name tft_setup.h the settings in User_Setup.h
will be ignored.
The tft_setup.h file essentially contains the same settings User_Setup.h
will only be valid for the specific project. That means you can have different projects with different displays, without having to change User_Setup.h
whenever you use a different display.
Project Structure
Here is an example how to create the required project structure. First create a new Arduino project and save it as “tft_test
“, for instance. That will create a folder tft_test
with a file tft_test.ino
in it:
In this folder, now create a file named “tft_setup.h
” – exactly with this name! Your project folder should then look like this:
tft_setup.h
In your Arduino IDE you now should see two tabs; tft_test.ino
and tft_setup.h
that you can click on to edit the files.
tft_test.ino
and tft_setup.h
tabsExample Settings
In the file tft_setup.h
you copy (e.g. from User_Setup.h
or from a tutorial) all the settings that are specific to your display. Below is the settings file for a 1.8″ ST7735 TFT Display, for instance:
// tft_setup.h #define ST7735_DRIVER #define ST7735_BLACKTAB #define TFT_WIDTH 128 #define TFT_HEIGHT 160 #define TFT_RGB_ORDER TFT_RGB // pins #define TFT_CS 5 #define TFT_RST 16 #define TFT_DC 17 #define TFT_MOSI 23 // SDA // HW MOSI #define TFT_SCLK 18 // SCL // HW SCLK #define TFT_MISO 19 // not used #define TFT_BL 22 // LED back-light #define TFT_BACKLIGHT_ON HIGH // fonts #define LOAD_GLCD #define LOAD_FONT2 #define LOAD_FONT4 #define LOAD_FONT6 #define LOAD_FONT7 #define LOAD_FONT8 #define LOAD_GFXFF #define SMOOTH_FONT // SPI #define SPI_FREQUENCY 27000000 #define SPI_READ_FREQUENCY 20000000 #define SPI_TOUCH_FREQUENCY 2500000
The most important setting is the display driver (ST7735_DRIVER
), the dimensions of the display (320×24) and the pins the display is connected to.
Sometimes there are driver variations that can be set via special flags (e.g. ST7735_BLACKTAB
). Similarly, the order of the RGB channels can vary between displays and you can specify this as well (TFT_RGB_ORDER TFT_RGB
).
The SPI frequency settings are usually not too different between displays but if you are seeing noise patterns or other distortion you can try to lower the SPI_FREQUENCY
. Higher frequencies will make the display faster, and you can experiment with that as well.
Below is an example of the distortions you may encounter if the SPI frequency is too high. The first text was outputted with a SPI_FREQUENCY
of 27000000 and the second one with a frequency of 40000000. You can clearly see the distortions in the second text.
You usually don’t have to change the list of fonts to load but if you are running out of memory you can remove the fonts that you don’t use.
You can find many existing settings for various combinations of microprocessors and display drivers in the UserSetups folder of the TFT_eSPI library. For an overview of all the settings have a look at the User_Setup.h file.
Find Hardware SPI pins
The speed with which the TFT screen can display depends largely on how fast the data can get moved from the microprocessor to the display. Most commonly the microprocessor and the display communicate via SPI (Serial Peripheral Interface), though there is a parallel interface as well.
Microprocessors such as the Arduino, ESP8266 or ESP32 support Hardware SPI, which is faster than Software SPI. See a speed comparison video here.
However, Hardware SPI requires you that you connect the TFT display to the correct pins. Depending on the microprocessor these pins differ. However, you can find them easily by selecting your board in the Arduino IDE and then running the code below.
void setup() { Serial.begin(115200); Serial.print("MOSI: "); Serial.println(SDA / MOSI); Serial.print("MISO: "); Serial.println(MISO); Serial.print("SCL / SCLK: "); Serial.println(SCK); Serial.print("CS / SS: "); Serial.println(SS); } void loop() { }
It prints out the pins you need for hardware SPI – specifically MOSI and SCLK. The remaining pins such as TFT_CS, TFT_BL, TFT_DC you can select freely and MISO is typically not used.
Logic Levels
Finally a warning about Logic Levels. TFT displays typically operate on 3.3V CMOS logic and you can connect the SPI lines directly to a microprocessor that also uses CMOS 3.3V logic such as the ESP32, for instance.
Arduino boards, on the other hand, operate with 5V TTL logic and you must not connect their GPIO pins directly to a TFT display that uses 3.3V CMOS logic. You will need a volage divider or better a logic level converter.
Some TFT displays have such a logic level converter built in, but if it is not directedly stated in the data sheet or product description, you can’t be sure. If the display is stated to run with 5V it may or may not have a level converter. If it runs on 3.3V, it most likely has not.
So, if your display is not working properly (blank screen, noise patterns, flickering, …) with an Arduino, you may need a logic level converter.
Wiring Example for 1.8″ TFT with ST7735 Driver
In this section, I will show you a wiring example. We are going to connect a 1.8″ TFT Display that has a ST7735S driver to an WEMOS Lolin32 lite. See the complete wiring in the picture below:
And here for your convenience the wiring again as a table:
Display | ESP32 |
---|---|
CS / SS | 5 |
RST | 16 |
DC | 17 |
SDA / MOSI | 23 |
SCL / SCLK | 18 |
BKL/BL | 22 |
GND | GND |
VCC | 3.3V |
The TFT display in this example is a 3.3V display without a logic level shifter. You therefore must connect VCC of the display to 3.3V and you cannot directly connect it to an Arduino Uno.
Code Example for 1.8″ TFT with ST7735 Driver
In this section we look at a little code example that uses TFT_eSPI library. It will be useful to test whether the setting in the tft_setup.h
file are correct.
Copy the following code into the file
. This code displays a green square, a red circle, a blue triangle and the text “Makerguides”.tft_test.ino
// tft_test.ino #include "tft_setup.h" #include"TFT_eSPI.h" TFT_eSPI tft = TFT_eSPI(); const int cw = tft.width()/2; const int ch = tft.height()/2; const int s = min(cw/3,ch/3); void setup(void) { tft.init(); tft.fillScreen(TFT_BLACK); tft.setRotation(1); tft.setTextFont(1); tft.setTextSize(2); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextDatum(CC_DATUM); tft.drawString("Makerguides", ch, cw+s); tft.fillCircle(ch, cw/2+s/2, s/2, TFT_RED); tft.fillRect(1.5*ch-s, cw/2, s, s, TFT_GREEN); tft.fillTriangle(ch/2, cw/2, ch/2+s, cw/2, ch/2, cw/2+s, TFT_BLUE); } void loop() { }
Note that tft_setup.h
is included at the top of the program. The code itself is easy to understand. We create a TFT_eSPI
object and constants for the center (cw
, ch
) and the size s
of the objects to draw.
In the setup
function we initialize the TFT screen, fill the screen with black and rotate it to portrait mode.
Next, we set the font, its size, color, and alignment, and write the text “Makerguides” to the screen. In the next three lines we draw the red circle, green square, and the blue triangle. The output on your TFT screen should look similar to this:
If not, then something is wrong with the settings in
or the with wiring of the TFT display.tft_test.ino
Wiring Example for 1.3″ TFT ST7789 Display
In this next example, I show you how to connect the common 1.3″ ST7789 TFT Display to an WEMOS Lolin32 lite (ESP32):
And here are the required connections again as a table. Note that this display module has no chip select (CS) and therefore no pin is needed for it.
Display | ESP32 |
---|---|
RST | 16 |
DC | 17 |
SDA / MOSI | 23 |
SCL / SCLK | 18 |
BKL/BL | 22 |
GND | GND |
VCC | 3.3V |
Make sure to connect VCC of the display to 3.3V! It is not compatible with 5V and you can’t use it directly with an Arduino UNO. Also you should use the hardware SPI pins. Depending on the microcontroller the hardware SPI pins will differ.
Code Example for 1.3″ TFT ST7789 Display
Here is the configuration and code for the 1.3″ ST7789 TFT Display. Copy the following configuration into the tft_setup.h
file.
// 1.3" TFT Display (GMT130 V.10), // no CS pin // 240x240, ST7789 // tft_setup.h #define ST7789_DRIVER #define TFT_WIDTH 240 #define TFT_HEIGHT 240 #define TFT_RGB_ORDER TFT_BGR #define TFT_CS -1 #define TFT_RST 16 #define TFT_DC 17 #define TFT_MOSI 23 // SDA // HW MOSI #define TFT_SCLK 18 // SCL // HW SCL #define TFT_MISO 19 // not used #define TFT_BL 22 // LED back-light #define TFT_BACKLIGHT_ON HIGH #define LOAD_GLCD #define LOAD_FONT2 #define LOAD_FONT4 #define LOAD_FONT6 #define LOAD_FONT7 #define LOAD_FONT8 #define LOAD_GFXFF #define SMOOTH_FONT #define SPI_FREQUENCY 27000000 #define SPI_READ_FREQUENCY 20000000 #define SPI_TOUCH_FREQUENCY 2500000
and the test code for the sketch goes into the tft_test.ino
file:
// tft_test.ino #include "tft_setup.h" #include"TFT_eSPI.h" TFT_eSPI tft = TFT_eSPI(); const int cw = tft.width()/2; const int ch = tft.height()/2; const int s = min(cw/4,ch/4); void setup(void) { tft.init(); tft.fillScreen(TFT_BLACK); tft.setRotation(1); tft.setTextFont(1); tft.setTextSize(2); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextDatum(CC_DATUM); tft.drawString("Makerguides", ch, cw+s); tft.fillCircle(ch, cw/2+s/2, s/2, TFT_RED); tft.fillRect(1.5*ch-s, cw/2, s, s, TFT_GREEN); tft.fillTriangle(ch/2, cw/2, ch/2+s, cw/2, ch/2, cw/2+s, TFT_BLUE); } void loop() { }
You should see the following output on your display:
Wiring Example for 2.8″ TFT ILI9341 Touch Display
In this final example, I show you how to connect a 2.8″ TFT ILI9341 Touch Display to an WEMOS Lolin32 lite (ESP32):
There are quite a few connections to make and the following table should help. Note that the SDI(MOSI)
and SCK
lines of the SPI interface are shared between the touch and the TFT display controller:
ESP32 | TFT | Touch |
---|---|---|
5 | CS | – |
4 | – | T_CS |
17 | RESET | – |
16 | DC | – |
23 | SDI(MOSI) | T_DIN |
18 | SCK | T_CLK |
19 | – | T_DO |
22 | LED | – |
You could connect pin 19 of the ESP32 to SDO(MISO)
as well but we don’t need it and there has been reports that in some cases this causes issues. I did not connect pin 19 to SDO(MISO)
and the display was working fine.
Code Example for 2.8″ TFT ILI9341 Touch Display
Here is the configuration and code for the 2.8″ TFT ILI9341 Touch Display. Copy the following configuration into the tft_setup.h
file.
// tft_setup.h // 2.8" TFT Touch Display // 240x 320, Driver: ILI9341 #define ILI9341_DRIVER //#define ILI9341_2_DRIVER #define TFT_WIDTH 240 #define TFT_HEIGHT 320 #define TFT_RGB_ORDER TFT_BGR // WEMOLS Lolin32 lite #define TFT_CS 5 #define TFT_RST 17 #define TFT_DC 16 #define TFT_MOSI 23 // SDA // HW MOSI #define TFT_SCLK 18 // SCL // HW SCLK #define TFT_MISO 19 // HW MISO #define TFT_BL 22 // LED back-light #define TFT_BACKLIGHT_ON HIGH #define TOUCH_CS 4 #define TOUCH_CLK TFT_SCLK #define TOUCH_DIN TFT_MOSI #define TOUCH_DO TFT_MISO #define LOAD_GLCD #define LOAD_FONT2 #define LOAD_FONT4 #define LOAD_FONT6 #define LOAD_FONT7 #define LOAD_FONT8 #define LOAD_GFXFF #define SMOOTH_FONT #define SPI_FREQUENCY 27000000 #define SPI_READ_FREQUENCY 20000000 #define SPI_TOUCH_FREQUENCY 2500000
And here some test code for the display that goes into into the tft_test.ino
file:
// tft_test.ino #include "tft_setup.h" #include "TFT_eSPI.h" TFT_eSPI tft = TFT_eSPI(); uint16_t cal[5] = { 0, 0, 0, 0, 0 }; void calibrate_touch() { if (!cal[1]) { tft.fillScreen(TFT_BLACK); tft.calibrateTouch(cal, TFT_YELLOW, TFT_BLACK, 20); Serial.printf("cal[5] = {%d, %d, %d, %d, %d};\n", cal[0], cal[1], cal[2], cal[3], cal[4]); } } void setup(void) { Serial.begin(115200); tft.init(); tft.setRotation(1); calibrate_touch(); tft.setTouch(cal); tft.fillScreen(TFT_BLACK); tft.setTextFont(1); tft.setTextSize(2); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextDatum(CC_DATUM); tft.drawString("Makerguides", TFT_HEIGHT / 2, TFT_WIDTH / 2); } void loop() { uint16_t x, y; if (tft.getTouch(&x, &y)) { Serial.printf("%d %d\n", x, y); tft.fillCircle(x, y, 2, TFT_YELLOW); } }
This code allows you to calibrate the touch screen and to detect touches on the display:
For more detailed information see the Interface TFT ILI9341 Touch Display with ESP32 tutorial.
Conclusions
In this tutorial you will learned how to configure the TFT_eSPI Library within the Arduino IDE for controlling TFT displays.
The TFT_eSPI Library is very versatile and supports many different TFT displays. However, finding the right setting for a new TFT display might not be easy.
Start by identifying the driver IC the display is using. Common drivers are the ST7735, ST7789, ST7796 and the ILI9341. Look for these names in product description, the data sheet and on the PCB of the display itself.
Next, find out the resolution (width, height) of the display in pixels, e.g. 128×160. Again, you should be able to find this information in product description, the data sheet or on the PCB of the display.
Then wire up the display with your microcontroller. If there is a backlight pin, make sure it is connected to 3.3V (or 5V, depending on the display). If you don’t know if the display is 5V compatible, don’t use an Arduino but use an ESP32 with 3.3V instead. Otherwise, you may destroy the display driver IC.
Finally, upload the test code an see what happens. There are a view common scenarios:
- Black display: Check backlight pin and set
#define TFT_BACKLIGHT_ON HIGH
- Colors are wrong: Try
#define TFT_RGB_ORDER TFT_RGB
orTFT_BGR
- Black & White are inverted:
#define TFT_INVERSION_ON or TFT_INVERSION_OFF
- Text for test code is not centered or cut off: Display dimensions are wrong.
SetTFT_HEIGHT
andTFT_WIDTH
correctly. - Noise patterns, distortions or flickering:
SPI_FREQUENCY
is too high - Missing pins: If there is no pin for reset (RDT), chip select (CC/CS), or backlight (BL) on the display then set the corresponding constants to -1, e.g.
#define TFT_RST -1
If you have any comments, feel free to leave them in the comment section.
Happy Tinkering ; )
Stefan is a professional software developer and researcher. He has worked in robotics, bioinformatics, image/audio processing and education at Siemens, IBM and Google. He specializes in AI and machine learning and has a keen interest in DIY projects involving Arduino and 3D printing.