Skip to main content

docs Section 08 Porting LVGL

This section uses the LVGL v8 example from the example package. It drives the display and touch panel through the ESP32_Display_Panel library and displays an official LVGL example.

Hardware Connection​

To upload the corresponding code to the ESP32-S3, you need to connect the USB port of the ESP32-S3-Touch-LCD-7 to the computer's USB port using a Type-C to Type-A cable:

ESP32-S3-Touch-LCD-7 USB connection diagram

Example​

Please download the example package from the following address: ESP32-S3-Touch-LCD-7 Example (if already downloaded, simply open the corresponding folder). After downloading or cloning the repository, open the corresponding examples/Arduino/examples/09_lvgl_v8_demo folder.

Double-click to open 09_lvgl_v8_demo.ino.

In the Arduino IDE, select the serial port and board model Waveshare ESP32-S3-Touch-LCD-7.

Set the corresponding board parameters:

ESP32-S3-Touch-LCD-7 LVGL example 4

Then click the Upload button to upload the program, and wait for the upload to complete.

Running Results​

Power cycle the screen, and you will see the LVGL v8 example displayed on the screen. For the version with a touch panel, slide on the screen to test the touch function.

ESP32-S3-Touch-LCD-7 LVGL v8 example result

Code Review​

1. Driving the Display and Touch Panel​

This example uses the esp_panel_board_custom_conf.h file in the example directory to configure the display, touch panel, backlight, and I/O expander. For information about configuring this file, refer to the ESP32_Display_Panel official documentation.

The main configuration used by this example is described below.

Enable custom LCD panel

#define ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM (1)

First, change the macro ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM from 0 to 1 to enable custom configuration. This will enable the configuration parameters under #if ESP_PANEL_BOARD_DEFAULT_USE_CUSTOM.

#define ESP_PANEL_BOARD_NAME "Waveshare:ESP32-S3-Touch-LCD-7"
#define ESP_PANEL_BOARD_WIDTH (800) // Panel width (horizontal, in pixels)
#define ESP_PANEL_BOARD_HEIGHT (480) // Panel height (vertical, in pixels)

Set the custom board name and define the screen resolution.

Set LCD parameters

#define ESP_PANEL_BOARD_USE_LCD (1)

Change the macro ESP_PANEL_BOARD_USE_LCD from 0 to 1 to enable the LCD panel. This will enable the configuration parameters under #if ESP_PANEL_BOARD_USE_LCD.

#define ESP_PANEL_BOARD_LCD_CONTROLLER ST7262
#define ESP_PANEL_BOARD_LCD_BUS_TYPE (ESP_PANEL_BUS_TYPE_RGB)

Define the LCD controller IC and communication type - choose RGB bus communication.

#if ESP_PANEL_BOARD_LCD_BUS_TYPE == ESP_PANEL_BUS_TYPE_RGB
#define ESP_PANEL_BOARD_LCD_RGB_USE_CONTROL_PANEL (0) // 0/1. Typically set to 1

#define ESP_PANEL_BOARD_LCD_RGB_CLK_HZ (16 * 1000 * 1000)
...
#define ESP_PANEL_BOARD_LCD_RGB_IO_DATA15 (40)

#endif

ESP_PANEL_BOARD_LCD_RGB_USE_CONTROL_PANEL is set to 0, indicating that an RGB interface without three-wire SPI is used. The remaining parameters are configured according to the LCD specifications, as in the previous RGB bar example.

Set touch panel parameters

#define ESP_OPEN_TOUCH 1

Define the macro to enable touch functionality. A value of 0 disables touch, 1 enables touch - choose according to the purchased model.

#define ESP_PANEL_BOARD_USE_TOUCH (ESP_OPEN_TOUCH)

Since we set ESP_OPEN_TOUCH to 1, the touch configuration under #if ESP_PANEL_BOARD_USE_TOUCH will be enabled. If you purchased the non-touch version, set ESP_OPEN_TOUCH to 0 to disable the touch panel parameters.

#define ESP_PANEL_BOARD_TOUCH_CONTROLLER GT911
#define ESP_PANEL_BOARD_TOUCH_BUS_TYPE (ESP_PANEL_BUS_TYPE_I2C)

