LVGL with ESP32 Cheap Yellow Display Board (ESP32-2432S028R)

In this guide, you’ll get started with the LVGL (Light and Versatile Graphics Library) with the ESP32 CYD (Cheap Yellow Display ESP32-2432S028R). The LVGL is a popular free and open-source embedded graphics library to create awesome UIs for many microcontrollers and displays. We’ll use an ESP32 development board with a built-in TFT Touchscreen display.

Getting Started with LVGL Graphics Library with ESP32 Cheap Yellow Display CYD Board ESP32-2432S028R

If you have a standalone TFT Touchscreen Display 2.8 inch with ILI9341 driver, you can read our LVGL guide for the ESP32.

Introducing the ESP32 Cheap Yellow Display – CYD (ESP32-2432S028R)

The ESP32-2432S028R development board has become known in the maker community as the “Cheap Yellow Display” or CYD for short. This development board, whose main chip is an ESP32-WROOM-32 module, comes with a 2.8-inch TFT touchscreen LCD, a microSD card interface, an RGB LED, and all the required circuitry to program and apply power to the board.

ESP32 Cheap Yellow Display CYD Board ESP32-2432S028R front

This is a very versatile board to build GUIs for your IoT projects and is much more convenient and practical than using a separate ESP32 board with a TFT screen.

ESP32 Cheap Yellow Display CYD Board ESP32-2432S028R back labeled

Related content: Getting Started with ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R)

Here’s a list of more detailed specifications of this development board:

  • Dual-core MCU, integrated WI-FI and Bluetooth functions
  • Frequency can reach 240MHz
  • 520KB SRAM, 448KB ROM, Flash size is 4MB
  • Module size 50.0×86.0mm
  • Operating Voltage: 5V
  • Power consumption: approximately 115mA
  • Product weight: approximately 50g
  • The module includes:
    • 2.8-inch color TFT display screen with ILI9341 driver chip
    • Display resolution: 240x320px with resistive touchscreen
    • Backlight control circuit
    • TF card interface for external storage
    • Serial interface
    • Temperature and humidity sensor interface (DHT11 interface) and reserved IO port interface
    • It can be programmed with: Arduino IDE, MicroPython, ESP-IDF

In the Extended GPIO connectors, there are at least 4 GPIOs available: GPIO 35, GPIO 22, GPIO 21, and GPIO 27. It also has the TX/RX pins available (see previous image).

More information about the CYD board GPIOs: ESP32 Cheap Yellow Display (CYD) Pinout (ESP32-2432S028R).

Where to buy?

You can click the link below to check where to buy the ESP32 Cheap Yellow display and its price in different stores.

Introducing LVGL (Light and Versatile Graphics Library)

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).

Logo LVGL Light and Versatile Graphics Library

Here are some of its key features:

  • Blocks: buttons, charts, lists, sliders, images, etc…
  • Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling;
  • Various input devices such as touchpad, mouse, keyboard, encoder, etc…
  • Multi-language support with UTF-8 encoding;
  • Multi-display support, i.e. use multiple TFT, monochrome displays simultaneously;
  • Fully customizable graphic elements with CSS-like styles;
  • Hardware independent: use with any microcontroller or display;
  • Scalable: able to operate with little memory (64 kB Flash, 16 kB RAM);
  • Written in C for maximal compatibility (C++ compatible) and binding to MicroPython.

It also has a wide range of code examples in their documentation that you can use: text, buttons, sliders, input fields, keyboard, custom styling, images, arcs, lines, animations, menus, tabs, layouts, tables, and much more…

LVGL Library Examples

Installing Arduino Libraries

The ESP32 communicates with the TFT Display and Touchscreen using SPI communication protocol. We’ll be using the TFT_eSPI, XPT2046_Touchscreen, and LVGL 9 libraries.

Installing the TFT_eSPI Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for TFT_eSPI. Select the TFT_eSPI library by Bodmer and install it.

Installing TFT_eSPI library Bodmer Arduino IDE 2

Installing the XPT2046_Touchscreen Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for XPT2046_Touchscreen. Select the XPT2046_Touchscreen library by Paul Stoffregen and install it.

Installing XPT2046_Touchscreen Library by Paul Stoffregen Arduino IDE 2

Installing the LVGL 9 Library

Open your Arduino IDE and go to Sketch Include Library > Manage Libraries. The Library Manager should open. Search for LVGL. Select the LVGL library by kiskegabor and install version 9.2.

Installing LVGL version 9.2 Arduino IDE software

Prepare Config Files for TFT_eSPI and LVGL Library

To properly use the TFT_eSPI library, you need a configuration file called User_Setup.h with the right definitions. You also need to prepare the lv_conf.h file for the LVGL library. We’ve already prepared these two files so that you don’t have any configuration issues following our examples. You just need to download them and move them to the correct folders. Follow the next instructions to learn how to do it.

a) Preparing the Config Files – Windows PC

b) Preparing the Config Files – Mac OS

a) Preparing the Config Files – Windows PC

Having all the libraries installed (TFT_eSPI, XPT2046_Touchscreen, and LVGL), start by downloading the User_Setup.h configuration file.

User_Setup.h file for TFT_eSPI library Bodmer Arduino IDE 2

In your Arduino IDE, go to File and open the Preferences menu.

Open Arduino IDE 2 Preferences Menu Windows PC

Copy the Arduino IDE “Sketchbook location” path. In my case, it’s:

C:\Users\rui_s\Documents\Arduino
Open Sketchbook Location Arduino IDE 2 Browse

Then, in your Windows PC File Explorer tab enter the sketchbook location path to open the Arduino folder (it’s usually under the Documents folder).

Browse to Arduino libraries folder to copy lv_conf.h file Arduino IDE 2

Open the libraries folder:

Open the Arduino IDE 2 Libraries Folder Windows PC

You should see the TFT_eSPI library folder there. Open it.

Open TFT_eSPI folder libraries Arduino IDE 2

