Arduino library 路 Displays

TFT_eSPI: fast color TFT graphics on the ESP32

TFT_eSPI, by Bodmer, is the most used TFT library on the ESP32, the ESP8266 and the RP2040. It drives the common SPI panels (ILI9341, ST7789, ST7735, GC9A01, ILI9488 and ST7796) at the full speed of the chip鈥檚 SPI hardware, and adds things the Adafruit libraries do not: smooth anti-aliased fonts, wide and smooth lines and arcs, text alignment by datum, and sprites.

Built in on Mokxi: #include <TFT_eSPI.h> and it builds, with nothing to install. Free, and no account needed.

What TFT_eSPI does

A sprite (TFT_eSprite) is an off-screen image in RAM with all the same drawing calls. You draw a gauge or a moving object into the sprite, then push it to the screen in one go, which is what removes the flicker of erasing and redrawing directly on the panel.

The step that trips everyone up is configuration. On a real board, TFT_eSPI does not take the driver or pins in the constructor: they come from User_Setup.h (or a file selected in User_Setup_Select.h) inside the library鈥檚 own folder, and that file is overwritten whenever the library updates. Keep a copy of your setup outside it.

Library Manager nameTFT_eSPI
AuthorBodmer
Include#include <TFT_eSPI.h>
BoardsESP32-C3, ESP32-C6, Raspberry Pi Pico, Raspberry Pi Pico W, Seeed XIAO SAMD21, STM32, STM32 Nucleo-F411RE, STM32 Blue Pill, micro:bit V2, Arduino Uno R4, ESP32 DevKit, ESP32-S3-DevKitC-1, ESP8266 NodeMCU, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, Seeed XIAO ESP32-S3, Arduino Nano ESP32, Arduino Nano RP2040 Connect, Seeed XIAO RP2040, Waveshare RP2040-Zero, Arduino Uno R4 WiFi
In the simulatorRuns, with a gap the note below names.
Parts it drivesTFT display, 240x320, Touch TFT, 2.8 inch ILI9341 with XPT2046, IPS display, ST7789, TFT display, 1.8 inch ST7735, Round display, GC9A01, Touch TFT, 3.5 inch ILI9488 with XPT2046, Touch TFT, 4 inch ST7796S with XPT2046

Install it

It builds on ESP32-C3, ESP32-C6, Raspberry Pi Pico, Raspberry Pi Pico W, Seeed XIAO SAMD21, STM32, STM32 Nucleo-F411RE, STM32 Blue Pill, micro:bit V2, Arduino Uno R4, ESP32 DevKit, ESP32-S3-DevKitC-1, ESP8266 NodeMCU, Seeed XIAO ESP32-C3, ESP32-C3 SuperMini, Seeed XIAO ESP32-C6, ESP32-DevKitC V4, LOLIN32 Lite, Wemos D1 R32, Cheap Yellow Display, TTGO T-Display, Seeed XIAO ESP32-S3, Arduino Nano ESP32, Arduino Nano RP2040 Connect, Seeed XIAO RP2040, Waveshare RP2040-Zero, Arduino Uno R4 WiFi.

In Mokxi it is built in: #include <TFT_eSPI.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "TFT_eSPI" by Bodmer from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add TFT_eSPI to lib_deps in PlatformIO. Mokxi follows the calls of release 2.5.43, so a sketch written here builds there too.

What to know in the simulator: Driver and pins come from defines before the include, not User_Setup.h. The numbered and free fonts are Mokxi鈥檚 typeface at their sizes; smooth fonts load from arrays, not from SPIFFS. The panels do not answer on MISO, so readPixel() on the TFT gives black. Not on the AVR boards, as upstream.

ESP32-C3 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

TFT_eSPI tft = TFT_eSPI()

Creates the screen object with the driver, size and pins from the setup file.

tft.init()

Starts SPI and sends the panel its start-up commands. Call it once in setup() before anything else.

tft.setRotation(1)

Landscape or portrait, 0 to 3. Touch calibration and sprites follow the rotation set here.

tft.setTextColor(TFT_WHITE, TFT_BLACK)

Text color and background. Giving a background means each character paints its own cell, so a changing value overwrites the old one cleanly.

tft.setTextDatum(MC_DATUM)

Sets which point of the text drawString() positions: MC_DATUM is middle center, TL_DATUM top left (the default), BR_DATUM bottom right.

tft.setTextDatum(MC_DATUM);
tft.drawString("42", tft.width() / 2, tft.height() / 2, 4);

tft.drawString("Hello", x, y, 2)

Draws a string at x, y in numbered font 2. drawNumber() and drawFloat() do the same for values.

spr.createSprite(120, 60)

Allocates a 120 by 60 sprite in RAM. At 16 bits a pixel that is about 14 KB, so check the result on smaller chips.

spr.pushSprite(x, y)

Copies the finished sprite to the screen at x, y in one transfer. deleteSprite() frees its memory.

spr.fillSprite(TFT_BLACK);
spr.fillSmoothCircle(30, 30, 20, TFT_YELLOW, TFT_BLACK);
spr.pushSprite(100, 80);

tft.getTouch(&x, &y)

Reads the XPT2046 touch controller when TOUCH_CS is set, returning true and the screen position while the panel is pressed.

Example: Shapes and text on a TFT with TFT_eSPI

On the Raspberry Pi Pico. It runs in the browser exactly as printed.

sketch.ino 路 Raspberry Pi Pico
#include <TFT_eSPI.h>

// No User_Setup.h here: an ILI9341 with CS on 10, DC on 9 and RST on 8,
// and the Pico's SPI pins (GP18 SCK, GP19 MOSI).
TFT_eSPI tft = TFT_eSPI();

void setup() {
  Serial.begin(115200);
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.drawString("Hello, TFT_eSPI", 10, 10, 2);
  tft.fillCircle(80, 140, 40, TFT_RED);
  tft.drawRect(160, 100, 120, 80, TFT_GREEN);
  tft.setTextDatum(MC_DATUM);
  tft.drawNumber(42, 220, 140, 4);
  Serial.println("drawn");
}

void loop() {}

Wiring

  • Raspberry Pi Pico GP18 to TFT display, 240x320 SCK
  • Raspberry Pi Pico GP19 to TFT display, 240x320 MOSI
  • Raspberry Pi Pico GP10 to TFT display, 240x320 CS
  • Raspberry Pi Pico GP9 to TFT display, 240x320 DC
  • Raspberry Pi Pico GP8 to TFT display, 240x320 RST
  • Raspberry Pi Pico 3V3 to TFT display, 240x320 VCC
  • Raspberry Pi Pico 3V3 to TFT display, 240x320 LED
  • Raspberry Pi Pico GND to TFT display, 240x320 GND

Open it in the editor, wired and ready to run

Common errors and how to fix them

A white or black screen with no picture

The driver or pins in the setup file do not match the panel. On a real board, open User_Setup.h in the TFT_eSPI folder, enable the right *_DRIVER and set TFT_CS, TFT_DC, TFT_RST, TFT_MOSI and TFT_SCLK to your wiring.

Red and blue are swapped

The panel鈥檚 color order differs from the setup. Define TFT_RGB_ORDER as TFT_BGR (or TFT_RGB) in the setup; for images pushed with pushImage(), try tft.setSwapBytes(true).

A sprite never appears

createSprite() could not get the memory and returned nullptr. Make the sprite smaller, use fewer bits with setColorDepth(8) before creating it, or delete sprites you no longer need.

Settings disappeared after updating the library

An update replaces User_Setup.h. Keep your settings in a file of your own and select it from User_Setup_Select.h, or define the settings as build flags in PlatformIO.

Questions and answers

Does Mokxi read User_Setup.h?

No. Define the driver and pins with #define lines above #include <TFT_eSPI.h>, using the same names. With none given, each board gets the pins its usual setup uses, and boards like the Cheap Yellow Display get their own.

Try TFT_eSPI without installing anything

Open the example, change the sketch, and keep your version in a free account.