Define the touch controller as GT911 and the communication interface as I2C bus.

#define ESP_PANEL_BOARD_TOUCH_I2C_IO_SCL (9)
#define ESP_PANEL_BOARD_TOUCH_I2C_IO_SDA (8)
#define ESP_PANEL_BOARD_TOUCH_INT_IO (4)

Here we set the SCL, SDA, and interrupt pins for the touch.

Set backlight parameters

#define ESP_PANEL_BOARD_USE_BACKLIGHT (1)

Set ESP_PANEL_BOARD_USE_BACKLIGHT to 1 to enable backlight control, which will enable the configuration under #if ESP_PANEL_BOARD_USE_BACKLIGHT.

#define ESP_PANEL_BOARD_BACKLIGHT_TYPE (ESP_PANEL_BACKLIGHT_TYPE_SWITCH_EXPANDER)

#if (ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_SWITCH_GPIO) || \
(ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_SWITCH_EXPANDER) || \
(ESP_PANEL_BOARD_BACKLIGHT_TYPE == ESP_PANEL_BACKLIGHT_TYPE_PWM_LEDC)

#define ESP_PANEL_BOARD_BACKLIGHT_IO (2) // Output GPIO pin number
#define ESP_PANEL_BOARD_BACKLIGHT_ON_LEVEL (1) // Active level, 0: low, 1: high

#endif

Here the backlight type is set to be controlled by an I/O expander, and the control I/O pin is set to EXIO2.

#define ESP_PANEL_BOARD_BACKLIGHT_IDLE_OFF (0)

Set the backlight to be on after initialization.

Set I/O expander parameters

#define ESP_PANEL_BOARD_USE_EXPANDER (1)

Set the macro ESP_PANEL_BOARD_USE_EXPANDER to 1 to enable the I/O expander, which will enable the configuration under #if ESP_PANEL_BOARD_USE_EXPANDER.

#define ESP_PANEL_BOARD_EXPANDER_CHIP CH422G

Set the I/O expander chip name to CH422G.

#define ESP_PANEL_BOARD_EXPANDER_I2C_CLK_HZ (400 * 1000)
// Typically set to 400K
#define ESP_PANEL_BOARD_EXPANDER_I2C_SCL_PULLUP (1) // 0/1. Typically set to 1
#define ESP_PANEL_BOARD_EXPANDER_I2C_SDA_PULLUP (1) // 0/1. Typically set to 1
#define ESP_PANEL_BOARD_EXPANDER_I2C_IO_SCL (9)
#define ESP_PANEL_BOARD_EXPANDER_I2C_IO_SDA (8)

#define ESP_PANEL_BOARD_EXPANDER_I2C_ADDRESS (0x20)

Set the I2C communication parameters for the I/O expander: clock frequency, SDA and SCL pins, etc.

After configuring the above parameters, the program can initialize the screen and display.

2. Initializing LVGL​

Header files

#include <Arduino.h>
#include <esp_display_panel.hpp>
#include <esp_err.h>
#include <lvgl.h>
#include <demos/lv_demos.h>

#include "esp_lv_adapter_arduino.h"

using namespace esp_panel::drivers;
using namespace esp_panel::board;
  • This includes Arduino, ESP32_Display_Panel, LVGL, and the LVGL demo components, as well as the esp_lv_adapter_arduino.h adapter in the example directory.

  • using namespace: simplifies the syntax so we can write Board directly instead of esp_panel::board::Board.

    What is the esp_lv_adapter_arduino.h adapter?

    This file is the Arduino adapter in the example directory. It registers the display and touch input devices and provides LVGL initialization, task startup, mutex locking, and unlocking interfaces:

    • esp_lv_adapter_init(): Initializes LVGL, the timer, and the mutex.
    • esp_lv_adapter_register_display(): Registers the display device.
    • esp_lv_adapter_register_touch(): Registers the touch input device.
    • esp_lv_adapter_start(): Starts the LVGL task.

    This example no longer uses lvgl_v8_port.h, lvgl_port_init(), or lvgl_port_lock().

Initialize the development board

Serial.begin(115200);
Serial.println("LVGL v8 demo start");

Board *board = new Board();
if ((board == nullptr) || !board->init()) {
Serial.println("Board init failed");
while (true) {
delay(1000);
}
}

