Mastering the CYD: Your Ultimate Beginner’s Guide to the Cheap Yellow Display (ESP32-2432S028R) using Platform.io

Feb 8, 2025 | Smart home, Electronics

Device Device License Language Build GitHub Release

In many projects, you see the use of the ESP32 Cheap Yellow Display Board. This is a how-to guide on getting started with the ESP32 Cheap Yellow Display Board (ESP32-2432S028R) using the Platform.io framework in Visual Studio Code. The ESP32 Cheap Yellow Display Board (ESP32-2432S028R) is a development board that combines an ESP32 with a TFT touchscreen. This allows you to easily add a graphical user interface (GUI) to your IoT projects, instead of designing and creating a PCB or wiring your hardware setup first.

ESP32-2432S028R with touch test application

When working with a standalone TFT Touchscreen Display 2.8 inch with an ILI9341 or ST7789 driver, this guide can be a helpful starting point for your project.

The ESP32 Cheap Yellow Display Board – CYD (ESP32-2432S028R)

The ESP32-2432S028R is one of several options available from Yellow Display Boards, a popular choice among makers and hobbyists. The specific model used in this guide features a 2.8-inch TFT display with touch functionality, but other sizes are also available online, including 4.3″, 5.0″, and 7.0″ variants. These boards have gained recognition within the maker community as “Cheap Yellow Display” or CYD develop board, because of their affordability and versatility.

These boards are particularly convenient because they seamlessly integrate a TFT display with touch capabilities
and a popular developer microcontroller board, eliminating the need for manual wiring or creating a PCB. They have
proven to be extremely useful in my own projects and testing—thanks to their display and processing power, as well
as access to additional IO pins, which allows adding extra hardware as needed.

Next is shown the ESP32-2432S028R version 3 develop board

Back side

Front side

ESP32-2432S028R features

  • Dimensions
    • Module size 50.0×86.0mm
    • Product weight: approximately 50g
  • Connections
    • Serial
    • USB micro
    • USB-C (only on the v3)
  • Power
    • Operating Voltage: 5V
    • Power consumption: approximately 115mA
  • Microcontroller ESP-WROOM-32
    • Dual-core MCU, integrated WI-FI and Bluetooth functions
    • Frequency can reach 240MHz
    • 520KB SRAM, 448KB ROM, Flash size is 4MB
  • TFT display ILI9341(v1,v2) or ST7789(v3)
    • 2.8-inch color screen, support 16 BIT RGB 65K color display, display rich colors
    • 240X320 resolution
    • Backlight control circuit
  • Onboard peripherals
    • TF card interface for external storage
    • RGB LED
    • built-in LDR (light-dependent resistor)
    • Speaker interface
    • Extended IO

Where to buy?

There are several stores where you can buy the ESP32-2432S028R the most common is Aliexpress. (By using my link you support Kafkar)

Creating an example application with Platform.io

Create a new Platform.io project

To begin this project, we created a new empty Platform.io project in Visual Studio Code. Ensure that Visual Studio Code is installed with Platform.IO

For this guide, we named the project “ESP32-2432S028-Tutorial.” The board type selected was NodeMCU-32S, and the framework used was Arduino.


After pressing Finish, the project will be created. If the project is successfully created, you will find the file platform.ini in the root directory of the project folder. This file will contain the necessary environment settings.

[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino

Adding Libraries to the project

The next step is to add the needed libraries To control the TFT Display and the Touchscreen using SPI communication protocol, we have to add the following Liberarys:

TFT_eSPI created by Bodmer [https://github.com/Bodmer/TFT_eSPI]
This is a TFT library optimized for the Raspberry Pi Pico (RP2040), STM32, ESP8266 and ESP32 that supports different driver chips

XPT2046_Touchscreen created by Paul Stoffregen [https://github.com/PaulStoffregen/XPT2046_Touchscreen]
This is a Touchscreen Library for XPT2046 Touch Controller Chip.

Adding these libraries can be done using the Platform.io library import function or by adding these libraries direct to your platform.ini file

lib_deps = 
  bodmer/TFT_eSPI@^2.5.43
  https://github.com/PaulStoffregen/XPT2046_Touchscreen.git#v1.4

Configure TFT_eSPI

To control the TFT display, the TFT_eSPI library need to be configured correct to control the TFT screen and enable display functionality.
The TFT_eSPi library offers predefined user setups, but currently not support for the ESP32-2432S028R board. To address this, I have prepared specific setup files that can be used. Download these files on GitHub Setup_ESP32_2432S028R_ILI9341.h, Setup_ESP32_2432S028R_ST7789.h
Place the configuration files in the same folder as the main.cpp These files contain the correct IO ports configuration for the TFT display.
Depending on the version of the used ESP32-2432S028R development board, you have to select the correct configuration file. For v1 and v2 use Setup_ESP32_2432S028R_ILI9341.h For v3 use Setup_ESP32_2432S028R_ST7789.h See more details on Pinout ESP32 Cheap Yellow Display Board(CYD) ESP32-2432S028R
For this selection, you need to add the following lines to your platform.io and un-comment the one needed for your setup

build_flags =
  ;###############################################################
  ; TFT_eSPI library setting here (no need to edit library files):
  ;###############################################################
  -D USER_SETUP_LOADED=1 ;Set this settings as valid
  ;-include src/Setup_ESP32_2432S028R_ILI9341.h ;for version 1 and version 2
  -include src/Setup_ESP32_2432S028R_ST7789.h  ;for version 3

Add serial port speed to Platform.IO

The test application reports touch positions over the serial port at a speed of 11520 Baud. To monitor this data within Platform.IO, you need to set the same speed in the platform.ini file.

monitor_speed = 115200

Adding the test application

Final step is to add the application code to the project therefore you have to replace the main.cpp or copy the code from main.cpp to the main.cpp in your project.

Or you can download the complete project from GitHub: https://github.com/Kafkar/ESP32_2432S028R-tutorial

Now you can build and upload your application to your ESP32_2432S028R and test it.

After startup, it will show the Welcome screen with the Kafar.com logo.

ESP32-2432S028R start screen getting started tutorial

After touching the screen it will change to the touch test screen where you can test the touch function of the ESP32_2432S028R.

ESP32-2432S028R touch test screen getting started tutorial

Example Application Explained (main.cpp)

Includes

The application starts with including the needed liberaries. beside the TFT_eSPI.h and the XPT2046_Touchscreen.h needs also the generic SPI.h to be include. This liberary is used by the TFT_eSPI.h and the XPT2046_Touchscreen.h.

#include <Arduino.h>
#include <SPI.h>

// include the installed "TFT_eSPI" library by Bodmer to interface with the TFT Display - https://github.com/Bodmer/TFT_eSPI
#include <TFT_eSPI.h>

// include the installed the "XPT2046_Touchscreen" library by Paul Stoffregen to use the Touchscreen - https://github.com/PaulStoffregen/XPT2046_Touchscreen
#include <XPT2046_Touchscreen.h>

Instance TFT_eSPI

To use the TFT_eSPI in the application, it should be instantiated. This uses the configured setup file.

If you are not using the ESP32_2432S028R but another display, then you have to check in the setup file if the correct IO ports are used to connect to the display

// Create a instance of the TFT_eSPI class
TFT_eSPI tft = TFT_eSPI();

Instance XPT2046 touchscreen

To use the touchscreen function, the driver should be configured. Therefore, the IO ports used by the touchscreen have to be defined. See for more IO details the Pinout ESP32 Cheap Yellow Display Board(CYD) ESP32-2432S028R

// Set the pius of the xpt2046 touchscreen
#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

After the configuration, the driver has to be instantiated.

// Create a instance of the SPIClass and XPT2046_Touchscreen classes
SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

Global definitions and variables

The test program is using some global variable. IT start with the defines of the screen size and the font type to use.

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

The next set of variables are needed for transferring data between some functions.

// Global Variables
int posX;     // x position of the touch
int posY;     // y position of the touch
int pressure; // pressure of the touch

// Set X and Y coordinates for center of display
int centerX;
int centerY;

Also the Kafkar.com logo is global defined. a black white image of 1 bit with a size of 116 x 100 pixels. You can tis replace by your own image.

Smal Kafkar logo

There are online tools to transform your image to bytes.

const unsigned char bitmap_kafkar_logo[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    ...
    0x00, 0x00, 0x00, 0x0c, 0x00, 0xf0, 0x00, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0f, 0xff, 0xc0, 0x00, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

function logTouchData

The logTouchData function is triggered when the screen is touched. It sends the current measured position and pressure of the touch over the serial port. If the terminal port in Platform.IO is open, you will see the output.

void logTouchData(int posX, int posY, int pressure)
{
  Serial.print("X = ");
  Serial.print(posX);
  Serial.print(" | Y = ");
  Serial.print(posY);
  Serial.print(" | Pressure = ");
  Serial.print(pressure);
  Serial.println();
}

function displayTouchData

The function displayTouchData is triggered after a touch on the touchscreen. This function begins by clearing the screen. It then writes the touch position (X and Y coordinates) and pressure in the center of the screen. Additionally, it draws boxes as markers to help visualize whether the touch position matches the corresponding position on the screen. Finally, it places a dot at the pressed position, with the size of the dot proportional to the pressure level.

void displayTouchData(int posX, int posY, int pressure)
{
  // Clear TFT screen
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_BLACK, TFT_WHITE);

  // Draw text
  int textY = 100;
  String text = "X = " + String(posX) + "Y = " + String(posY);
  tft.drawCentreString(text, centerX, textY, FONT_SIZE);

  textY += 20;
  text = "Pressure = " + String(pressure);
  tft.drawCentreString(text, centerX, textY, FONT_SIZE);

  tft.drawCentreString("Kafkar.com", centerX, 200, FONT_SIZE);

  // Draw touch box
  tft.drawRect(20, 20, 280, 200, TFT_BLUE);

  tft.drawRect(50, 50, 10, 10, TFT_BLUE);
  tft.drawRect(260, 50, 10, 10, TFT_BLUE);
  tft.drawRect(50, 180, 10, 10, TFT_BLUE);
  tft.drawRect(260, 180, 10, 10, TFT_BLUE);

  tft.fillSmoothCircle(posX, posY, pressure/200, TFT_YELLOW);
}

Function Setup

This function should also be available in an Audino-based program. It will be triggered at the start of the application and used for initializing and configuring components during startup.

The first step is initializing the serial communication, which allows us to send data to a computer or other devices. We set the baud rate to 115200 for reliable high-speed communication.

void setup()
{
  Serial.begin(115200);

Next, we configure and start the touchscreen component. This involves initializing the SPI interface and setting up the touchscreen in landscape mode.

  // Start the touchscreen component and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);

  touchscreen.begin(touchscreenSPI);

  // Set the Touchscreen rotation in landscape mode
  touchscreen.setRotation(1);

Now, let’s initialize the TFT display. After initialization, the screen will be cleared and prepared for displaying content.

  // Start the tft display
  tft.init();

  // Set the TFT display rotation in landscape mode
  tft.setRotation(1);

  // Clear the screen and display a message
  tft.fillScreen(TFT_WHITE);
  tft.setTextColor(TFT_BLACK, TFT_WHITE);

  // Set X and Y coordinates for center of display
  centerX = SCREEN_WIDTH / 2;
  centerY = SCREEN_HEIGHT / 2;

With the display ready, we can now add some welcoming text to inform users about the functionality of the touchscreen.

  tft.drawCentreString("Hello, Kafkar.com!", centerX, 30, FONT_SIZE);
  tft.drawCentreString("Touchscreen to test", centerX, 200, FONT_SIZE);

Finally, we’ll add the Kafkar logo to the center of the screen.

  int x = (tft.width() - 116) / 2;
  int y = (tft.height() - 110) / 2;

  // Draw the Kafkar logo bitmap
  tft.drawBitmap(x, y, bitmap_kafkar_logo, 116, 100, TFT_BLACK);
}

Function Loop

Once the setup function is complete, it will automatically start the loop function. This behavior is predefined in the Arduino framework.

The loop continuously checks for two conditions: touchscreen.tirqTouched() and touchscreen.touched(). If both return true, it proceeds to capture the touchpoint’s position. Once a valid touch is detected, the system uses a mapping function to convert the raw touchscreen coordinates into screen-relative positions.

void loop()
{
  // Checks if Touchscreen is touched
  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
    posX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    posY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    pressure = p.z;

If there is a position and pressure detected, it will call the logTouchData and the displayTouchData.

    logTouchData(posX, posY, pressure);
    displayTouchData(posX, posY, pressure);

    delay(100);
  }
}