ESP32 ILI9341: Drawing shapes

Introduction

In this tutorial we will learn how to draw shapes on a ILI9341 display, using an ESP32, the Arduino core and the Arduino_GFX library.

For an introductory tutorial on how to get started controlling a ILI9341 with an ESP32, please check here. The tutorial contains the wiring diagram between the ESP32 and the display, and how to write a simple “Hello World” message using the library.

Drawing shapes on a ILI9341 display

We will start our code by including the Arduino_GFX_Library.h library, which allows us to interact with the display without having to worry about the lower level details.

#include <Arduino_GFX_Library.h>

Then we will define some constants to hold the number of the pins of the ESP32 that are connected to the ILI9341 display. Note that the pin numberings I’ll be using match the wiring shown on the getting started tutorial. If you are using a different connection scheme, you should adapt these constants.

#define TFT_SCK    18
#define TFT_MOSI   23
#define TFT_MISO   19
#define TFT_CS     22
#define TFT_DC     21
#define TFT_RESET  17

Moving on to the Arduino setup, we will start by initializing a data bus for the device we are using (ESP32, via SPI interface). Recall from the introductory tutorial on how to interact with the display that this is an abstraction that allows the library to support different devices.

Arduino_ESP32SPI bus = Arduino_ESP32SPI(TFT_DC, TFT_CS, TFT_SCK, TFT_MOSI, TFT_MISO);

Now that we have our data bus, we will create an object of class Arduino_ILI9341, which allows to interact with the display.

As parameters, the constructor of this class receives the address of the data bus object and the number of the ESP32 GPIO connected to the reset pin of the display.

Arduino_ILI9341 display = Arduino_ILI9341(&bus, TFT_RESET);

Then we will initialize the display by calling the begin method on the Arduino_ILI9341 object we have just created. We will also set the background to white before we start drawing shapes.

display.begin();

display.fillScreen(WHITE);

Now that we have prepared our display, we can start drawing shapes. But before we start, it is important to mention that all the shapes we are going to draw support two variants: filled and not filled. Additionally, we are going to use the color constants defined here.

We will start with triangles. To draw a triangle on a ILI9341 display, we only need to call the drawTriangle method on the Arduino_ILI9341 object.

This method receives the following parameters:

  • x and y coordinates of vertex 1
  • x and y coordinates of vertex 2
  • x and y coordinates of vertex 3
  • color of the triangle lines
display.drawTriangle(10, 10, 10, 40, 40, 40, BLUE);

To draw a filled triangle we can call the fillTriangle method, which receives exactly the same parameters (the color now corresponds to the fill color instead of just the lines).

display.fillTriangle(60, 10, 90, 10, 75, 40, BLUE);

Moving on to a different shape, we will now draw circles. Like before, we will start by the non-filled variant. So, to draw a circle, we can call the drawCircle method, with the following parameters:

  • x position of the center of the circle
  • y position of the center of the circle
  • Radius of the circle
  • Color of the circle
display.drawCircle(25, 70, 20, RED);

To draw a filled circle, we simply need to call the fillCircle method instead, which receives the same parameters.

display.fillCircle(85, 70, 20, RED);

To draw a rectangle, we can call the drawRect method with the following parameters:

  • x position of the top left corner of the rectangle
  • y position of the top left corner of the rectangle
  • Width of the rectangle
  • Height of the rectangle
  • Color of the rectangle
 display.drawRect(10, 100, 40, 40, GREEN);

Naturally, a rectangle with the same width and height corresponds to a square, which means the previous function call will draw a square.

To draw the filled version we should call the fillRect method.

 display.fillRect(60, 100, 70, 40, GREEN);

As a variant of the rectangle, the library also allows to draw rounded rectangles. This is done with a call to the drawRoundRect, which has the following parameters:

  • x position of the top left corner of the rectangle
  • y position of the top left corner of the rectangle
  • Width of the rectangle
  • Height of the rectangle
  • Radius of the corner rounding
  • Color of the rectangle
display.drawRoundRect(10, 150, 40, 40, 1, YELLOW);

The filled version corresponds to calling the fillRoundRect method.

display.fillRoundRect(60, 150, 70, 40, 1, YELLOW);

To draw an ellipse, we can call the drawEllipse method with the following parameters:

  • x position of the center
  • y position of the center
  • Radius of the x coordinate
  • Radius of the y coordinate
  • Color of the ellipse
display.drawEllipse(25, 230, 10, 20, BLACK);

Once again, the filled version is drawn with a call to the fillEllipse method.

display.fillEllipse(85, 230, 20, 10, BLACK);

To finalize, we will draw an arc with a call to the drawArc method, which receives the following parameters:

  • x coordinate of the center of the arc
  • y coordinate of the center of the arc
  • Outer radius of the arc
  • Inner radius of the arc
  • Degree of the arc start
  • Degree of the arc end
  • Color
display.drawArc(25, 290, 20, 10, 0, 270, DARKGREY);

The filled version is drawn with a call to the fillArc method.

display.fillArc(85, 290, 30, 10, 180, 0, DARKGREY);

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.drawTriangle(10, 10, 10, 40, 40, 40, BLUE);
  display.fillTriangle(60, 10, 90, 10, 75, 40, BLUE);

  display.drawCircle(25, 70, 20, RED);
  display.fillCircle(85, 70, 20, RED);

  display.drawRect(10, 100, 40, 40, GREEN);
  display.fillRect(60, 100, 70, 40, GREEN);

  display.drawRoundRect(10, 150, 40, 40, 1, YELLOW);
  display.fillRoundRect(60, 150, 70, 40, 1, YELLOW);

  display.drawEllipse(25, 230, 10, 20, BLACK);
  display.fillEllipse(85, 230, 20, 10, BLACK);

  display.drawArc(25, 290, 20, 10, 0, 270, DARKGREY);
  display.fillArc(85, 290, 30, 10, 180, 0, DARKGREY);
 
}
 
void loop() {}

Testing the code

To test the code, simply compile it and upload it to your ESP32, after all the wirings to the display are done. You should get an output similar to figure 1, which shows the different shapes drawn.

Shapes drawn on the ILI9341 display, controlled by the ESP32.
Figure 1 – Shapes drawn on the ILI9341 display, controlled by the ESP32.

Related ESP32 posts

Leave a Reply