Initializes the serial port and development board. If board initialization fails, the program prints an error message and remains in the loop.

Configure the RGB display buffer

const esp_lv_adapter_rotation_t rotation = ESP_LV_ADAPTER_ROTATE_0;
const esp_lv_adapter_tear_avoid_mode_t tear_mode = ESP_LV_ADAPTER_TEAR_AVOID_MODE_DEFAULT_RGB;
const uint8_t frame_buffer_count = esp_lv_adapter_get_required_frame_buffer_count(tear_mode, rotation);

LCD *lcd = board->getLCD();
if (lcd == nullptr) {
Serial.println("LCD device is not available");
while (true) {
delay(1000);
}
}
auto *lcd_bus = lcd->getBus();
if (lcd_bus->getBasicAttributes().type == ESP_PANEL_BUS_TYPE_RGB) {
lcd->configFrameBufferNumber(frame_buffer_count);
static_cast<BusRGB *>(lcd_bus)->configRGB_BounceBufferSize(lcd->getFrameWidth() * 10);
}

assert(board->begin());

For the RGB bus, the example calculates the frame buffer count from the tearing-avoidance mode and rotation, then configures the RGB bounce buffer. board->begin() starts the display and touch devices on the development board.

Register the LVGL display and touch input

esp_lv_adapter_config_t adapter_config = ESP_LV_ADAPTER_DEFAULT_CONFIG();
adapter_config.task_stack_size = 12 * 1024;
adapter_config.task_priority = 2;
adapter_config.task_core_id = ARDUINO_RUNNING_CORE;
ESP_ERROR_CHECK(esp_lv_adapter_init(&adapter_config));

esp_lv_adapter_display_config_t disp_config = ESP_LV_ADAPTER_DISPLAY_RGB_DEFAULT_CONFIG(
lcd, lcd->getFrameWidth(), lcd->getFrameHeight(), rotation
);
disp_config.profile.use_psram = true;

lv_display_t *disp = esp_lv_adapter_register_display(&disp_config);
assert(disp != nullptr);

if (board->getTouch() != nullptr) {
esp_lv_adapter_touch_config_t touch_config = ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(disp, board->getTouch());
lv_indev_t *touch = esp_lv_adapter_register_touch(&touch_config);
assert(touch != nullptr);
}

esp_lv_adapter_init() initializes the LVGL adapter. The display configuration then registers the LCD. If the board has a touch device, the code also registers the touch input device. The touch registration code is skipped for versions without touch.

Start the LVGL task and create the interface

ESP_ERROR_CHECK(esp_lv_adapter_start());

ESP_ERROR_CHECK(esp_lv_adapter_lock(-1));
lv_demo_widgets();
esp_lv_adapter_unlock();

esp_lv_adapter_start() starts the LVGL task. LVGL is not thread-safe, so call esp_lv_adapter_lock(-1) before creating the interface; -1 means to wait continuously until the lock is acquired. lv_demo_widgets() creates the official Widgets example, and esp_lv_adapter_unlock() releases the lock after creation.


LVGL v9 Porting​

This section uses the LVGL v9.5.0 example from the example package. It drives the display and touch panel through the ESP32_Display_Panel library and displays the LVGL Widgets example.

Hardware Connection​

The USB connection is the same as above. Use a Type-C to Type-A cable to connect the USB port of the ESP32-S3-Touch-LCD-7 to the computer's USB port.

Example Code​

Please download the example package from the following address: ESP32-S3-Touch-LCD-7 Example (if already downloaded, simply open the corresponding folder). After downloading or cloning the repository, open the corresponding examples/Arduino/examples/10_lvgl_v9_demo folder.

In the Arduino IDE, double-click 10_lvgl_v9_demo.ino, then select the serial port and board model Waveshare ESP32-S3-Touch-LCD-7.

Set the corresponding board parameters, click the Upload button, and wait for the upload to complete.

Running Results​

Power cycle the screen, and you will see the LVGL v9.5.0 Widgets example displayed on the screen. For the version with a touch panel, slide on the screen to test the touch function.

ESP32-S3-Touch-LCD-7 LVGL v9.5.0 example result