A 3.5 inch ILI9488 touch TFT on an ESP32
Intermediate
Or see every lesson.
- 465parts on the bench
- 43boards running now
- 1.00xreal time, on every board
The ILI9488 is the chip on the red 3.5 inch SPI screens: 320 by 480 pixels, with an XPT2046 resistive touch panel on the same board. The 4 inch boards use an ST7796S at the same resolution and the same fourteen pins. Both are too big for an Uno to draw quickly, and both are a good match for an ESP32 and the TFT_eSPI library.
The circuit above is an ESP32 DevKit with the 3.5 inch board: a row of color swatches along the top, and a black canvas below. Press Run, tap a color, then draw on the screen with your mouse or finger.
What you need
- An ESP32 DevKit (the 30 or 38 pin board)
- A 3.5 inch ILI9488 SPI TFT with touch (the red 14-pin board), or a 4 inch ST7796S one
- Jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| VCC and LED | 3V3 | LED is the backlight |
| GND | GND | |
| CS | GPIO 15 | TFT_CS |
| DC | GPIO 2 | TFT_DC, the command or data line |
| RST | GPIO 4 | TFT_RST |
| MOSI (SDI) | GPIO 23 | TFT_MOSI |
| SCK | GPIO 18 | TFT_SCLK |
| MISO (SDO) | not connected | The ILI9488 never lets go of it |
| T_CLK and T_DIN | GPIO 18 and 23 | The touch shares the clock and data out |
| T_CS | GPIO 21 | TOUCH_CS, the touch chip select |
| T_DO | GPIO 19 | TFT_MISO: the touch readings come back here |
Setting up TFT_eSPI
TFT_eSPI does not take the screen and its pins in the code. It reads them from a file in the library folder, User_Setup.h, and you edit that file once: uncomment #define ILI9488_DRIVER and set TFT_MISO, TFT_MOSI, TFT_SCLK, TFT_CS, TFT_DC, TFT_RST and TOUCH_CS.
In Mokxi the same lines go at the top of the sketch, above #include <TFT_eSPI.h>, with the same names. That keeps the whole setup in one place you can see. Copy them into User_Setup.h when you build it for real.
For the 4 inch board, change ILI9488_DRIVER to ST7796_DRIVER. Nothing else in the sketch changes.
#define ILI9488_DRIVER
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST 4
#define TOUCH_CS 21
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
Serial.begin(115200);
tft.init();
tft.setRotation(0); // portrait, 320x480
tft.fillScreen(TFT_BLACK);
}Why the ILI9488 needs 18-bit color
Most color TFTs take a pixel as two bytes, 16-bit "565" color: 5 bits of red, 6 of green and 5 of blue. The ILI9488 does not over SPI. Its datasheet lists only 3-bit and 18-bit pixels for the serial bus, so every pixel goes as three bytes, one each for red, green and blue.
TFT_eSPI knows this. With ILI9488_DRIVER it sets the chip to 18 bits and turns each 565 color into three bytes as it sends it, so your code still uses TFT_RED and color565(). With an ILI9341 driver instead, the chip reads two pixels out of every three it is sent, in the wrong colors.
Three bytes a pixel is also why the ILI9488 is slower. Here, with TFT_eSPI on the ESP32, fillScreen() takes 261 ms on the ILI9488 and 192 ms on the ST7796S, which takes ordinary 16-bit color. Draw what changed, not the whole screen.
Reading the touch panel
The XPT2046 is a second chip on the board, with its own chip select (T_CS). It shares the clock and data lines with the screen, and answers on T_DO. tft.getTouchRawZ() says how hard the panel is pressed, and tft.getTouchRaw(&x, &y) gives two raw numbers from about 200 at one edge of the glass to about 3900 at the other.
The sketch checks the pressure first, then turns the raw numbers into pixels with map(). In rotation 0 the X numbers run the other way from the picture, so its X map goes from 3890 down to 205. On a real panel, tft.calibrateTouch() finds the edges for you.
void loop() {
if (tft.getTouchRawZ() < 300) return; // not pressed
uint16_t rx, ry;
tft.getTouchRaw(&rx, &ry);
int x = constrain(map(rx, 3890, 205, 0, 319), 0, 319);
int y = constrain(map(ry, 205, 3890, 0, 479), 0, 479);
tft.fillCircle(x, y, 4, TFT_YELLOW);
}Turning the screen on its side
tft.setRotation(1) turns the picture a quarter turn, to 480 wide by 320 tall, and tft.width() and tft.height() swap to match. Rotations 0 and 2 are portrait, 1 and 3 landscape. The chip does the turning: TFT_eSPI writes one byte, called MADCTL, that tells it which way to walk its memory.
The touch panel does not turn with it, because the film is glued to the glass, not to the picture. A sketch that rotates the screen has to swap and flip its touch numbers the same way, or let tft.calibrateTouch() work it out for that rotation.
ILI9488 or ST7796S?
The two boards look alike and use the same pins, so the choice comes down to size and speed. The 4 inch ST7796S has a bigger picture and takes 16-bit color, so it fills about a quarter faster on the same wires. The 3.5 inch ILI9488 is smaller, cheaper and easier to find.
Code moves between them with one line: the driver define. The touch chip, the wiring and every drawing call stay the same. Some 4 inch boards are IPS panels that show a negative picture until you add #define TFT_INVERSION_ON; the plain TN board here does not need it.
Common mistakes
The display MISO wired with T_DO. The ILI9488 keeps driving its SDO pin even when it is not selected, so the touch readings come back as garbage. Leave the display MISO unconnected.
The wrong driver define. ILI9341_DRIVER or ST7796_DRIVER on an ILI9488 gives the wrong colors; ILI9488_DRIVER on an ST7796S does too.
Running it from an Uno. It works with the ILI9488 library, but 320 by 480 pixels at three bytes each is a lot of SPI for a 16 MHz board, and TFT_eSPI does not run on the AVR boards at all.
Drawing the whole screen every loop. Even on an ESP32, a full fill is a quarter of a second.
Questions
Does TFT_eSPI support the ILI9488?
Yes. Put #define ILI9488_DRIVER in User_Setup.h (or above the include, in Mokxi). It sends 18-bit color, which is the only full-color format the ILI9488 takes over SPI.
What is the difference between the ILI9488 and the ST7796S?
Both are 320x480 SPI TFT controllers on 14-pin touch boards. The ST7796S (usually 4 inch) takes 16-bit color like the ILI9341, so it fills faster; the ILI9488 (usually 3.5 inch) takes 18-bit color only.
Why are the colors wrong on my ILI9488?
Most often the sketch uses an ILI9341 driver, which sends 16-bit color. Use ILI9488_DRIVER in TFT_eSPI, or the ILI9488 library.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.