You should be in a similar folder path as shown below:

C:\Users\rui_s\Documents\Arduino\libraries\TFT_eSPI

Copy the User_Setup.h file provided earlier and replace the existing file.

Move copy User_Setup.h file to TFT_eSPI library folder Arduino IDE 2

Then, download the lv_conf.h configuration file.

lv_config.h file for LVGL library by Kisvegabor Arduino IDE 2

Open a similar folder path in your computer as shown below:

C:\Users\rui_s\Documents\Arduino\libraries

Move the lv_conf.h to the libraries folder (do NOT move it inside the lvgl folder).

Move copy lv_conf.h configuration file to Arduino libraries folder Arduino IDE 2

IMPORTANT: other User_Setup.h and lv_conf.h files available on the internet will probably NOT work with the examples available at Random Nerd Tutorials. You must use the exact files provided in this article.

Note: if you update your libraries, you’ll need to do this procedure again and place the right configuration files in the right places.

b) Preparing the Config Files – Mac OS

Having both libraries installed (TFT_eSPI and XPT2046_Touchscreen), download the User_Setup.h configuration file.

Download User_Setup.h file for TFT_eSPI library Bodmer Arduino IDE 2

In your Arduino IDE, open the Settings menu.

Open Arduino IDE 2 Preferences Menu Mac OS

Copy the Arduino IDE “Sketchbook location” path. In my case, it’s:

/Users/rui/Documents/Arduino
Open Sketchbook Location Arduino IDE 2 Browse Mac OS

In Finder, type /Users/rui/Documents/Arduino and open that directory.

Open the Arduino IDE 2 Folder Mac OS

Open the libraries folder.

Open the Arduino IDE 2 Libraries Folder Mac OS

You should see the TFT_eSPI library folder there. Open it.

Open TFT_eSPI folder libraries Arduino IDE 2 Mac OS

You should be in a similar folder path as shown below:

/Users/rui/Documents/Arduino/libraries/TFT_eSPI

Copy the User_Setup.h file provided earlier and replace the existing file.

Move copy User_Setup.h file to TFT_eSPI library folder Arduino IDE 2 Mac OS

You should now have the User_Setup.h file provided on that path.

Move User_Setup.h file to TFT_eSPI library folder Arduino IDE 2 Mac OS

Then, download the lv_conf.h configuration file.

Download lv_config.h file for LVGL library by Kisvegabor Arduino IDE 2

Open a similar folder path for the libraries in your computer as shown below:

/Users/rui/Documents/Arduino/libraries
Open the Arduino IDE 2 Libraries Folder Mac OS

Move the lv_conf.h to the libraries folder (do NOT move it inside the lvgl folder).

Move copy lv_conf.h configuration file to Arduino libraries folder Arduino IDE 2 Mac OS

IMPORTANT: other User_Setup.h and lv_conf.h files available on the internet will probably NOT work with the examples available at Random Nerd Tutorials. You must use the exact files provided in this article.

Note: if you update your libraries, you’ll need to do this procedure again and place the right configuration files in the right places.

Code – Display Text, Create Buttons and Slider

The following code displays a simple text in your TFT display and allows you to test the touchscreen using a button and slider. When you press the buttons or slider, it should trigger some events.

Copy the following code to the Arduino IDE and upload it to your board.

/*  Rui Santos & Sara Santos - Random Nerd Tutorials
    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>

// Install the "XPT2046_Touchscreen" library by Paul Stoffregen to use the Touchscreen - https://github.com/PaulStoffregen/XPT2046_Touchscreen - Note: this library doesn't require further configuration
#include <XPT2046_Touchscreen.h>

// Touchscreen pins
#define XPT2046_IRQ 36   // T_IRQ
#define XPT2046_MOSI 32  // T_DIN
#define XPT2046_MISO 39  // T_OUT
#define XPT2046_CLK 25   // T_CLK
#define XPT2046_CS 33    // T_CS

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320

// Touchscreen coordinates: (x, y) and pressure (z)
int x, y, z;

#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();
}

// Get the Touchscreen data
void touchscreen_read(lv_indev_t * indev, lv_indev_data_t * data) {
  // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z)
  if(touchscreen.tirqTouched() && touchscreen.touched()) {
    // Get Touchscreen points
    TS_Point p = touchscreen.getPoint();
    // Calibrate Touchscreen points with map function to the correct width and height
    x = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    y = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    z = p.z;

    data->state = LV_INDEV_STATE_PRESSED;

    // Set the coordinates
    data->point.x = x;
    data->point.y = y;

    // Print Touchscreen info about X, Y and Pressure (Z) on the Serial Monitor
    /* Serial.print("X = ");
    Serial.print(x);
    Serial.print(" | Y = ");
    Serial.print(y);
    Serial.print(" | Pressure = ");
    Serial.print(z);
    Serial.println();*/
  }
  else {
    data->state = LV_INDEV_STATE_RELEASED;
  }
}

int btn1_count = 0;
// Callback that is triggered when btn1 is clicked
static void event_handler_btn1(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  if(code == LV_EVENT_CLICKED) {
    btn1_count++;
    LV_LOG_USER("Button clicked %d", (int)btn1_count);
  }
}

// Callback that is triggered when btn2 is clicked/toggled
static void event_handler_btn2(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * obj = (lv_obj_t*) lv_event_get_target(e);
  if(code == LV_EVENT_VALUE_CHANGED) {
    LV_UNUSED(obj);
    LV_LOG_USER("Toggled %s", lv_obj_has_state(obj, LV_STATE_CHECKED) ? "on" : "off");
  }
}

static lv_obj_t * slider_label;
// Callback that prints the current slider value on the TFT display and Serial Monitor for debugging purposes
static void slider_event_callback(lv_event_t * e) {
  lv_obj_t * slider = (lv_obj_t*) lv_event_get_target(e);
  char buf[8];
  lv_snprintf(buf, sizeof(buf), "%d%%", (int)lv_slider_get_value(slider));
  lv_label_set_text(slider_label, buf);
  lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
  LV_LOG_USER("Slider changed to %d%%", (int)lv_slider_get_value(slider));
}

