In this guide, you’ll learn how to process and load an image to be displayed on a TFT 2.8 inch ILI9341 240×320 with the ESP32 board using LVGL (Light Versatile Graphics Library). The ESP32 will be programmed using Arduino IDE.
Are you using a CYD board? Read this guide: ESP32 CYD with LVGL: Display Image on the Screen
Project Overview
In this project, you’ll learn how to display images on the TFT screen using LVGL. We’ll create an example to display the image of a cat as shown in the picture below, but you can modify it to load any other image.
Prerequisites
Before proceeding, make sure you follow the next prerequisites. You must follow all steps, otherwise, your project will not work.
1) Parts Required
For this project, you need the following parts:
- TFT LCD Touchscreen Display – 2.8 inch ILI9341 240×320
- ESP32 board with enough pins to wire the display (for example an ESP32 DOIT V1 board)
2) Install ESP32 Boards in Arduino IDE
We’ll program the ESP32 using Arduino IDE. Make sure you have the ESP32 boards installed. Follow the next tutorial:
3) Get familiar with the ILI9341 TFT LCD Touchscreen Display
The display we’re using in this guide is the 2.8. inch TFT LCD that also comes with a touchscreen. The display communicates via SPI communication protocol and uses the ILI9341 driver. The touchscreen also uses the SPI communication protocol.
The TFT LCD touchscreen also comes with an SD card interface if you need to load files for your specific project. This display is also available with different screen sizes, but we’ll use the one with 240 x 320 pixels).
If this is your first time using this display, make sure to follow our getting started guide:
4) Wire the Display to the ESP32
Wire the TFT LCD and touchscreen pins to the ESP32 GPIOs according to the next table (you must use these exact pins, otherwise the project will not work).
TFT LCD Touchscreen | ESP32 |
T_IRQ | GPIO 36 |
T_OUT | GPIO 39 |
T_DIN | GPIO 32 |
T_CS | GPIO 33 |
T_CLK | GPIO 25 |
SDO(MISO) | GPIO 12 |
LED | GPIO 21 |
SCK | GPIO 14 |
SDI(MOSI) | GPIO 13 |
D/C | GPIO 2 |
RESET | EN/RESET |
CS | GPIO 15 |
GND | GND |
VCC | 5V (or 3.3V)* |
* In the VCC pin, you can either use 5V or 3.3V depending if your J1 connection is open or closed (by default it’s usually open as you can see in the figure below).
VCC = 5V | J1=OPEN
VCC = 3.3V | J1=CLOSE
5) Install TFT and LVGL Libraries
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics library that provides a wide range of easy-to-use graphical elements for your microcontroller projects that require a graphical user interface (GUI).
Follow the next tutorial to install and configure the required libraries to use LVGL with the ESP32 using Arduino IDE and the TFT LCD touchscreen.
Preparing the Image File – image.h
To load a custom image using LVGL, you need to create and configure a file called image.h that must be placed inside the sketch folder. We already prepared that file for you. If you want to load a custom image, you just need to replace the image uint8_t map and the image size.
You can use our sample image or follow the next steps to prepare a custom image:
1. Go to the LVGL Image Converter Website: lvgl.io/tools/imageconverter
2. Select the following options highlighted in the image below:
- Version: LVGL v9
- Select an image from your computer
- Color format: ARGB8888
- Then, click the Convert button
3. It will download a file with the name of your picture but with the .c extension. Open that file and copy the code between brackets { } with many hexadecimal characters.
4. Create a new file called image.h.
5. Copy the code in this repository and paste it into the new image.h file that you’ve just created.
6. Replace the content of the my_image_map variable with the content you’ve just copied in step 3. (Don’t change the name of the my_image_map variable, only copy and replace what is between brackets.
#ifdef __has_include
#if __has_include("lvgl.h")
#ifndef LV_LVGL_H_INCLUDE_SIMPLE
#define LV_LVGL_H_INCLUDE_SIMPLE
#endif
#endif
#endif
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#define LV_BIG_ENDIAN_SYSTEM
#ifndef LV_ATTRIBUTE_MEM_ALIGN
#define LV_ATTRIBUTE_MEM_ALIGN
#endif
#ifndef LV_ATTRIBUTE_IMG_MY_IMAGE
#define LV_ATTRIBUTE_IMG_MY_IMAGE
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_MY_IMAGE uint8_t my_image_map[] = {REPLACE_WITH_YOUR__IMAGE_ATTRIBUTE};
const lv_image_dsc_t my_image = {
.header = {
.magic = LV_IMAGE_HEADER_MAGIC,
.cf = LV_COLOR_FORMAT_ARGB8888,
.flags = 0,
.w = 128,
.h = 128,
//.stride = 120,
.reserved_2 = 0
},
.data_size = sizeof(my_image_map),
.data = my_image_map,
.reserved = NULL
};
7. Scroll down on that file and change the following lines with your image width .w and height .h:
const lv_image_dsc_t my_image = {
.header = {
.magic = LV_IMAGE_HEADER_MAGIC,
.cf = LV_COLOR_FORMAT_ARGB8888,
.flags = 0,
.w = 128,
.h = 128,
//.stride = 120,
.reserved_2 = 0
},
.data_size = sizeof(my_image_map),
.data = my_image_map,
.reserved = NULL
};
8. Finally, save your image.h file.
Important: the image.h file should be placed next to the .ino file in the sketch folder of your project.
Your Arduino IDE should have two tabs:
ESP32 with TFT LCD: Load and Display Image – Arduino Code
The following code will display an image on the screen. You must have prepared the image.h previously with the image of your choice. Alternatively, you can use our default image.h file. This file should be placed in the sketch folder next to the .ino file.
/* Rui Santos & Sara Santos - Random Nerd Tutorials - https://RandomNerdTutorials.com/esp32-cyd-lvgl-display-image/
THIS EXAMPLE WAS TESTED WITH THE FOLLOWING HARDWARE:
1) ESP32-2432S028R 2.8 inch 240×320 also known as the Cheap Yellow Display (CYD): https://makeradvisor.com/tools/cyd-cheap-yellow-display-esp32-2432s028r/
SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/cyd-lvgl/
2) REGULAR ESP32 Dev Board + 2.8 inch 240x320 TFT Display: https://makeradvisor.com/tools/2-8-inch-ili9341-tft-240x320/ and https://makeradvisor.com/tools/esp32-dev-board-wi-fi-bluetooth/
SET UP INSTRUCTIONS: https://RandomNerdTutorials.com/esp32-tft-lvgl/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
/* Install the "lvgl" library version 9.2 by kisvegabor to interface with the TFT Display - https://lvgl.io/
*** IMPORTANT: lv_conf.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***
*** YOU MUST USE THE lv_conf.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***
FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */
#include <lvgl.h>
/* Install the "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI
*** IMPORTANT: User_Setup.h available on the internet will probably NOT work with the examples available at Random Nerd Tutorials ***
*** YOU MUST USE THE User_Setup.h FILE PROVIDED IN THE LINK BELOW IN ORDER TO USE THE EXAMPLES FROM RANDOM NERD TUTORIALS ***
FULL INSTRUCTIONS AVAILABLE ON HOW CONFIGURE THE LIBRARY: https://RandomNerdTutorials.com/cyd-lvgl/ or https://RandomNerdTutorials.com/esp32-tft-lvgl/ */
#include <TFT_eSPI.h>
#include <image.h>
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
uint32_t draw_buf[DRAW_BUF_SIZE / 4];
// If logging is enabled, it will inform the user about what is happening in the library
void log_print(lv_log_level_t level, const char * buf) {
LV_UNUSED(level);
Serial.println(buf);
Serial.flush();
}
void draw_image(void) {
LV_IMAGE_DECLARE(my_image);
lv_obj_t * img1 = lv_image_create(lv_screen_active());
lv_image_set_src(img1, &my_image);
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
}
void setup() {
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200);
Serial.println(LVGL_Arduino);
// Start LVGL
lv_init();
// Register print function for debugging
lv_log_register_print_cb(log_print);
// Create a display object
lv_display_t * disp;
// Initialize the TFT display using the TFT_eSPI library
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
// Function to draw the image
draw_image();
}
void loop() {
lv_task_handler(); // let the GUI do its work
lv_tick_inc(5); // tell LVGL how much time has passed
delay(5); // let this time pass
}
How Does the Code Work?
Let’s take a look at how to display an image on the TFT screen. Alternatively, you can skip to the Demonstration section.
Including Libraries
You need to include the lvgl.h and the TFT_eSPI.h libraries to communicate and display text on the screen.
#include <lvgl.h>
#include <TFT_eSPI.h>
Include the image.h file that contains all the information to draw the image.
#include <image.h>
setup()
In the setup(), include the following lines for debugging. These will print the version of LVGL that you’re using. You must be using version 9.
String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200);
Serial.println(LVGL_Arduino);
Initialize the LVGL Library
Initialize the LVGL Library by calling the lv_init() function in the setup().
// Start LVGL
lv_init();
Register Debugging Function
Register your log_print() function declared previously as a function associated with debugging LVGL.
// Register print function for debugging
lv_log_register_print_cb(log_print);
Create a Display Object
To write to the display, you must create a display object first. You need to do this in all your LVGL sketches. The following lines will create an LVGL display object called disp with the screen width, screen height, and drawing buffer defined earlier.
// Create a display object
lv_display_t * disp;
// Initialize the TFT display using the TFT_eSPI library
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);
Drawing the image
The LVGL library works asynchronously. You must call the function draw_image() to draw on the display in the setup(). Then, everything works with events and callbacks. The code will always be listening for events in the background.
draw_image();
draw_image()
Create a function called draw_image() that will be called on the setup().
void draw_image(void) {
LV_IMAGE_DECLARE(my_image);
lv_obj_t * img1 = lv_image_create(lv_screen_active());
lv_image_set_src(img1, &my_image);
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
}
Start by declaring your image using the following line (my_image is declared on the image.h file).
LV_IMAGE_DECLARE(my_image);
Create an image LVGL object on the current screen called img1 using the lv_image_create() function.
lv_obj_t * img1 = lv_image_create(lv_screen_active());
Set the image source using the lv_image_set_src() function and pass as arguments the LVGL image object and image source.
lv_image_set_src(img1, &my_image);
Align the image at the center of the screen.
lv_obj_align(img1, LV_ALIGN_CENTER, 0, 0);
loop()
In the loop(), you can add any other tasks that you need your ESP32 to do like in any regular Arduino sketch. In our case, we won’t add any tasks to the loop().
void loop() {
lv_task_handler();
lv_tick_inc(5);
delay(5);
}
Demonstration
Your image.h file should be next to your .ino file. The image.h file will automatically be uploaded to the board when you upload the code.
After having both files prepared, upload the code to your board. Go to Tools > Board and select ESP32 > ESP32 Dev Module. Then, select the right COM port in Tools > Port. Finally, click the upload button.
After a few seconds, the screen will display the image as shown in the picture below.
Wrapping Up
In this tutorial, you learned how to display images on the TFT LCD Touchscreen with the ESP32 using the LVGL library.
We hope you found this tutorial useful. We’re preparing more guides about this board, so stay tuned. If you would like to learn more about creating graphical user interfaces using the LVGL library with the ESP32, check out our latest eBook:
Other guides you might like reading:
- LVGL with ESP32 TFT LCD Touchscreen Display – 2.8 inch ILI9341 240×320 (Arduino IDE)
- ESP32: TFT Touchscreen On/Off Button – 2.8 inch ILI9341 240×320 (Arduino IDE)
- ESP32: TFT LCD Touchscreen Display – 2.8 inch ILI9341 240×320 (Arduino IDE)
To learn more about the ESP32, make sure to take a look at our resources: