Полное руководство: Программирование ESP32 CYD (Cheap Yellow Display) с помощью VS Code и PlatformIO.
Introduction to ESP32 CYD Development
Он ESP32 CYD (Cheap Yellow Display) represents a breakthrough in affordable embedded systems development, combining the powerful ESP32 microcontroller with an integrated 2.8-inch TFT touchscreen. This all-in-one solution eliminates the need for complex wiring between separate components, making it ideal for IoT dashboards, smart home controllers, wearable devices, and industrial HMIs. While many tutorials focus on the Arduino IDE for ESP32 CYD development, this comprehensive guide explores a more professional approach using Visual Studio Code with PlatformIO, offering superior code management, debugging capabilities, and library handling.
This tutorial not only covers basic setup but also dives deep into configuring the essential libraries—TFT_eSPI, XPT2046_Touchscreen, and LVGL—that transform this budget-friendly board into a capable interactive display platform. Whether you’re building a weather station interface, a retro gaming console, or a custom control panel, mastering VS Code with the ESP32 CYD will significantly accelerate your development workflow and project sophistication.

Prerequisites for ESP32 CYD Development
Before diving into the programming process, ensure you have the following components and knowledge:
Software Requirements:
-
Visual Studio Code (latest stable version)
-
PlatformIO IDE extension for VS Code
-
Basic familiarity with C/C++ programming
-
Git (for library management)
Hardware Requirements:
-
ESP32 CYD board (ESP32-2432S028R) or compatible variant
-
USB-C cable for programming and power
-
Computer with available USB port
Prior Experience:
-
Базовый ESP32 programming concepts
-
Understanding of SPI communication protocol
-
Previous experience with Arduino IDE (helpful but not mandatory)
-
Familiarity with library management in embedded development
Примечание: This guide also applies if you’re using a standard ESP32 development board with a separate 2.8-inch ILI9341 240×320 TFT LCD touchscreen. The configuration steps remain largely identical, with only minor pin assignment differences.
Setting Up VS Code and PlatformIO
Installation Process
-
Download and Install VS Code: Visit the official Visual Studio Code website and download the appropriate version for your operating system (Windows, macOS, or Linux). Follow the standard installation procedure.
-
Install PlatformIO Extension:
-
Open VS Code and navigate to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X on macOS)
-
Search for “PlatformIO IDE”
-
Click “Install” on the official PlatformIO extension by PlatformIO
-
Wait for the installation to complete (this may take several minutes as PlatformIO downloads necessary toolchains)
-
-
Initial PlatformIO Configuration:
-
After installation, you’ll see the PlatformIO icon (an alien head) in the VS Code activity bar
-
Click this icon to open the PlatformIO Home screen
-
PlatformIO will automatically set up the ESP32 toolchain on first launch
-
Creating Your First ESP32 CYD Project
-
From PlatformIO Home, select “New Project”
-
Name your project (e.g., “ESP32_CYD_Test”)
-
Select “Espressif ESP32” as the board
-
Choose “ESP32 Dev Module” as the specific board (the CYD uses a standard ESP32)
-
Select “Arduino” as the framework
-
Choose your project location and click “Finish”
PlatformIO will create a project structure with a src folder (for your code) and a critical platformio.ini file (for project configuration). This initialization process demonstrates the professional workflow advantage of PlatformIO over Arduino IDE, with proper project separation and dependency management.
Installing Essential Libraries for ESP32 CYD
Understanding Library Dependencies
Он ESP32 CYD requires three core libraries for full functionality:
-
TFT_eSPI: Handles display graphics and text rendering
-
XPT2046_Сенсорный экран: Manages touch input from the resistive touch layer
-
LVGL (optional but recommended): Provides advanced graphical user interface elements
Installing XPT2046_Touchscreen Library
Unlike the Arduino IDE where libraries can be installed via the Library Manager, PlatformIO requires a different approach for the XPT2046_Touchscreen library due to known compatibility issues:
-
Open your project’s
platformio.inifile -
Add the following line under the
[env:esp32dev]section (or your environment name):
lib_deps = https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
-
Save the file. PlatformIO will automatically download and install this library from GitHub on the next build.
Expert Tip: Adding libraries via GitHub URLs ensures you get the latest version directly from the source, which is particularly important for frequently updated libraries like XPT2046_Touchscreen. This method also provides better version control than the PlatformIO library registry for this specific library.
Installing TFT_eSPI Library
The TFT_eSPI library can be installed through PlatformIO’s Library Manager:
-
Click the PlatformIO icon in the activity bar
-
Select “Libraries” from the PlatformIO menu
-
Search for “TFT_eSPI” in the search bar
-
Find the library by Bodmer (the official version)
-
Click “Add to Project” and select your current ESP32 CYD project
Alternatively, you can add it directly to your platformio.ini file:
lib_deps = https://github.com/PaulStoffregen/XPT2046_Touchscreen.git bodmer/TFT_eSPI@^2.5.43
The version specification (@^2.5.43) ensures compatibility while allowing minor updates. After adding, your platformio.ini should also include these essential settings for proper serial monitoring:
monitor_speed = 115200 upload_speed = 921600 board_build.flash_mode = dio
Configuring the TFT_eSPI Library for ESP32 CYD
The Critical User_Setup.h File
Он TFT_eSPI library requires specific configuration for each display type through a User_Setup.h file. Generic configurations available online often won’t work correctly with the ESP32 CYD, leading to display issues, incorrect colors, or touch calibration problems.
Step-by-Step Configuration Process
-
Locate the TFT_eSPI library in your project:
-
In VS Code’s Explorer panel, navigate to:
.pio/libdeps/esp32dev/TFT_eSPI -
Он
esp32devportion may vary based on your board selection during project creation
-
-
Find and open User_Setup.h:
-
Within the TFT_eSPI folder, locate
User_Setup.h -
This file contains numerous configuration options for different displays
-
-
Replace with ESP32 CYD specific configuration:
-
Download the pre-configured
User_Setup.hfile specifically tested for ESP32 CYD -
Completely replace the contents of the existing
User_Setup.hwith the downloaded version -
Save the file
-
-
Key Configuration Details:
The correctUser_Setup.hfor ESP32 CYD should include these essential definitions:
#определять ILI9341_DRIVER #определять TFT_WIDTH 240 #определять TFT_HEIGHT 320 #определять TFT_MISO 39 #определять TFT_MOSI 32 #определять TFT_SCLK 25 #определять TFT_CS 33 #определять TFT_DC 15 #определять TFT_RST 32 #определять TOUCH_CS 33 #определять LOAD_GLCD #определять LOAD_FONT2 #определять SPI_FREQUENCY 40000000 #определять SPI_TOUCH_FREQUENCY 2500000
Critical Note: Using an incorrect
User_Setup.hfile is the most common source of problems when working with TFT displays on ESP32. The configuration must match exactly the pin assignments and display driver of your specific hardware. Random Nerd Tutorials provides a tested configuration that accounts for the ESP32 CYD’s unique pin mapping and ILI9341 display controller characteristics.
Testing Display and Touchscreen Functionality
Complete Test Sketch
After installing and configuring the libraries, verify everything works correctly with this comprehensive test code:
#включать <SPI.h> #включать <TFT_eSPI.h> #включать <XPT2046_Touchscreen.h> TFT_eSPI tft = TFT_eSPI(); // ESP32 CYD touchscreen pin definitions #определять XPT2046_IRQ 36 // T_IRQ #определять XPT2046_MOSI 32 // T_DIN #определять XPT2046_MISO 39 // T_OUT #определять XPT2046_CLK 25 // T_CLK #определять XPT2046_CS 33 // T_CS Сенсорный экран SPIClass SPI = SPIClass(ВСПИ); XPT2046_Сенсорный экран сенсорный экран(XPT2046_CS, XPT2046_IRQ); #определять ШИРИНА_ЭКРАНА 320 #определять ВЫСОТА_ЭКРАНА 240 #определять FONT_SIZE 2 пустота настраивать() { Серийный номер.начинать(115200); // Initialize touchscreen SPI сенсорный экранSPI.начинать(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); сенсорный экран.начинать(сенсорный экранSPI); сенсорный экран.setRotation(1); // Горизонтальный режим // Инициализация дисплея тфт.инициализация(); тфт.setRotation(1); тфт.fillScreen(TFT_BLACK); тфт.setTextColor(TFT_WHITE, TFT_BLACK); // Display welcome message тфт.drawCentreString("ESP32 CYD Ready", ШИРИНА_ЭКРАНА/2, 50, FONT_SIZE); тфт.drawCentreString("Touch to Test", ШИРИНА_ЭКРАНА/2, 100, FONT_SIZE); тфт.drawCentreString("Check Serial Monitor", ШИРИНА_ЭКРАНА/2, 150, FONT_SIZE); Серийный номер.println("ESP32 CYD Test Initialized"); } пустота петля() { если (сенсорный экран.tirqTouched() && сенсорный экран.тронут()) { TS_Point p = сенсорный экран.получить точку(); // Calibrate raw touch coordinates to screen dimensions инт x = карта(p.x, 200, 3700, 1, ШИРИНА_ЭКРАНА); инт y = карта(p.y, 240, 3800, 1, ВЫСОТА_ЭКРАНА); инт z = p.z; // Display touch coordinates тфт.fillRect(0, 180, ШИРИНА_ЭКРАНА, 60, TFT_BLACK); тфт.drawCentreString("X: " + Нить(x), ШИРИНА_ЭКРАНА/2, 180, FONT_SIZE); тфт.drawCentreString("Y: " + Нить(y), ШИРИНА_ЭКРАНА/2, 200, FONT_SIZE); тфт.drawCentreString("Pressure: " + Нить(z), ШИРИНА_ЭКРАНА/2, 220, FONT_SIZE); // Print to serial monitor Серийный номер.printf("Touch - X: %d, Y: %d, Pressure: %d\n", x, y, z); задерживать(200); // Debounce delay } }
Upload and Verification Process
-
Создайте проект: Click the checkmark icon in the blue bottom status bar (or press Ctrl+Alt+B) to compile the code
-
Upload to ESP32 CYD: Click the right-arrow icon (or press Ctrl+Alt+U) to upload the compiled code
-
Открытый последовательный монитор: Click the plug icon (or press Ctrl+Alt+S) to open the serial monitor at 115200 baud
-
Expected Results:
-
The display should show a welcome message
-
Touching the screen should display coordinates on both the display and serial monitor
-
The touch pressure value should increase when pressing harder
-
Устранение распространенных проблем
| Проблема | Possible Cause | Решение |
|---|---|---|
| Blank or white screen | Incorrect User_Setup.h | Verify User_Setup.h matches ESP32 CYD exactly |
| Touch coordinates incorrect | Calibration values off | Adjust map() function parameters in test code |
| Display colors distorted | Wrong color mode setting | Ensure TFT_RGB_ORDER is correctly set in User_Setup.h |
| SPI conflicts | Multiple SPI devices | Ensure proper CS pin selection and SPI bus separation |
Installing and Configuring LVGL for Advanced GUIs
Why LVGL for ESP32 CYD?
LVGL (Light and Versatile Graphics Library) is a professional open-source embedded graphics library that enables sophisticated user interfaces on microcontrollers. While the TFT_eSPI library handles basic drawing functions, LVGL provides:
-
Advanced widgets (buttons, sliders, charts, lists)
-
Animations and transitions
-
Multi-language support
-
Memory-efficient rendering
-
Touch gesture recognition
For projects requiring more than basic text and shapes, LVGL transforms the ESP32 CYD into a capable platform for modern GUI applications.
Installation Process
-
Add LVGL to PlatformIO Project:
-
Open PlatformIO Libraries (PIO Home → Libraries)
-
Search for “lvgl”
-
Select version 9.x (latest stable)
-
Click “Add to Project” and select your ESP32 CYD project
-
-
Create lv_conf.h Configuration File:
-
In your project’s root directory, create a new file named
lv_conf.h -
Copy the LVGL configuration template specifically designed for ESP32 CYD:
-
#ifndef LV_CONF_H #определять LV_CONF_H #определять LV_MEM_SIZE (32 * 1024) // Increased memory for ESP32 #определять LV_HOR_RES_MAX 320 #определять LV_VER_RES_MAX 240 #определять LV_COLOR_DEPTH 16 #определять LV_USE_GPU_STM32_DMA2D 0 #определять LV_USE_LOG 1 #определять LV_LOG_PRINTF 1 #определять LV_USE_ASSERT_NULL 1 #определять LV_USE_ASSERT_MEM 1 #определять LV_USE_ASSERT_OBJ 1 #определять LV_USE_USER_DATA 1 // Enable required widgets #определять LV_USE_LABEL 1 #определять LV_USE_BUTTON 1 #определять LV_USE_BUTTONMATRIX 1 #определять LV_USE_CHECKBOX 1 #определять LV_USE_SLIDER 1 #определять LV_USE_DROPDOWN 1 // Add other widgets as needed #endif /*LV_CONF_H*/
-
Update platformio.ini: Ensure your configuration includes sufficient memory allocation:
board_build.partitions = huge_app.csv build_flags = -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue lib_ldf_mode = deep+
LVGL Initialization Code
Integrate LVGL with your existing TFT_eSPI and touchscreen setup:
#включать <lvgl.h> #включать <TFT_eSPI.h> #включать <XPT2046_Touchscreen.h> TFT_eSPI tft = TFT_eSPI(); XPT2046_Сенсорный экран сенсорный экран(XPT2046_CS, XPT2046_IRQ); static lv_disp_draw_buf_t draw_buf; static lv_color_t buf[ШИРИНА_ЭКРАНА * ВЫСОТА_ЭКРАНА / 10]; пустота my_disp_flush(lv_disp_drv_t *disp, константа lv_area_t *area, lv_color_t *color_p) { uint32_t w = (area->x2 - area->x1 + 1); uint32_t h = (area->y2 - area->y1 + 1); тфт.startWrite(); тфт.setAddrWindow(area->x1, area->y1, w, h); тфт.pushColors((uint16_t *)&color_p->full, w * h, истинный); тфт.endWrite(); lv_disp_flush_ready(disp); } пустота touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *данные) { если (сенсорный экран.тронут()) { TS_Point p = сенсорный экран.получить точку(); данные->точка.x = карта(p.x, 200, 3700, 0, ШИРИНА_ЭКРАНА); данные->точка.y = карта(p.y, 240, 3800, 0, ВЫСОТА_ЭКРАНА); данные->состояние = LV_INDEV_STATE_PR; } еще { данные->состояние = LV_INDEV_STATE_REL; } } пустота настраивать() { Серийный номер.начинать(115200); // Инициализация дисплея тфт.инициализация(); тфт.setRotation(1); // Инициализация сенсорного экрана сенсорный экран.начинать(); // Initialize LVGL lv_init(); lv_disp_draw_buf_init(&draw_buf, buf, NULL, ШИРИНА_ЭКРАНА * ВЫСОТА_ЭКРАНА / 10); // Initialize display driver static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.hor_res = ШИРИНА_ЭКРАНА; disp_drv.ver_res = ВЫСОТА_ЭКРАНА; disp_drv.flush_cb = my_disp_flush; disp_drv.draw_buf = &draw_buf; lv_disp_drv_register(&disp_drv); // Initialize input device driver static lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = touchpad_read; lv_indev_drv_register(&indev_drv); // Create a simple button as test lv_obj_t *btn = lv_btn_create(lv_scr_act()); lv_obj_set_size(btn, 100, 50); lv_obj_center(btn); lv_obj_t *label = lv_label_create(btn); lv_label_set_text(label, "Click Me!"); lv_obj_center(label); Серийный номер.println("LVGL Initialized with ESP32 CYD"); } пустота петля() { lv_timer_handler(); задерживать(5); }
Building a Complete ESP32 CYD Project
Sample Application: IoT Dashboard
Combine all learned elements into a practical IoT dashboard example:
// ESP32 CYD IoT Dashboard // Displays sensor data with LVGL widgets #включать <lvgl.h> #включать <TFT_eSPI.h> #включать <XPT2046_Touchscreen.h> #включать <WiFi.h> #включать <HTTPClient.h> // Display and touch objects TFT_eSPI tft; XPT2046_Сенсорный экран сенсорный экран(XPT2046_CS, XPT2046_IRQ); // LVGL objects lv_obj_t *temperatureLabel; lv_obj_t *humidityLabel; lv_obj_t *pressureLabel; lv_obj_t *chart; lv_chart_series_t *tempSeries; // WiFi credentials константа чар* SSID = "YOUR_SSID"; константа чар* пароль = "YOUR_PASSWORD"; // Weather API константа String apiKey = "YOUR_API_KEY"; константа String city = "London"; пустота updateWeatherData() { если (Wi-Fi.статус() == WL_CONNECTED) { HTTPClient http; String url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&appid=" + apiKey + "&units=metric"; http.начинать(url); инт httpCode = http.GET(); если (httpCode == 200) { String payload = http.getString(); // Parse JSON response (simplified) плавать temperature = 22.5; // Extract from JSON плавать влажность = 65; // Extract from JSON плавать pressure = 1013; // Extract from JSON // Update LVGL labels lv_label_set_text_fmt(temperatureLabel, "Temp: %.1f°C", temperature); lv_label_set_text_fmt(humidityLabel, "Humidity: %.0f%%", влажность); lv_label_set_text_fmt(pressureLabel, "Pressure: %.0fhPa", pressure); // Update chart lv_chart_set_next_value(chart, tempSeries, temperature); } http.конец(); } } пустота настраивать() { Серийный номер.начинать(115200); // Инициализация дисплея тфт.инициализация(); тфт.setRotation(1); // Инициализация сенсорного экрана сенсорный экран.начинать(); // Initialize LVGL lv_init(); // ... LVGL initialization code from previous section // Connect to WiFi Wi-Fi.начинать(SSID, пароль); пока (Wi-Fi.статус() != WL_CONNECTED) { задерживать(1000); Серийный номер.println("Connecting to WiFi..."); } Серийный номер.println("WiFi connected"); // Create UI lv_obj_t *scr = lv_scr_act(); // Title lv_obj_t *title = lv_label_create(scr); lv_label_set_text(title, "ESP32 CYD Weather Dashboard"); lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 10); // Data labels temperatureLabel = lv_label_create(scr); lv_label_set_text(temperatureLabel, "Temp: -- °C"); lv_obj_align(temperatureLabel, LV_ALIGN_LEFT_MID, 20, -40); humidityLabel = lv_label_create(scr); lv_label_set_text(humidityLabel, "Humidity: --%"); lv_obj_align(humidityLabel, LV_ALIGN_LEFT_MID, 20, -10); pressureLabel = lv_label_create(scr); lv_label_set_text(pressureLabel, "Pressure: -- hPa"); lv_obj_align(pressureLabel, LV_ALIGN_LEFT_MID, 20, 20); // Chart chart = lv_chart_create(scr); lv_obj_set_size(chart, 150, 100); lv_obj_align(chart, LV_ALIGN_RIGHT_MID, -20, 0); lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 40); lv_chart_set_point_count(chart, 20); tempSeries = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); // Update button lv_obj_t *btn = lv_btn_create(scr); lv_obj_set_size(btn, 100, 40); lv_obj_align(btn, LV_ALIGN_BOTTOM_MID, 0, -20); lv_obj_t *btnLabel = lv_label_create(btn); lv_label_set_text(btnLabel, "Update"); lv_obj_center(btnLabel); // Button event lv_obj_add_event_cb(btn, [](lv_event_t *e) { updateWeatherData(); }, LV_EVENT_CLICKED, NULL); // Initial data update updateWeatherData(); } пустота петля() { lv_timer_handler(); // Auto-update every 30 seconds static без подписи длинный lastUpdate = 0; если (миллис() - lastUpdate > 30000) { updateWeatherData(); lastUpdate = миллис(); } задерживать(5); }
Advanced Tips and Best Practices
Optimizing Performance
-
Use PSRAM Effectively: The ESP32 CYD includes 8MB of PSRAM. Enable it in
platformio.ini:board_build.partitions = huge_app.csv build_flags = -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
-
LVGL Memory Optimization:
-
Adjust
LV_MEM_SIZEвlv_conf.hbased on your widget complexity -
Использовать
lv_disp_set_draw_buffers()for double buffering -
Enable compression for images:
#define LV_USE_IMG_COMPRESSED 1
-
-
Display Refresh Optimization:
-
Set appropriate SPI frequency (40MHz works well for ESP32 CYD)
-
Использовать
tft.setSwapBytes(true)for correct color order -
Implement partial updates where possible instead of full screen refreshes
-
Troubleshooting Advanced Issues
| Advanced Issue | Diagnosis Method | Решение |
|---|---|---|
| LVGL lag or slow response | Monitor frame rate with lv_refr_get_fps_avg() |
Reduce widget count, optimize drawing callbacks, increase LVGL tick rate |
| Memory fragmentation | Monitor heap with ESP.getFreeHeap() |
Use PSRAM for buffers, implement memory pooling for frequently created/destroyed objects |
| SPI conflicts with other peripherals | Check SPI bus usage conflicts | Use different SPI buses (HSPI/VSPI) for display vs other sensors |
| Touch calibration drift | Log raw touch values over time | Implement dynamic calibration, store calibration data in NVS |
Version Management Best Practices
-
Library Version Pinning: Always specify library versions in
platformio.inito ensure consistent builds:lib_deps = bodmer/TFT_eSPI@2.5.43 https://github.com/PaulStoffregen/XPT2046_Touchscreen.git#v1.4.0 lvgl/lvgl@9.2.0
-
Configuration File Management: Store your
User_Setup.hиlv_conf.hfiles in a version control system separate from the library installations. -
Project Templates: Create a baseline ESP32 CYD project with all configurations pre-set, then duplicate it for new projects rather than reconfiguring each time.
Conclusion and Further Resources
The ESP32 CYD, when combined with VS Code and PlatformIO, becomes a powerful development platform for interactive display applications. By following this comprehensive guide, you’ve established a professional development environment, configured all necessary libraries, and learned to create both basic and advanced applications with LVGL.
Key Takeaways:
-
VS Code with PlatformIO offers superior project management compared to Arduino IDE
-
Proper library configuration is critical—especially the
User_Setup.hfile for TFT_eSPI -
LVGL enables professional-grade user interfaces on the ESP32 CYD
-
Regular testing at each configuration step prevents compound issues
Next Steps to Expand Your ESP32 CYD Skills:
-
Explore LVGL Widgets: Experiment with advanced widgets like charts, meters, rollers, and text areas
-
Add External Sensors: Connect I2C or SPI sensors to create complete monitoring systems
-
Implement Power Saving: Use ESP32 deep sleep modes with display power management for battery-powered projects
-
Create Custom Themes: Design unique visual styles with LVGL’s theme system
-
Add Wireless Connectivity: Implement MQTT for IoT dashboards or Bluetooth for peripheral control
Дополнительные ресурсы:
With this foundation, you’re equipped to tackle increasingly complex projects with the ESP32 CYD. The combination of low-cost hardware and professional development tools democratizes advanced embedded display applications, enabling everything from home automation interfaces to portable diagnostic tools. As you continue developing, remember to share your projects with the community—each project contributes to the collective knowledge base that makes platforms like the ESP32 CYD so valuable to makers and engineers worldwide.
======================================