void lv_create_main_gui(void) {
  // Create a text label aligned center on top ("Hello, world!")
  lv_obj_t * text_label = lv_label_create(lv_screen_active());
  lv_label_set_long_mode(text_label, LV_LABEL_LONG_WRAP);    // Breaks the long lines
  lv_label_set_text(text_label, "Hello, world!");
  lv_obj_set_width(text_label, 150);    // Set smaller width to make the lines wrap
  lv_obj_set_style_text_align(text_label, LV_TEXT_ALIGN_CENTER, 0);
  lv_obj_align(text_label, LV_ALIGN_CENTER, 0, -90);

  lv_obj_t * btn_label;
  // Create a Button (btn1)
  lv_obj_t * btn1 = lv_button_create(lv_screen_active());
  lv_obj_add_event_cb(btn1, event_handler_btn1, LV_EVENT_ALL, NULL);
  lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -50);
  lv_obj_remove_flag(btn1, LV_OBJ_FLAG_PRESS_LOCK);

  btn_label = lv_label_create(btn1);
  lv_label_set_text(btn_label, "Button");
  lv_obj_center(btn_label);

  // Create a Toggle button (btn2)
  lv_obj_t * btn2 = lv_button_create(lv_screen_active());
  lv_obj_add_event_cb(btn2, event_handler_btn2, LV_EVENT_ALL, NULL);
  lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 10);
  lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
  lv_obj_set_height(btn2, LV_SIZE_CONTENT);

  btn_label = lv_label_create(btn2);
  lv_label_set_text(btn_label, "Toggle");
  lv_obj_center(btn_label);
  
  // Create a slider aligned in the center bottom of the TFT display
  lv_obj_t * slider = lv_slider_create(lv_screen_active());
  lv_obj_align(slider, LV_ALIGN_CENTER, 0, 60);
  lv_obj_add_event_cb(slider, slider_event_callback, LV_EVENT_VALUE_CHANGED, NULL);
  lv_slider_set_range(slider, 0, 100);
  lv_obj_set_style_anim_duration(slider, 2000, 0);

  // Create a label below the slider to display the current slider value
  slider_label = lv_label_create(lv_screen_active());
  lv_label_set_text(slider_label, "0%");
  lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
}

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);

  // Start the SPI for the touchscreen and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  // Set the Touchscreen rotation in landscape mode
  // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);
  touchscreen.setRotation(2);

  // 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);
    
  // Initialize an LVGL input device object (Touchscreen)
  lv_indev_t * indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  // Set the callback function to read Touchscreen input
  lv_indev_set_read_cb(indev, touchscreen_read);

  // Function to draw the GUI (text, buttons and sliders)
  lv_create_main_gui();
}

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
}

View raw code

How the Code Works

Let’s take a quick look at the parts of the code that are relevant to this example.

Libraries

Include the lvgl, TFT_eSPI and XPT2046_Touchscreen libraries.

#include <lvgl.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>

Initialize Touchscreen

The following lines set the touchscreen pinout:

#define XPT2046_IRQ 36
#define XPT2046_MOSI 32
#define XPT2046_MISO 39
#define XPT2046_CLK 25
#define XPT2046_CS 33

Create a touchscreenSPI and touchscreen instances:

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

Other Variables

Set the screen width and screen height:

#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
#define FONT_SIZE 2

Variables to store the coordinates: (x, y) and pressure (z).

int x, y, z;

setup()

Start a serial communication with the Serial Monitor at a baud rate of 115200 and print the LVGL library version that you are using:

String LVGL_Arduino = String("LVGL Library Version: ") + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.begin(115200);
Serial.println(LVGL_Arduino);

Start the LVGL and assign a callback function for debugging purposes.

lv_init();
lv_log_register_print_cb(log_print);

Start the SPI for the touchscreen and initialize the touchscreen.

touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
touchscreen.setRotation(2);

Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 0: touchscreen.setRotation(0);

Create the display object and initialize the TFT display using the TFT_eSPI library.

lv_display_t * disp;
disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_270);

Initialize an LVGL input device object (touchscreen) and set the callback function that will be triggered when you click the touchscreen.

lv_indev_t * indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev, touchscreen_read);

Finally, call the lv_create_main_gui() function to draw the GUI for your touchscreen:

lv_create_main_gui();

loop()

When running an LVGL example, the loop() will usually look like this:

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

lv_create_main_gui()

The lv_create_main_gui() function draws the text label, buttons, and sliders. It’s also where you assign the event handler callback functions that will be triggered when you interact with your display.

void lv_create_main_gui(void) {
  // Create a text label aligned center on top ("Hello, world!")
  lv_obj_t * text_label = lv_label_create(lv_screen_active());
  lv_label_set_long_mode(text_label, LV_LABEL_LONG_WRAP);    // Breaks the long lines
  lv_label_set_text(text_label, "Hello, world!");
  lv_obj_set_width(text_label, 150);    // Set smaller width to make the lines wrap
  lv_obj_set_style_text_align(text_label, LV_TEXT_ALIGN_CENTER, 0);
  lv_obj_align(text_label, LV_ALIGN_CENTER, 0, -90);

  lv_obj_t * btn_label;
  // Create a Button (btn1)
  lv_obj_t * btn1 = lv_button_create(lv_screen_active());
  lv_obj_add_event_cb(btn1, event_handler_btn1, LV_EVENT_ALL, NULL);
  lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -50);
  lv_obj_remove_flag(btn1, LV_OBJ_FLAG_PRESS_LOCK);

  btn_label = lv_label_create(btn1);
  lv_label_set_text(btn_label, "Button");
  lv_obj_center(btn_label);

  // Create a Toggle button (btn2)
  lv_obj_t * btn2 = lv_button_create(lv_screen_active());
  lv_obj_add_event_cb(btn2, event_handler_btn2, LV_EVENT_ALL, NULL);
  lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 10);
  lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
  lv_obj_set_height(btn2, LV_SIZE_CONTENT);

  btn_label = lv_label_create(btn2);
  lv_label_set_text(btn_label, "Toggle");
  lv_obj_center(btn_label);
  
  // Create a slider aligned in the center bottom of the TFT display
  lv_obj_t * slider = lv_slider_create(lv_screen_active());
  lv_obj_align(slider, LV_ALIGN_CENTER, 0, 60);
  lv_obj_add_event_cb(slider, slider_event_callback, LV_EVENT_VALUE_CHANGED, NULL);
  lv_slider_set_range(slider, 0, 100);
  lv_obj_set_style_anim_duration(slider, 2000, 0);

  // Create a label below the slider to display the current slider value
  slider_label = lv_label_create(lv_screen_active());
  lv_label_set_text(slider_label, "0%");
  lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
}

