Learning ESP-DL Series 04- LVGL, IDF, and ESP-DL Integration 2025
IDF v5.4 & LVGL v9.2 & ESP-DL Integration (2025)
Introduction
This is the final post in my ESP-DL series.
My goal is to create a simple LVGL application that utilizes the esp-dl
library for digit recognition.
In this blog, I will clearly explain how I implemented the integration and share key lessons learned.
Project Core Values
- For learning purposes.
- The implementation is kept simple and straightforward.
- No fancy stuff, make it work.
Application Features
This application allows the user to handwrite a digit on the screen. The device then predicts the digit using the ESP-DL library.
The Hard Part
Previously, I created a sketchpad project using the Arduino framework and PlatformIO:
https://github.com/tommokmok/esp32s3_YetAnotherSketchpad
However, ESP-DL requires a higher version of ESP-IDF, so I needed to port the LVGL code to an ESP-IDF-based framework (not PlatformIO).
There are very few examples of using ESP-DL with the Arduino framework, so the first step was learning how to implement LVGL in ESP-IDF, then integrating it with the ESP-DL digit recognition example.
Porting LVGL to ESP-IDF
Hardware specs:
- ESP32-S3 dev board + 2.8” TFT LCD
(Purchased from Taobao. More info: ESP32-LVGL开发板)Note: This dev board is not recommended due to hardware issues. It may reset automatically, especially when connected to a PC.
- ESP32-S3-N8R8 (8MB external RAM and 8MB external SPI flash)
- LCD Driver: ST7789, 320 x 240 pixels (SPI interface)
- Touch Driver: XPT2046 (SPI interface)
After researching, I found three possible approaches for porting LVGL to ESP-IDF:
Espressif’s official LVGL port:
https://components.espressif.com/components/espressif/esp_lvgl_port/versions/2.6.0/readme- Up-to-date library with example code.
- Good starting point.
LVGL team’s porting example:
https://github.com/lvgl/lv_port_esp32/tree/master- Outdated (LVGL v7, ESP-IDF v4).
- Not recommended for latest ESP-IDF, but useful as a reference.
ESP-IDF example:
https://github.com/espressif/esp-idf/tree/v5.5.1/examples/peripherals/lcd/spi_lcd_touch/main- Up-to-date code.
- Less functionality, simpler than using
esp_lvgl_port
.
After careful consideration, I chose option 1 for easier porting to the latest LVGL and ESP-IDF versions.
Based on my previous sketchpad project, I used LVGL v9.2.2
and IDF v5.4.2
.
Porting LVGL v9.2.2 to Current Hardware
Prerequisites
- VS Code with the Espressif ESP-IDF extension and
IDF v5.4.2
installed.
The porting process was straightforward, and adding the touch driver did not take much time.
Source code:
https://github.com/tommokmok/esp32s3_lvgl_idf
However, I spent some time manually adding calibration code for the touch point positions. For details, please check the repository above.
Integrating LVGL with ESP-DL Example Code
This was the most challenging and time-consuming part.
Key Issues Encountered
- Incorrect
sdkconfig
settings caused ESP32 to hang:- When the canvas size is too large (e.g., 320x240), LVGL cannot allocate enough memory.
- Solution: Set
CONFIG_LV_USE_CLIB_MALLOC=y
. By default, ESP32-S3 uses external PSRAM for allocations >4KB.
Lessons Learned
- Enable LVGL logging for development:
Without logging, debugging is very difficult because ESP32-S3 may hang without any UART output.
1 | CONFIG_LV_USE_LOG=y |
- In VS Code, configure ESP-IDF to avoid deleting
managed_components
during a Full Clean:
This prevents unnecessary re-downloads and speeds up development.
- Color format consistency:
The color format set on the LCD driver, LCD display, and LVGL must match. Otherwise, colors will be displayed incorrectly.
1 | // Color set on the driver |
Test Video
Watch the demo:
https://youtube.com/shorts/B73eYAXCKzQ?feature=share
As shown in the video, the accuracy is not ideal, especially for digits 3
, 9
, and 8
.
This leads to the next step: improving the project. The first thing to try is increasing the input size—30x25 pixels is too small for handwritten digits.
Conclusion
Source code:
https://github.com/tommokmok/esp32s3_lvgl_digit_recongnition
This is not the final version, but just a starting point.
Looking back, it seems like a lot of work, but in reality, it was very little outcome which still not perfect.
It’s similar to an RPG game: before completing the main quest, you need to finish several mini-tasks.
You can’t do it in just one big leap.
It’s time-consuming, but I enjoy the process—especially when things finally work.
Let’s see how far I can go with these little steps.