Flashing and configuration
From the zip to a running board, and the settings you will touch after the first boot.
You have a zip from the export dialog. This page takes it to a running board, on either PlatformIO or the Arduino IDE, and then covers the configuration you are most likely to have to touch afterwards: rotation, colour, touch calibration, the filesystem for images, and the handful of boards that need something extra.
Before you power anything. Check the wiring against your board's schematic, not just
against the preset. Board pinouts change between revisions, and a wrong backlight or reset pin
can damage a panel. The preset's verify note and the Configuration notes in the
generated README.md say what to look at.
What you need
- A toolchain. Either PlatformIO
(the VS Code extension or the CLI) or the
Arduino IDE. PlatformIO is
less work because
platformio.inicarries the board, the libraries and the build flags; the Arduino IDE needs a few files copied by hand. - The board core. ESP32 boards: Espressif's
esp32Arduino core (3.x for LVGL 9; the ESP32-P4 needs a recent one). STM32: the STM32duino core. RP2040 and RP2350: a Pico Arduino core. PlatformIO installs these itself from theplatformline. - A USB driver for the board's serial chip if Windows does not see a COM port - most cheap ESP32 boards use a CH340 or CP210x.
- A data-capable USB cable. Charge-only cables are the most common reason a board is never detected.
Route A: PlatformIO
- Unzip. Open the project folder (the one containing
platformio.ini) in VS Code with the PlatformIO extension, orcdinto it. - Plug the board in. If it has a BOOT button and is not detected for upload, hold BOOT while pressing RESET, then release BOOT.
- Build and upload:
The first run downloads the platform, the core and every library inpio run -t uploadlib_deps, which takes a few minutes. - If the project has image assets in
data/, upload the filesystem as well:pio run -t uploadfs - Open the monitor:
at 115200 baud. You should seepio device monitor<Name> starting..., any device probe results, andUI ready.
platformio.ini already sets monitor_speed, the partition scheme
(huge_app.csv on ESP32), the TFT_eSPI defines where that library is used, and
-DLV_CONF_INCLUDE_SIMPLE -I . so the generated lv_conf.h is the one LVGL
picks up. Nothing needs copying anywhere.
Route B: Arduino IDE
- Install the libraries. Open
LIBRARIES.md; for each entry in Install these, search for the quoted name in Sketch > Include Library > Manage Libraries and install it. Match the LVGL major version - 9.x or 8.3.x - to the one in the file's Versions table. - Place
lv_conf.h. Copy it into your Arduinolibraries/folder, next to thelvglfolder (not inside it). LVGL looks there by default. If you already have one from another project, replace it or merge; the generated file enables only the fonts and widgets this design uses. - Place the driver configuration. With TFT_eSPI, copy the generated
User_Setup.hoverlibraries/TFT_eSPI/User_Setup.h- that library is configured by a file inside itself. With LovyanGFX, GFX Library for Arduino or esp_lcd there is nothing to copy; the configuration is in the sketch folder. - Open the sketch. Double-click the
.ino. The IDE opens the whole folder, including theui/subfolder, as one sketch. - Choose the board under Tools > Board - the FQBN on the Board
tab, and the Board core line in
LIBRARIES.md, name it. Then the settings that matter:- Partition Scheme: Huge APP (3MB No OTA/1MB SPIFFS) on a 4 MB ESP32. LVGL builds are large, and this is what the asset budget assumes.
- PSRAM: enabled where the board has it; OPI PSRAM on an ESP32-S3 with an RGB panel, which will not allocate its framebuffer otherwise.
- Upload Speed: 921600 usually works; drop to 115200 if uploads fail.
- USB CDC On Boot: enabled on S3 and C3 boards that expose native USB, or the serial monitor stays silent.
- Upload, then open the serial monitor at 115200.
- Upload the images, if there are any - see below.
Uploading image assets
Images stored on the filesystem are flashed separately from the sketch. The symptom of
forgetting is every image drawing as an empty box, and ui_fs_init() printing a
warning per missing file on the serial monitor. data/README.md in the export lists
each file, the total against the partition, and the exact steps:
| Filesystem | PlatformIO | Arduino IDE |
|---|---|---|
| SPIFFS | pio run -t uploadfs | The ESP32 Sketch Data Upload plugin (Arduino IDE 1.x), Tools > ESP32 Sketch Data Upload. On IDE 2.x the maintained plugin uploads LittleFS instead - switch the filesystem in Assets > Filesystem to match. |
| LittleFS | pio run -t uploadfs | The arduino-littlefs-upload plugin, then Ctrl+Shift+P > Upload LittleFS to Pico/ESP8266/ESP32. |
| FFat | pio run -t uploadfs | A FAT upload plugin, or write the image with esptool.py write_flash. |
| SD card | Copy the files to the card's root | Copy the files to the card's root. |
Whichever tool you use, the files must sit in a folder named data/ next to the
.ino - which is where the export puts them - and Tools > Partition Scheme
must leave room for the filesystem.
First boot
A good boot prints the project name, then a line per device the hardware layer probed, then
UI ready, and the panel shows the first screen. If the screen is blank or wrong,
the serial output narrows it down fast:
- Nothing at all on serial - wrong port, wrong baud, or USB CDC not enabled on a native-USB board.
draw buffer allocation failed - lower DRAW_BUF_LINES- the buffer does not fit. Lower Buffer height in the export settings and re-export.- Boot loop with a backtrace - usually the same memory problem, or PSRAM configured in the sketch but disabled in the IDE.
UI readybut a white or black panel - the backlight pin or its active level, or the panel is not being initialised because the wrong library driver or bus is selected.- A device reported absent - wrong I2C address, wrong bus, missing pull-ups, or its reset line not wired (the CST816S needs one).
The troubleshooting page has the full symptom table.
Configuration after the first boot
Almost everything is a setting in the designer, and the right fix is to change it there and
re-export - the generated files are meant to be replaced, and ui_events.c survives.
The ones you are most likely to need:
| Symptom | Setting |
|---|---|
| The image is rotated or mirrored | Hardware > Display > Rotation. Touch follows the display rotation on capacitive controllers; resistive ones may then need the axis switches. |
| Colours are a negative | Hardware > Display > Invert. |
| Red and blue are swapped | Hardware > Display > Colour order, RGB or BGR. |
| Touch lands in the wrong place | Hardware > Touch: Swap X/Y, Invert X, Invert Y. Try Swap first if a horizontal drag moves vertically. |
| Touch is offset at the edges (resistive) | Hardware > Touch > Calibration: the raw minimum and maximum per axis. Print raw values from the serial monitor at each corner and enter them. |
| Flicker, tearing, noise on the panel | Lower the SPI clock on the Display tab, or shorten the wires. RGB panels: check the PSRAM speed and the pixel clock. |
| Backlight off, or on when it should be off | Hardware > Display > Backlight: the pin and its active level. |
| The board reboots as the UI starts | Export settings > Buffer height, lower. Or enable PSRAM in the IDE to match the project. |
| A sensor reads its initial value forever | It was not found at boot: check its address on the Devices tab and the bus pins on the Buses tab against the serial output. |
For a quick experiment you can edit lcd_pins.h directly - every one of these is a
#define there - but carry the change back into the designer before the next export
or it will be lost.
Board-specific notes
- Cheap Yellow Display (2432S028R). Touch is on its own SPI bus (VSPI), separate from the display's HSPI - the preset already says so. The GPIO 2, 12 and 15 strapping-pin warnings are expected. A capacitive variant (2432S028C, CST820) exists and has its own preset; on some of those, GPIO 21 is shared between touch INT and the backlight. Both presets add the CN1 connector (GPIO 27 SDA / 22 SCL) as an I2C bus, ready for a sensor.
- Sunton 4.3" and 7" RGB. PSRAM must be enabled - OPI, 80 MHz - or the framebuffer will not allocate. The two boards' RGB data pin orders differ; confirm against your revision.
- LilyGO T-Display-S3. GPIO 15 must be driven high to power the LCD; the generated sketch does it before anything else.
- LilyGO T-Display-S3 AMOLED. No backlight pin; brightness is a controller command.
- Waveshare ESP32-S3-Touch-LCD-4.3. Touch reset (EXIO1), backlight enable (EXIO2) and
panel reset (EXIO3) are behind a CH422G I/O expander on the I2C bus at GPIO 8/9. The preset
adds the bus and the expander, and the generated sketch brings them up before anything else
(
hw_init_early()), pulses both resets through the expander and switches the backlight on through it. EXIO4 (SD card chip select) and EXIO5 (USB select) are left at their defaults. If the panel stays dark, the serial monitor'sCH422G: not foundline is the first thing to look for - it means the I2C bus is not answering. - M5Stack Core2. The backlight and panel reset are controlled by the AXP192 power management chip over I2C. Initialise the PMIC (the M5Core2 library does it) before LVGL. The preset adds Port A (Grove, GPIO 32/33) as an I2C bus.
- WT32-SC01 / SC01 Plus. MISO is not broken out on the SC01 (leave it at -1); CS is tied low on the Plus (leave it at -1).
- ESP32-S3 round GC9A01 with CST816S. The touch controller's RESET must be wired or it will not answer on I2C.
- Raspberry Pi Pico. 264 KB of RAM: keep the draw buffer at roughly a tenth of the screen (the preset's buffer height already does).
- STM32. Needs the STM32duino core; SPI pins are remappable per variant and LTDC pins are fixed per package - confirm against the datasheet.
Re-exporting
Change the design, export again, unzip over the old folder. Everything is replaced except
ui/ui_events.c; if the new export declares a new Call function stub, add its body to
your existing file from the fresh ui_events.h. A changed LVGL version also means
re-installing the matching library and re-uploading any image assets, whose binary format differs
between 8 and 9.