event_handler_btn1()

The event_handler_btn1() function is triggered when you click the “Button” and it will also display in the Arduino IDE Serial Monitor the number of times the button has been clicked.

int btn1_count = 0;
// Callback that is triggered when btn1 is clicked
static void event_handler_btn1(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  if(code == LV_EVENT_CLICKED) {
    btn1_count++;
    LV_LOG_USER("Button clicked %d%", (int)btn1_count);
  }
}

event_handler_btn2()

The event_handler_btn2() is triggered when you click the “Toggle” button, it stores the current button state and prints a message with the current state in the Serial Monitor.

// Callback that is triggered when btn2 is clicked/toggled
static void event_handler_btn2(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * obj = (lv_obj_t*) lv_event_get_target(e);
  if(code == LV_EVENT_VALUE_CHANGED) {
    LV_UNUSED(obj);
    LV_LOG_USER("Toggled %s", lv_obj_has_state(obj, LV_STATE_CHECKED) ? "on" : "off");
  }
}

slider_event_callback()

The slider_event_callback() function is called when you move the slider, it will also display both in the touchscreen and Serial Monitor the latest slider value on a scale from 0 to 100%.

static lv_obj_t * slider_label;
// Callback that prints the current slider value on the TFT display and Serial Monitor for debugging purposes
static void slider_event_callback(lv_event_t * e) {
  lv_obj_t * slider = (lv_obj_t*) lv_event_get_target(e);
  char buf[8];
  lv_snprintf(buf, sizeof(buf), "%d%%", (int)lv_slider_get_value(slider));
  lv_label_set_text(slider_label, buf);
  lv_obj_align_to(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
  LV_LOG_USER("Slider changed to %d%%", (int)lv_slider_get_value(slider));
}

Demonstration

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.

Arduino IDE 2 Upload Button

After uploading the code to your board, it should display the sample “Hello, world!” text centered at the top.

Press with your finger the first “Button”. In the Serial Monitor, it will print the coordinates of your button press, as well as a message with the number of times the button has been clicked: “Button clicked 1”, “Button clicked 2”, “Button clicked 3″…

ESP32 Cheap Yellow Display Board CYD TFT Display Touchscreen LVGL Library Example

Then, click the “Toggle” button, this could be used to control an LED or any other output. This button type has two states (color blue when off and color red when on).

ESP32 Cheap Yellow Display Board CYD TFT Display Touchscreen LVGL Library Example Button Toggle

Drag the slider with your finger, you’ll see the slider moving and the slider label changing when you move your finger.

ESP32 Cheap Yellow Display Board CYD TFT Display Touchscreen LVGL Library Example Move Slider

All the events will be printed in your Arduino IDE Serial Monitor for debugging purposes:

ESP32 TFT Touchscreen Display LVGL Basic Example Text Label Button Slider

Wrapping Up

In this tutorial, you learned to get started with the LVGL library with the ESP32 Cheap Yellow Display board. In the next guides, we’ll explore other features and components of the LVGL library.

We hope you found this tutorial useful. We’re preparing more guides about this board, so stay tuned.

Other guides you might like reading:

To learn more about the ESP32, make sure to take a look at our resources:



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

97 thoughts on “LVGL with ESP32 Cheap Yellow Display Board (ESP32-2432S028R)”

  1. As Always your Examples are great,
    I have the 2USB version of the CYD which has the st7789 screen, as I left my own User_setup file in TFT_espi library vut used your lv_conf the sketch ran very well.
    The only issue I have is the mapping for touch is alittle off and the buttons click and toggle slighty off to the lh side of button and will not toggle on the rh side for about the last 10% of the button and slider.
    DO I have to adjust the touch mapping and if so which parts do i need to touch or is this contained within LVGL as I am unfamiliar with this library?
    Many thanks as always a great tutorial
    Mark D

    Reply
  2. Suprisingly I went into your lc conf file and changed it to use the st7789 screen and it made no difference to colour brightness or function. all seemed well

    Reply
    • Wow used a bit of intellect and used the serial print inside the sketch and got it to print p.y and px and then adjusted the mapping now buttons and slider in perfect touchscreen harmony.
      if anyone else uses a CYD2USB, and finds mapping alittle off try these.
      x = map(p.x, 330, 3868, 1, SCREEN_WIDTH); //was 200 3700
      y = map(p.y, 280, 3850, 1, SCREEN_HEIGHT); // was 240 3800

      Reply
  3. Hello Rui and Sara.
    I can use the touchscreen.setRotation(3); change to touchscreen.setRotation(1); But the screen then remains upside down. The slider and buttons also no longer work. greetings from old man Bert

    Reply
  4. Hi Bert you have only rotated the touchscreen not the display.
    Try tft.setRotation(3); or (1) to Match your screen rotation and your touch rotation
    Regards
    Mark D

    Reply
      • Hi Bert,
        You need to create a tft object first. Insert this line somewhere at the top of your sketch (after the #include statements):

        TFT_eSPI tft = TFT_eSPI();

        Now your
        tft.setRotation(1);
        will compile.

        The problem is that it does not help!
        Regardless of the value used for tft.setRotation() (I’ve tried all four), the graphics on the screen does not rotate.

        I’ve also tried an LVGL function

        lv_disp_set_rotation(disp,LV_DISP_ROTATION_x); // replace x with 0, 90, 180 or 270

        to no avail.

        Reply
        • Hi Ben, I had the same issue just with only teh tft_eSPI-library and found somewhere that you need to add a delay after setting te rotation to give the chip some time to act. 50ms will do.
          tft.init();
          tft.setRotation(2);
          delay(50); // needed for display to react

          Did the job in my case.

          Reply
  5. You are awesome!

    I spent the whole weekend a couple of weeks ago and ran into some other problem with LVGL. I got this email today, followed these steps, and it worked in 5 minutes. Can’t thank you enough for this.

    Reply
    • Hi.
      Yes, you can use I2C on GPIOs 22 and 27 using the extended IO socket.
      I haven’t tested powering the display with batteries. The only input is via the microUSB socket.
      Regards,
      Sara

      Reply
  6. Thanks for this userfull procedure.

    Do you have a piece of code for a button onclick event with an http request ?

    Merci,
    marc,

    Reply
  7. Hi you
    Thank you very much for this great tutorial. I will study it more in depth later. RNT is a very valuable maker source for me, even if I search for information later. Your examples are often a good starting point, as they always work.
    Will this tutorial be part of a ebook?

    Reply
    • Hi.
      We’re currently working on an eBook about this subject.
      It will include many practical examples.
      Regards,
      Sara

      Reply
  8. Great guide, sharing a fantastic community on CYD over here on Brian Lough’s Discord channel discord.gg/998cVD53

    Reply
    • I recently discovered that Discord channel, great source for information about the CYD, and the many varieties of CYD.
      Some very helpful and knowledgeable people too, who will often advise or help with so many aspects of CYD and other ESP stuff too.
      Even a great Display Library with a very simple way to define the board your are using in the library(no complicated User_setup file req), called bb_spi_lcd in the Arduino library

      Reply
  9. Congratulation Rui & Sara !
    It works !
    But colors are inverted on mine (buttons are yellow and the back is black) How to invert video ?
    Thanks
    JMH

    Reply
  10. hello,
    It works but I need a piece of code for the action when we click on the button.
    Do you have a exemple ?
    Thanks,

    Reply
    • Hi.
      You can had the action you want inside the buttons callback functions.
      For example, for button 1, it’s the event_handler_btn1() function. Inside add any actions you want to perform when you click the button.
      Regards,
      Sara

      Reply
      • Hi,
        when pressing button2, the toggle button, it changes color, but cannot find where this change of color is done . Any input ?

        Reply
  11. Hello, thank you very much for the tutorial. How do I include the code of other lvgl elements?
    it’s possible?

    Reply
  12. I had previously tried fighting my way through confusing instructions from various sources, setting up lvgl.h, the Touch SPI, the various libraries, moving some folders into other folders for unknown reasons, etc. This took days, and worse, it didn’t work, so this is All Good Stuff. Thank you.

    Reply
  13. Hey, First of all thanks for the great tutorials (esp-now really helped me out), Now I am trying to get a LVGL GUI for my project but I get this error all the time.
    line 199:
    lv_display_t * disp;
    disp = lv_tft_espi_create(TFT_HOR_RES, TFT_VER_RES, draw_buf, DRAW_BUF_SIZE);

    screen.cpp:199:10: error: ‘lv_tft_espi_create’ was not declared in this scope; did you mean ‘lv_tlsf_create’?
    199 | disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));

    I have tried several other lvgl projects, made sure I have the same versions but to no help.

    Reply
    • Hi.
      Please double-check the instructions to install the libraries and preparing the configuration files.
      Make sure you’re placing everything in the right places and that you’re using the recommended library versions.
      Regards,
      Sara

      Reply
  14. Hey, sorry if this post comes twice.

    But I am having a problem with this code, the error I get is this:
    error: ‘lv_tft_espi_create’ was not declared in this scope; did you mean ‘lv_tlsf_create’?
    178 | disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));

    And i just copy your code, can you help me?
    ps. thanks for great tutorial, especially the esp-now was super helpful to me

    Reply
      • Hi.
        Please follow the libraries’ installation carefully.
        Make sure you’re using the provided files and placing them on the right folders.
        Regards,
        Sara

        Reply
  15. Fantastic resource, as always. Thanks again for helping us beginners! Do you intend to create a tutorial on using the keyboard widget too? This really intrigues me and I would like to use it, but alas… my knowledge is not complete enough.

    Reply
  16. An upgrade on screen rotation and the right colors.
    I have an ESP32-2432S028 (without the final R) and to have the correct rotation you need to use the TFT_eSPI library command at the beginning of the sketch immediately after the declarations:

    TFT_eSPI tft = TFT_eSPI();

    then these lines must be added to the setup

    touchscreen.setRotation(1);
    lv_display_t * disp;
    disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT,draw_buf,sizeof(draw_buf));
    tft.setRotation(1);
    tft.invertDisplay(1);// this changes the color assignment

    Reply
    • I have the same variant without R, my Rotation was ok but colors were off (Yellow buttons on Black Background)

      I just added these lines:

      In Definition
      TFT_eSPI tft = TFT_eSPI();

      In Setup
      tft.invertDisplay(1);// this changes the color assignment

      Touch mapping seems a bit off ill try the suggestions above

      Reply
  17. @Gabryx

    Thank you very much! We must have the same CYD. I’ve added a note about this to my library folder so it’ll always be there to remind me.

    @Sara Santos
    These tutorials are very useful/straight forward, and I really appreciate it! I do wish that all the preliminary hand holding could be put into a separate tutorial though. I’m referring to the sections for Windows and Mac users on how to copy and paste a file to a directory. Wow! How many pictures does it take?! Just kidding, yeah, but no I’m serious. I know, beginners gotta begin somewhere. So that’s cool. But yeah…

    Reply
  18. When i use the LVLG library, the code takes so long to compile (Over 10 min), anything i could do to improve the compilation speed?

    Reply
    • You should leave the Arduino IDE and start using VS Code and PlatformIO, the compiling is very fast, only the first compile takes around 250 seconds, after that if you only make small changes the compiler is smart and takes only 20-25 seconds

      Reply
    • 1 min max for me if they are large sketches
      AMD Ryzen 5 4500 6-Core (Renoir) 3.60GHz 16GB Ram

      To speed up compilation you must exclude all Arduino directories from antivirus, including those in C:User/name\AppData\Local\Arduino15\

      Reply
  19. For Much better colors for the CYD2USB Variant, add all this to the setup

    tft.invertDisplay(1); // if your colors are inverted

    tft.writecommand(ILI9341_GAMMASET); //Gamma curve selected
    tft.writedata(2);
    delay(120);
    tft.writecommand(ILI9341_GAMMASET); //Gamma curve selected
    tft.writedata(1);

    Reply
  20. I want to be able to use larger fonts (90+). I have looked at a number of github sites but am not getting anywhere. Do you know of a site that is easy to understand and fairly simple ( like your tutorials) to implement.

    Thanks

    Reply
    • Hi Chris, for larger Fonts pop over to the above discord channel for some advice, there are some good examples of how to use larger fonts within various libraries.
      Brian Lough’s Discord channel discord.gg/998cVD53

      Reply
  21. Hi, how can I reduce the compiling time? It takes about half an hour to do any code using “lvgl”-library. I followed all instructions on this website. My Board is “ESP32-2432S028”. Laptop is very strong.

    Reply
  22. Ciao
    Potete aiutarmi nella compilazione mi da questo errore: Grazie

    c:\Users\ivovi\AppData\Local\Programs\Arduino IDE\libraries\libraries\lvgl\src\examples\styles\lv_example_style_14.c:1:10: fatal error: ../../src/themes/lv_theme_private.h: No such file or directory
    1 | #include “../../src/themes/lv_theme_private.h”
    | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    compilation terminated.

    Reply
  23. Ciao, ho aggiornato librerie con i files di configurazione ultima versione dell’ebook v1.3 LVGL ma ritorna sempre errore compilazione. Grazie

    c:\Users\ivovi\AppData\Local\Programs\Arduino IDE\libraries\libraries\lvgl\src\examples\styles\lv_example_style_14.c:1:10: fatal error: ../../src/themes/lv_theme_private.h: No such file or directory
    1 | #include “../../src/themes/lv_theme_private.h”
    | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    compilation terminated.
    Alternative per ../../src/themes/lv_theme_private.h: []
    ResolveLibrary(../../src/themes/lv_theme_private.h)
    -> candidati: []
    exit status 1

    Compilation error: exit status 1

    Reply
  24. Hi,
    Followed the different steps, and compiled…..but get errors :
    166:3: error: ‘lv_log_register_print_cb’ was not declared in this scope
    166 | lv_log_register_print_cb(log_print);
    178:10: error: ‘lv_tft_espi_create’ was not declared in this scope; did you mean ‘lv_timer_create’?
    178 | disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf));
    Any suggestions ?
    thank you in advancd
    best regards
    Ludo

    Reply
    • Hi.
      Are you using VS Code or Arduino IDE?
      Did you copy the whole code’ It seems it cannot find some of the functions defined in the code??
      Regards,
      Sara

      Reply
      • Hi Sara,
        I am using arduino ide.
        In the mean time, I moved back to lvgl 9.0, and then I did not get the errors anymore. Strange that 9.2 works for you, not for me…. Anyway, it works now.
        Thank you
        Regards

        Reply
  25. Hi,
    The toggle button is changing color when clicked, but cannot find the place where these colors are defined.
    Please confirm.
    Thank you.
    Regards
    Ludo

    Reply
  26. Hi,
    in this example, the toggle button changes color .
    Where in the program is this done ? I cannot find any red/blue color change
    regards
    Ludo

    Reply
    • Hi.
      Those are the default colors for a toggle button set by the LVGL library for that kind of widget.
      But it is possible to change the colors using styles.
      Regards,
      Sara

      Reply
  27. #include “../../lv_examples.h”
    #if LV_USE_SCALE && LV_BUILD_EXAMPLES

    LV_IMAGE_DECLARE(img_hand);

    lv_obj_t * needle_line;
    lv_obj_t * needle_img;

    static void set_needle_line_value(void * obj, int32_t v)
    {
    lv_scale_set_line_needle_value(obj, needle_line, 60, v);
    }

    static void set_needle_img_value(void * obj, int32_t v)
    {
    lv_scale_set_image_needle_value(obj, needle_img, v);
    }

    /**
    * A simple round scale
    */
    void lv_example_scale_3(void)
    {
    lv_obj_t * scale_line = lv_scale_create(lv_screen_active());

    lv_obj_set_size(scale_line, 150, 150);
    lv_scale_set_mode(scale_line, LV_SCALE_MODE_ROUND_INNER);
    lv_obj_set_style_bg_opa(scale_line, LV_OPA_COVER, 0);
    lv_obj_set_style_bg_color(scale_line, lv_palette_lighten(LV_PALETTE_RED, 5), 0);
    lv_obj_set_style_radius(scale_line, LV_RADIUS_CIRCLE, 0);
    lv_obj_set_style_clip_corner(scale_line, true, 0);
    lv_obj_align(scale_line, LV_ALIGN_LEFT_MID, LV_PCT(2), 0);

    lv_scale_set_label_show(scale_line, true);

    lv_scale_set_total_tick_count(scale_line, 31);
    lv_scale_set_major_tick_every(scale_line, 5);

    lv_obj_set_style_length(scale_line, 5, LV_PART_ITEMS);
    lv_obj_set_style_length(scale_line, 10, LV_PART_INDICATOR);
    lv_scale_set_range(scale_line, 10, 40);

    lv_scale_set_angle_range(scale_line, 270);
    lv_scale_set_rotation(scale_line, 135);

    needle_line = lv_line_create(scale_line);

    lv_obj_set_style_line_width(needle_line, 6, LV_PART_MAIN);
    lv_obj_set_style_line_rounded(needle_line, true, LV_PART_MAIN);

    lv_anim_t anim_scale_line;
    lv_anim_init(&anim_scale_line);
    lv_anim_set_var(&anim_scale_line, scale_line);
    lv_anim_set_exec_cb(&anim_scale_line, set_needle_line_value);
    lv_anim_set_duration(&anim_scale_line, 1000);
    lv_anim_set_repeat_count(&anim_scale_line, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_playback_duration(&anim_scale_line, 1000);
    lv_anim_set_values(&anim_scale_line, 10, 40);
    lv_anim_start(&anim_scale_line);

    lv_obj_t * scale_img = lv_scale_create(lv_screen_active());

    lv_obj_set_size(scale_img, 150, 150);
    lv_scale_set_mode(scale_img, LV_SCALE_MODE_ROUND_INNER);
    lv_obj_set_style_bg_opa(scale_img, LV_OPA_COVER, 0);
    lv_obj_set_style_bg_color(scale_img, lv_palette_lighten(LV_PALETTE_RED, 5), 0);
    lv_obj_set_style_radius(scale_img, LV_RADIUS_CIRCLE, 0);
    lv_obj_set_style_clip_corner(scale_img, true, 0);
    lv_obj_align(scale_img, LV_ALIGN_RIGHT_MID, LV_PCT(-2), 0);

    lv_scale_set_label_show(scale_img, true);

    lv_scale_set_total_tick_count(scale_img, 31);
    lv_scale_set_major_tick_every(scale_img, 5);

    lv_obj_set_style_length(scale_img, 5, LV_PART_ITEMS);
    lv_obj_set_style_length(scale_img, 10, LV_PART_INDICATOR);
    lv_scale_set_range(scale_img, 10, 40);

    lv_scale_set_angle_range(scale_img, 270);
    lv_scale_set_rotation(scale_img, 135);

    /* image must point to the right. E.g. -O------>*/
    needle_img = lv_image_create(scale_img);
    lv_image_set_src(needle_img, &img_hand);
    lv_obj_align(needle_img, LV_ALIGN_CENTER, 47, -2);
    lv_image_set_pivot(needle_img, 3, 4);

    lv_anim_t anim_scale_img;
    lv_anim_init(&anim_scale_img);
    lv_anim_set_var(&anim_scale_img, scale_img);
    lv_anim_set_exec_cb(&anim_scale_img, set_needle_img_value);
    lv_anim_set_duration(&anim_scale_img, 1000);
    lv_anim_set_repeat_count(&anim_scale_img, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_playback_duration(&anim_scale_img, 1000);
    lv_anim_set_values(&anim_scale_img, 10, 40);
    lv_anim_start(&anim_scale_img);

    }

    #endif

    The Arduino IDE does not like this
    get
    src/main.cpp: In function ‘void set_needle_line_value(void*, int32_t)’:
    src/main.cpp:94:36: error: invalid conversion from ‘void‘ to ‘lv_obj_t‘ [-fpermissive]
    lv_scale_set_line_needle_value(obj, needle_line, 60, v);

    static void set_needle_line_value(void * obj, int32_t v)
    {
    lv_scale_set_line_needle_value(obj, needle_line, 60, v);
    }

    Reply
  28. Hi,

    Does enyone know why I can’t get this to work on my ESP32-2432S032? I ordered an ESP32-2432S028 from Amazon, but they shipped a ..32.
    When I’ve compared images to the ESP32-2432S028, it seems mostly the cards are mirrored and the USB-port is USB-C, instead if micro-USB, but could they have switched IO-pins for the TFT or something? I haven’t found many tutorials with the ESP32-2432S032.

    Main goal was to set up a Weather station, which you also have a tutorial for here, but when I compiled that, it said that it’s too big 137% for my card.

    I’m fairly new to ESP-boards, so it might be that I’m doing some trivial mistake also.

    Out of the box the card had this demo with the girl and the shop ect. so it’s not completely faulty. I then tried a template from the Ardruino Cloud, the Sparkfun Weather Station, and I could even get it online, but didn’t find any way to modify the code.

    After this I did the steps here with Arduino IDE 2.3.3 and uploaded the code, but only the led is red and display is not on/responding at all.

    I could return this card and ask for the ESP32-2432S028, but I don’t think this one is broken, just need some help to get the display setting correct I asume? Any help would be great!

    Thanks in advance!

    Reply
    • Hi.

      If you see an Error like this: “Sketch too big” during the uploading process, in Arduino IDE go to Tools > Partition scheme > choose anything that has more than 1.4MB APP, for example: “Huge APP (3MB No OTA/1MB SPIFFS“.

      What chip does your display use? Is it the ILI9341?
      If it’s a different one, you need to specify that in the User_Setup file.

      Regards,
      Sara

      Reply
      • Hi Sara,

        I now changed the Partitition scheme as you suggested and had inserted my Wi-Fi credentials to the Weather station code. I now see the ESP32 on my routers device list, but still the dislpay is dead and now the led is off, so there’s nothing to indicate the board is even on.

        I also looked in to the User_Setup file, but I’m kind of more leaning to this display actually being a ILI9341, as I also have a 2,4″ ILI9341 display. I could try that together with another ESP32 learning kit I have and see if I could figure out what’s the problem.

        Br,
        Andreas

        Reply
  29. Hello! Thanks for all the excellent tutorials.
    This code doesn’t compile in PIO/VS Code. It seems that touchscreen.begin() does not take an argument (touchscreenSPI). If I change to touchscreen.begin(); the code compiles and runs on my CYD, but the touchscreen doesn’t work (even without any touch, it constantly returns warnings about indev_pointer_proc is smaller than zero). I notice all the RNT CYD pages configure the touchscreen this way. Am I doing something wrong or has there been a change in the library?

    Reply
  30. Well this is a weird one…there’s no issue with the code. The library should take SPI as an argument. However, when I install the library using PIO library manager, it doesn’t work. If I refer to the library directly it works.
    In other words, this platformio.ini does NOT work:

    lib_deps =
    lvgl/lvgl@^9.2.0
    bodmer/TFT_eSPI@^2.5.43
    paulstoffregen/XPT2046_Touchscreen

    And this platformio.ini DOES work:

    lib_deps =
    lvgl/lvgl@^9.2.0
    bodmer/TFT_eSPI@^2.5.43
    https://github.com/PaulStoffregen/XPT2046_Touchscreen

    Reply
  31. Hi,
    Everything works fine, but the slider action is reversed.
    If i slide left the value increases instead of decreasing, and vice versa.
    How can I fix this ?

    Reply
  32. Is there any existing firmware for an esp32 lvgl display that would allow me to send graphics drawing commands to it from a Linux program on another computer, either over wifi or a serial connection? I.e. an interpreter for some graphics protocol. I’m not too fussy what the graphics package driving it on the Linux side is (as long as it is in C or at least callable from C). Basically I want to use an LVGL display as a graphics terminal, sort of like how we used to use Tektronix terminals back in the 80’s over RS232 serial lines… I don’t particularly want to have to create it from scratch myself and I definitely don’t want to port my actual applications to the ESP32, I just want to use it as a smart display or terminal which I can ask to draw lines and curves etc from a C program on a linux computer. If it could handle creating and stamping sprites that would be a bonus, but minimum requirement for me is just line drawing.

    Reply
    • After posting that, it occurred to me that a solution which would be more generally useful, would be to have a version of the LVGL library hosted on the Linux system, which passed the call and parameters to the ESP32 to be executed – i.e. a similar model to how X-windows works. I don’t mind coding to the LVGL library interface, I just can’t run Linux-specific applications on the ESP32. Does a remote driver like that exist for LVGL anywhere?

      By the way, I did find something approaching the sort of library I was looking for: https://github.com/feilipu/ReGIS although it may be a bit more complex to use than I was hoping to find.

      Reply
      • Sorry I forgot to point out: although ReGIS is the sort of remote graphics protocol I’m looking for, it’s 1) serial only, no wifi support; and 2) no implementation for the ESP32/LVGL boards – so I would have to add both of those. Which I’m willing to do at some point (got a lot of projects on the go to finish first) but I was really hoping to find something that already existed and was ready to use.

        Reply
  33. Hi,
    Is there a system available which would allow me to build up a GUI without directly looking at the code for IT, for example QT has the capability to add different types of things onto a page, such as text boxes, radio buttons etc.

    Reply
  34. Without changing the settings in the IDE the screen did not work anymore. I did the setup again but now I get this message.
    No such file or directory
    #include <User_Setups/User_Custom_Fonts.h>
    Help me please

    Reply
  35. I have two of these CYD’s. Both bought from different suppliers. i Program device 1 fine, the display is expected. But device 2 needs inverting. Once inverted the colours are the same, however device 2 seems to me brighter, you can barely see the backbar of the slider.

    Any suggestions?

    Reply
  36. Are the boards identical. Does one have a USB C and a micro USB connector and the other maybe a single USB micro connector?
    If this is the case then the boards are alittle different. One is called the CYD and the other is called the 2USBCYD and they use different display drivers. The latter uses an ST7789 display and the former user ili9341 driver. Both of which have to be correct in tft espi user setup.h and lv.conf files

    Reply
  37. I have used PlatformIO for this example. When i use the serial monitor to see the logs that get created, a bunch of random strings get generated
    “H␑B␅␘␎8$!�1��|<�����ѱd��m�␑��.���L8�Ώ�H�8����v
    ����h�␎��e�N�a�N�Č){�N�)��n�+�8�H�e�␎af
    9)ev
    9)�B��b�,�H8u���;��Jb:���␌)��g���Nhncf
    9)a�n!��af
    9�c�N!��l8He�␎␌!J”�<␗9��,�L1
    Ϥ(a␡
    de�ʩ2��L1
    Ϥ(��f␌␑H�Ħ␗)J”���mNʩ2����a�␑H��4K�xbH�MN�)��c��(�H�MN�)2���+�zO␌ל�␎���
    �rOHʌ1����b��H�Ʀ�!
    ψ״r2���”

    Can anyone help with this?

    Reply
  38. What library and setup code do I need to add to gain access to the micro SD card slot? I just want to store a few data points and access them when the device reboots. Thanks

    Reply
  39. Hello Rui and Sara. I want to ask if I have the 3.5 inch CYD, what do I need to change because the code for 2.8 inch does not work. It can be uploaded in my CYD display but the screen went blank. Before, it was an example display. Can you help me?

    Reply
  40. Just a Query, what version of the Arduino IDE are you suggesting that we use for W10 to compile and burn this particular project?

    Also, that “CYD” board you specify “ESP32-2432S028R”, all I can find for retail sale is the “ESP32-2432S028”, your links also point to this board? I do not know how to tell the difference between this board and the suggested “ESP32-2432S028R”. Is there any difference?

    Reply
    • Hi.
      We’re using Arduino IDE 2.
      The boards are the same if the one without the “R” mentions that it has a resistive touchscreen display.
      I hope this helps.
      Regards,
      Sara

      Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.