Adding a colour screen to an Arduino project used to require expensive, power-hungry modules. Today, compact Arduino TFT display modules based on the ST7789 and ILI9341 controllers deliver bright, crisp colour graphics at prices even students can afford. Whether you want to display sensor readings, build a mini game, show a clock face, or visualise data in real time, these two controllers cover the vast majority of small-screen TFT projects you will encounter. This guide walks you through everything — hardware wiring, library setup, drawing primitives, displaying text, rendering images, and complete project examples.
- ST7789 vs ILI9341: Which Controller to Choose?
- Hardware Wiring and SPI Connections
- Library Setup in Arduino IDE
- Drawing Graphics: Shapes, Text, and Images
- Adding Touch Input with the XPT2046
- Complete Project Examples
- Performance Tips for Faster Rendering
- Frequently Asked Questions
ST7789 vs ILI9341: Which Controller to Choose?
Both controllers drive TFT LCD panels over SPI, but they target slightly different use cases.
The ILI9341 is the older and more widely used controller. It typically drives 2.4-inch to 3.2-inch panels at 240×320 pixels (QVGA). The chip operates at 5 V logic natively (or with a level shifter at 3.3 V), making it easy to pair with a standard 5 V Arduino Uno. Its driver support in the Arduino ecosystem is excellent: Adafruit’s ILI9341 library is mature, well-documented, and handles everything from basic shapes to JPEG decoding.
The ST7789 is the newer controller and is found on most 1.3-inch (240×240) and 1.54-inch (240×240) round-corner modules as well as some 2-inch (240×320) variants. It is a 3.3 V device and should NOT be driven with 5 V logic directly — you will need either a level shifter or use it with a 3.3 V Arduino (Due, Zero, Nano 33 IoT, Nano RP2040 Connect). The ST7789 offers excellent colour depth and a slimmer module form factor. Adafruit’s ST7789 library is the standard choice.
Summary:
- Use ILI9341 for larger 2.4″–3.2″ panels with a 5 V Arduino Uno or Mega.
- Use ST7789 for compact 1.3″–2″ panels with 3.3 V boards or through a level shifter.
Hardware Wiring and SPI Connections
Both controllers use the SPI bus. On an Arduino Uno (ATmega328P), the hardware SPI pins are:
- SCK → Pin 13
- MOSI → Pin 11
- MISO → Pin 12 (only needed for touch controller, not the display itself)
- CS (Chip Select) → Any digital pin (commonly Pin 10)
- DC (Data/Command) → Any digital pin (commonly Pin 9)
- RST (Reset) → Any digital pin (commonly Pin 8), or connect to Arduino Reset pin
Wiring the ILI9341 Module to Arduino Uno
| ILI9341 Pin | Arduino Uno Pin |
|---|---|
| VCC | 3.3 V or 5 V (check module specs) |
| GND | GND |
| CS | 10 |
| RST | 8 |
| DC | 9 |
| SDI (MOSI) | 11 |
| SCK | 13 |
| LED (backlight) | 3.3 V or via resistor to 5 V |
Wiring the ST7789 (240×240) to Arduino Nano 33 IoT / Nano RP2040
Since the ST7789 is a 3.3 V device, it is naturally compatible with 3.3 V Arduino boards. Connect the same SPI pins — the Nano 33 IoT uses D13 (SCK), D11 (MOSI), D10 (CS), D9 (DC), D8 (RST).
If using with Arduino Uno (5 V logic): Add a logic level shifter (e.g., 74AHCT125 or TXS0108E) on all SPI data lines. Running 5 V signals into an ST7789 will damage it over time.
Library Setup in Arduino IDE
Both controllers are supported by the Adafruit GFX Library (the graphics engine) plus a controller-specific driver library. You need to install all of the following:
- Open Arduino IDE → Sketch → Include Library → Manage Libraries.
- Search for and install Adafruit GFX Library.
- For ILI9341: install Adafruit ILI9341.
- For ST7789: install Adafruit ST7735 and ST7789 Library.
Initialising the ILI9341
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
void setup() {
tft.begin();
tft.setRotation(1); // landscape
tft.fillScreen(ILI9341_BLACK);
}
Initialising the ST7789 (240×240)
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
void setup() {
tft.init(240, 240); // width, height
tft.setRotation(2);
tft.fillScreen(ST77XX_BLACK);
}
Drawing Graphics: Shapes, Text, and Images
The Adafruit GFX Library provides a consistent API across both controllers. Here are the most commonly used drawing functions:
Drawing Shapes
// Filled rectangle: x, y, width, height, colour
tft.fillRect(10, 10, 100, 50, ILI9341_BLUE);
// Circle: x centre, y centre, radius, colour
tft.drawCircle(120, 160, 40, ILI9341_RED);
tft.fillCircle(120, 160, 38, ILI9341_YELLOW);
// Line
tft.drawLine(0, 0, 239, 319, ILI9341_WHITE);
// Triangle: x0,y0, x1,y1, x2,y2, colour
tft.fillTriangle(120, 10, 20, 200, 220, 200, ILI9341_GREEN);
Displaying Text
tft.setCursor(10, 10); // x, y position
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2); // 1=6x8px, 2=12x16px, 3=18x24px
tft.println("Hello Zbotic!");
// Display a variable
float temp = 27.5;
tft.setCursor(10, 40);
tft.print("Temp: ");
tft.print(temp, 1);
tft.println(" C");
Displaying Bitmap Images
To show an image, convert it to a C array using image2cpp. Save the array in a header file (image.h) and draw with:
#include "image.h" // array: const uint16_t myImage[]
tft.drawRGBBitmap(0, 0, myImage, 240, 240);
Adding Touch Input with the XPT2046
Many ILI9341 display shields include a resistive touchscreen overlay driven by an XPT2046 or similar ADC. The touch controller shares the SPI bus but uses its own CS pin (commonly Pin 2 on shields).
Install the XPT2046_Touchscreen library by Paul Stoffregen. After calibrating the touch coordinates (which map to pixel positions via linear interpolation), you can detect taps and implement buttons, sliders, and menus.
A simple touch-detect loop:
if (ts.touched()) {
TS_Point p = ts.getPoint();
int px = map(p.x, 200, 3800, 0, 240);
int py = map(p.y, 200, 3800, 0, 320);
tft.fillCircle(px, py, 3, ILI9341_CYAN);
}
Complete Project Examples
Live Sensor Dashboard
Connect a DHT11 on D4, a BMP280 over I2C, and an ILI9341 display shield. Draw a black background once in setup(), then in loop() erase only the numeric value areas (with a black rectangle) before printing new readings. This avoids a full-screen flicker on every update.
Mini Oscilloscope
Sample an analog pin (A0) at high speed and draw a waveform on the ILI9341. Use drawPixel() for precision, plotting each sample as x = sample index, y = mapped ADC value. Redraw the waveform area with a black fill between frames.
Digital Clock with ST7789
Pair a DS3231 RTC module (I2C) with an ST7789 on an Arduino Nano 33 IoT. Display hours and minutes in a large custom font, date and temperature from the RTC’s onboard thermometer in smaller text. The Nano 33 IoT’s Wi-Fi lets you synchronise time via NTP at boot.
Retro Snake Game
Implement the classic Snake game on a 240×320 ILI9341 display. Use the hardware SPI for speed. Draw the snake segments as 8×8 pixel coloured squares. A 4-directional button pad can be wired to digital pins D2–D5.
Performance Tips for Faster Rendering
Always Use Hardware SPI
The Adafruit constructor that accepts only CS, DC, and RST automatically uses hardware SPI, which is 4–8× faster than software (bit-banged) SPI. Never pass MOSI and SCK pins to the constructor unless you intentionally want software SPI.
Raise the SPI Clock Speed
The ILI9341 supports SPI up to 40 MHz. The Adafruit library defaults to a conservative speed. After initialising, call:
tft.setSPISpeed(40000000);
Batch Your Drawing Calls
Every call to fillRect(), drawPixel(), etc. acquires and releases the SPI bus. Minimise the number of distinct drawing calls by combining operations. For example, instead of drawing 100 individual pixels, use writePixels() with a buffer.
Use DMA on Supported Boards
The Arduino Zero (SAMD21) and RP2040-based boards support DMA-driven SPI. The Adafruit_ZeroDMA library can feed the SPI peripheral from RAM without CPU intervention, freeing your sketch to compute the next frame while the current one is being sent.
Avoid Serial.print() in the Render Loop
USB serial output on the Uno is blocking and slow (115200 baud = ~11 KB/s). A single Serial.println() in the inner render loop can drop your frame rate by 50%. Move all debugging output outside the drawing code.
Frequently Asked Questions
Can I use an ST7789 display with a 5 V Arduino Uno?
Yes, but you must use a bidirectional logic level shifter (such as the TXS0108E) on all SPI lines (MOSI, SCK, CS, DC, RST). Applying 5 V directly to the ST7789 will damage the chip. Alternatively, power the Arduino from 3.3 V by using the 3.3 V output of an external 3.3 V regulator and running your whole circuit at that voltage.
Why is my display showing garbled colours or a white screen?
The most common causes are: incorrect library or controller type initialised in code, SPI wiring errors (MOSI and SCK swapped), insufficient power (the display backlight needs up to 80 mA), or a missing or incorrect RST pulse. Double-check your constructor matches the exact controller on your module.
What is the maximum frame rate I can achieve on an Arduino Uno with ILI9341?
A full 240×320 screen fill at 40 MHz SPI takes approximately 30–50 ms on an Uno, giving a theoretical maximum of 20–33 fps for full-screen refreshes. In practice, most sketch logic reduces this to 10–15 fps. Partial updates (only redrawing changed regions) are the key to smooth animations.
How do I display Chinese or custom fonts on a TFT?
Adafruit GFX supports custom fonts in the Adafruit_GFX format. Generate custom font files using the fontconvert tool included in the library. For CJK characters, third-party libraries like U8g2 (with SPI driver) support large Unicode glyph sets.
Is it possible to display JPEG or PNG images directly?
Yes. For JPEG decoding, use the JPEGDEC library by Larry Bank. For PNG, use PNGdec. Both libraries decode images line-by-line and draw them via a callback, keeping RAM usage low enough for the Uno’s 2 KB SRAM (for small images) or requiring a Mega/RP2040 for larger files.
Ready to add a colour display to your next Arduino project? Explore our full collection of Arduino boards and display modules at Zbotic — fast delivery across India.
Add comment