Introduction
In this tutorial we are going to learn how to write text to a ILI9341 display using the ESP32 and the Arduino core.
Note that the ILI9341 is actually the LCD driver (you can check the datasheet here) but, for simplicity, we will refer to the display using this name. In my case, I’m using a 2.4″ TFT display, with 240×320 pixels, bought at eBay.
There are a lot of Arduino libraries available that allow us to interact with these displays without having to worry about the lower level details. For this tutorial we are going to use the Arduino_GFX.
As shown in figure 1, you can install the library from the Arduino IDE Library Manager.

Wiring the ESP32 to the ILI9341
Before we can start interacting with the display, we need to make sure it is properly connected to our ESP32. Figure 2 shows the connection diagram between the ESP32 and the ILI9341.
As can be seen, we are powering the display with a 3.3V supply. Note that, for this introductory tutorial, we also wired the display back LED to VCC, meaning that we won’t be controlling its state (it will always be on). Nonetheless, we could have assigned a GPIO of the ESP32 to control it.
Also take in consideration that both devices should share a common ground, like illustrated on the diagram.
We will interact with the display using the SPI interface. From the ESP32 side, we will use its VSPI interface, one of the two general purpose SPI controllers available on the device [1]. On this interface, the pins 18, 19 and 23 correspond to SCK, MISO and MOSI, respectively.
To connect to the chip select (CS) pin of the display, we will use GPIO22 of the ESP32. The reset pin will be connected to GPIO17.
To finalize, the Data/Command (D/C) pin of the display will be connected to GPIO21 of the ESP32. When the D/C signal is low, data received by the display is interpreted as commands. When the D/C signal is high, the received data is interpreted as data (ex: arguments of commands or pixel data) [2]. Note however that we don’t need to worry about these details when using the Arduino_GFX library.
It’s also important to mention that we can use other pins of the ESP32 instead of the ones I’ve used, since the number of the pins are defined when initializing the library.
The code
We will start our code by including the Arduino_GFX_Library.h library we have just installed.
#include <Arduino_GFX_Library.h>
After that, we will define a couple of constants to hold the numbers of the pins of the ESP32 connected to the display. Make sure to set the numbers of the pins accordingly to how you wired the ESP32 to the display (check figure 2 for the configuration I’ve used).
#define TFT_SCK 18
#define TFT_MOSI 23
#define TFT_MISO 19
#define TFT_CS 22
#define TFT_DC 21
#define TFT_RESET 17
Then we will move on to the Arduino setup function. There, we will start by taking care of initializing a data bus accordingly to the device we are using. In our case, since we are using the ESP32, we need to create a bus of class Arduino_ESP32SPI.
The constructor of this class receives the following parameters:
- Number of the ESP32 pin connect to the display DC pin
- Number of the ESP32 pin connect to the display CS pin
- Number of the ESP32 pin connect to the display SCK pin
- Number of the ESP32 pin connect to the display MOSI pin
- Number of the ESP32 pin connect to the display MISO pin
Naturally, we are going to pass the pin constants we defined before.
Arduino_ESP32SPI bus = Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Note that the concept of data bus is an abstraction that allows to use the library to control different devices with different SPI interface characteristics. The Arduino_ESP32SPI classe we have just created inherits from the Arduino_DataBus class. You can check the other implementations available here.
Next we are going to create an object of class Arduino_ILI9341. This class inherits from the Arduino_TFT class and allows us to interact with the display.
As input, the constructor receives the address of our data bus object and the number of the ESP32 pin connected to the reset pin of the display (remember that we have it on a constant).
Arduino_ILI9341 display = Arduino_ILI9341(&bus, TFT_RESET);
After this we will initialize our display with a call to the begin method on our Arduino_ILI9341 object.
display.begin();
Then we are going to set the background to white, so we can start writing some content to the display. To do so, we call the fillScreen method, passing as input the color we want to use, as a uint16_t. There are a couple of constants already defined here for some colors, which includes white.
display.fillScreen(WHITE);
Now that we have defined the color of the background, we will set the position of the cursor, which determines where the text will be drawn. To do so we can call the setCursor method, passing as input the x and y coordinates (in pixels, starting from the top left of the display) where to put the cursor. We are going to set the cursor to x = 20 and y = 20.
display.setCursor(20, 20);
After this we are going to set the text size by calling the setTextSize method. As input, we pass the size as a uint8_t. The value 1 (default) corresponds to 6×8 pixels, 2 to 12×16, 3 to 18×24, and so on. We are going to set the text size to 2.
display.setTextSize(2);
Before writing our message, we are also going to set the text color with a call to the setTextColor method. Like before, the color is specified as a uint16_t and we are going to use one of the constants defined in the library. In this case, we are going to use a blue color for the text.
display.setTextColor(BLUE);
Finally we are going to write some text to our display by calling the print method, passing as input the message we want to print. For our test, we are going to pass a very simple “Hello world”.
display.print("Hello world");
The complete code can be seen below.
#include <Arduino_GFX_Library.h>
#define TFT_SCK 18
#define TFT_MOSI 23
#define TFT_MISO 19
#define TFT_CS 22
#define TFT_DC 21
#define TFT_RESET 17
void setup(void)
{
Arduino_ESP32SPI bus = Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);
Arduino_ILI9341 display = Arduino_ILI9341(&bus, TFT_RESET);
display.begin();
display.fillScreen(WHITE);
display.setCursor(20, 20);
display.setTextSize(2);
display.setTextColor(BLUE);
display.print("Hello world");
}
void loop() {}
Testing the code
To test the previous code, simply compile it and upload it to your ESP32, after wiring it to the display accordingly to the diagram shown before in figure 2.
You should obtain a result similar to figure 3. As can be seen, we get the “Hello World” message we defined in our code.
Suggested ESP32 readings
References
[2] http://web.mit.edu/6.115/www/document/TFT_User_Manual.pdf
HELP NEEDED !
Using Arduino IDE 1.18.12, GFX library 1.1.2, ESP32 dev board
When verifying example sketch, I get this error:
error: ‘bus’ was not declared in this scope
exit status 1
‘Arduino_ESP32SPI’ does not name a type; did you mean ‘Arduino_SWSPI’?
How do I fix this?
Thanks
Please disregard all of the above, the wrong board was selected ( mega vs ESP32)
However, when verifying example sketch for ESP32, I get the following errors:
Arduino: 1.8.12 (Windows 10), Board: “ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None”
C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:5:0: warning: “TFT_MISO” redefined
#define TFT_MISO 19
^
In file included from C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:1:0:
C:\Users\ButchHam\Documents\Arduino Butch code\libraries\GFX_Library_for_Arduino\src/Arduino_GFX_Library.h:98:0: note: this is the location of the previous definition
#define TFT_MISO -1
^
C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:6:0: warning: “TFT_CS” redefined
#define TFT_CS 22
^
In file included from C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:1:0:
C:\Users\ButchHam\Documents\Arduino Butch code\libraries\GFX_Library_for_Arduino\src/Arduino_GFX_Library.h:99:0: note: this is the location of the previous definition
#define TFT_CS 5
^
C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:7:0: warning: “TFT_DC” redefined
#define TFT_DC 21
^
In file included from C:\Users\ButchHam\AppData\Local\Temp\arduino_modified_sketch_723951\sketch_apr17a.ino:1:0:
C:\Users\ButchHam\Documents\Arduino Butch code\libraries\GFX_Library_for_Arduino\src/Arduino_GFX_Library.h:100:0: note: this is the location of the previous definition
#define TFT_DC 27
^
C:\Users\ButchHam\Documents\Arduino Butch code\libraries\GFX_Library_for_Arduino\src\Arduino_DataBus.cpp: In member function ‘void Arduino_DataBus::batchOperation(uint8_t*, uint8_t)’:
C:\Users\ButchHam\Documents\Arduino Butch code\libraries\GFX_Library_for_Arduino\src\Arduino_DataBus.cpp:76:63: error: operation on ‘i’ may be undefined [-Werror=sequence-point]
writeCommand16(((uint16_t)batch[++i] < Preferences.
help still needed 🙁