Go back

TFT ILI9341 Display Demo: Graphics & Bouncing Ball on Arduino

Introduction

Color TFT displays are a fantastic way to add rich visual feedback to your Arduino projects. In this tutorial, we’ll drive a 240x320 ILI9341-based TFT using the Adafruit ILI9341 and Adafruit GFX libraries. You’ll learn how to wire the display, install the required libraries, and write code that draws static UI elements and animates a bouncing ball. All of this runs right in your browser with the Velxio simulator—no hardware needed!

Circuit Walkthrough

Let’s start by examining the circuit. The schematic is straightforward: an Arduino Uno communicates with the ILI9341 display over SPI (Serial Peripheral Interface).

Circuit diagram of tft-display on the Velxio simulator canvas

Here’s the complete wiring list:

Arduino Uno PinTFT ILI9341 PinWire Color
13 (SCK)SCKOrange
11 (MOSI)MOSIOrange
10 (CS)CSBlue
9 (D/C)D/CGreen
8 (RST)RSTRed
7 (LED)LEDWhite
5VVCC(not shown, assumed)
GNDGND(not shown, assumed)

No external components are required—the display runs at 5V logic (most ILI9341 modules are 5V tolerant) and the SPI pins are directly connected.

Code Walkthrough

Now let’s dive into the code. We’ll use the Adafruit ILI9341 library along with the Adafruit GFX library for graphics primitives. These libraries must be installed via the Library Manager.

Library Manager modal showing the libraries used by tft-display

Open the Library Manager (Tools > Manage Libraries) and search for “Adafruit ILI9341” and “Adafruit GFX Library”. Install both. The SPI library is included automatically.

Here’s the full code:

// TFT ILI9341 Display Demo (240x320)
// Library: Adafruit ILI9341 + Adafruit GFX
// Connect: CS=10, DC/RS=9, RST=8, LED=7, MOSI=11(SPI), SCK=13(SPI)

#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>

#define TFT_CS   10
#define TFT_DC    9
#define TFT_RST   8
#define TFT_LED   7

Adafruit_ILI9341 tft(TFT_CS, TFT_DC, TFT_RST);

// Background color: blue (visible on dark simulator canvas)
#define BG_COLOR 0x001F

// Ball state
int ballX = 120, ballY = 200;
int ballDX = 3, ballDY = 2;
const int BALL_R = 10;

// Play-field boundaries
const int FX = 5, FY = 110, FW = 230, FH = 200;

void drawStaticUI() {
  tft.fillScreen(BG_COLOR);

  // Title
  tft.setTextSize(3);
  tft.setTextColor(tft.color565(255, 220, 0));
  tft.setCursor(20, 10);
  tft.print("VELXIO TFT");

  // Subtitle
  tft.setTextSize(2);
  tft.setTextColor(tft.color565(180, 180, 255));
  tft.setCursor(30, 50);
  tft.print("ILI9341 Demo");

  // Color palette bars
  tft.fillRect(10, 82, 70, 18, tft.color565(220, 50, 50));
  tft.fillRect(85, 82, 70, 18, tft.color565(50, 200, 50));
  tft.fillRect(160, 82, 70, 18, tft.color565(50, 100, 240));

  // Play-field border
  tft.drawRect(FX, FY, FW, FH, tft.color565(80, 80, 130));
}

void setup() {
  pinMode(TFT_LED, OUTPUT);
  digitalWrite(TFT_LED, HIGH);

  tft.begin();
  drawStaticUI();
}

void loop() {
  // Erase old ball
  tft.fillCircle(ballX, ballY, BALL_R, BG_COLOR);

  // Update position
  ballX += ballDX;
  ballY += ballDY;

  // Bounce off field borders
  if (ballX < FX + BALL_R + 1 || ballX > FX + FW - BALL_R - 1) ballDX = -ballDX;
  if (ballY < FY + BALL_R + 1 || ballY > FY + FH - BALL_R - 1) ballDY = -ballDY;

  // Draw ball
  tft.fillCircle(ballX, ballY, BALL_R, tft.color565(255, 140, 0));

  delay(30);
}

Key Points in the Code

Key Concepts for Students

  1. SPI Communication: The display uses SPI, a synchronous serial protocol. The Arduino is the master, the display is the slave. Only three wires (SCK, MOSI, CS) are needed for data; D/C and RST are additional control lines.
  2. Graphics Primitives: The Adafruit GFX library provides functions like fillScreen(), fillRect(), drawRect(), fillCircle(), setCursor(), print(), and setTextSize(). These make it easy to draw shapes and text.
  3. Double Buffering (Concept): We erase the old ball before drawing the new one. This prevents smearing. In more advanced projects, you might use a frame buffer.
  4. Collision Detection: The bouncing ball logic checks if the ball’s center is within BALL_R pixels of the border. If so, the direction is reversed.
  5. Color Depth: The ILI9341 supports 262K colors (18-bit), but the library uses 16-bit (65K colors) for speed. color565() packs RGB into 5-6-5 bits.

Common Pitfalls & Debugging Tips

Suggested Extensions

Once you have the basic demo running, try these enhancements:

Try It Yourself!

Ready to see it in action? Open the live example in Velxio and hit the Run button.

Velxio editor toolbar with compile and run controls

You can also explore the canvas toolbar to zoom, pan, and inspect the simulation.

Velxio canvas toolbar above the simulation viewport

If you want to build this from scratch, use the component picker to add an Arduino Uno and an ILI9341 display.

Velxio component picker modal browsing parts by category

Click the link below to open the example and start experimenting:

Open TFT ILI9341 Display Demo on Velxio

Happy coding!


Share this post on:
David Montero

Written by

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

Related posts


Previous Post
LCD 20x4 Display with Arduino: Hello World in Velxio
Next Post
Build a Simon Says Memory Game with Arduino on Velxio