ESP32 CYD Touchscreen Button: Build an On/Off Control for Your IoT Projects

Want to add a simple, tactile touch control to your next IoT project without complex wiring? The ESP32 Cheap Yellow Display (CYD) makes it incredibly easy. In this project, you’ll build a working touchscreen on/off button that controls the board’s built-in RGB LED—a perfect foundation for controlling lights, motors, or any other output in your smart home or automation projects.

Why Build a Touchscreen Button on the ESP32 CYD?

The ESP32-2432S028R (Cheap Yellow Display) combines a powerful ESP32 chip with a 2.8-inch TFT touchscreen, all on one board. Creating a touchscreen button teaches you core concepts you can reuse in any GUI project:

  • Direct hardware control – Turn outputs on/off with a finger tap

  • Visual feedback – Buttons change color to show state

  • Touch coordinate mapping – Understand how screen touches translate to actions

  • Modular code – Easy to adapt for multiple buttons or different outputs

This project is your first step toward building smart home dashboards, industrial controls, or interactive displays.

What You’ll Need

Hardware

Software & Libraries

You’ll need these Arduino libraries:

  • TFT_eSPI by Bodmer – Display driver

  • XPT2046_Touchscreen by Paul Stoffregen – Touch driver

New to the CYD? First follow our ESP32 CYD Getting Started Guide to set up your board and configure the required User_Setup.h file. The code below won’t compile without the proper configuration.

Project Overview: How the On/Off Button Works

The finished project displays a single button that toggles between ON (green) and OFF (red) states. Tapping the green area turns the LED on; tapping the red area turns it off. The button provides clear visual feedback by changing color and the text label.

What you’ll learn:

  • Drawing interactive touch zones on the screen

  • Reading and calibrating touchscreen coordinates

  • Using touch input to control GPIO pins

  • Creating responsive visual feedback

Complete Code: Touchscreen On/Off Button

Copy this code into your Arduino IDE and upload it to your ESP32 CYD.

cpp
/*  ESP32 CYD Touchscreen On/Off Button
    Controls the built-in green RGB LED with a graphical button
    Complete details: https://RandomNerdTutorials.com/touchscreen-on-off-button-cheap-yellow-display-esp32-2432s028r/
*/

#include <SPI.h>
#include <TFT_eSPI.h>                 // Display library
#include <XPT2046_Touchscreen.h>      // Touch library

TFT_eSPI tft = TFT_eSPI();

// Touchscreen pin definitions for CYD
#define XPT2046_IRQ 36
#define XPT2046_MOSI 32
#define XPT2046_MISO 39
#define XPT2046_CLK 25
#define XPT2046_CS 33

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

// Display dimensions (landscape mode)
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 3

// Button frame position and size
#define FRAME_X 60
#define FRAME_Y 60
#define FRAME_W 200
#define FRAME_H 120

// Red (OFF) button area
#define REDBUTTON_X FRAME_X
#define REDBUTTON_Y FRAME_Y
#define REDBUTTON_W (FRAME_W / 2)
#define REDBUTTON_H FRAME_H

// Green (ON) button area
#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
#define GREENBUTTON_Y FRAME_Y
#define GREENBUTTON_W (FRAME_W / 2)
#define GREENBUTTON_H FRAME_H

// Onboard RGB LED pins
#define CYD_LED_GREEN 16    // We'll control the green LED
#define CYD_LED_RED 4       // (Not used in this example)
#define CYD_LED_BLUE 17     // (Not used in this example)

// Touch coordinates and pressure
int touchX, touchY, touchZ;

// Current button state: false = OFF (green button showing), true = ON (red button showing)
bool buttonState = false;

// Helper: Print touch data to Serial Monitor
void printTouchToSerial(int x, int y, int z) {
  Serial.print("X = "); Serial.print(x);
  Serial.print(" | Y = "); Serial.print(y);
  Serial.print(" | Pressure = "); Serial.println(z);
}

// Draw the button frame (black outline)
void drawFrame() {
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, TFT_BLACK);
}

// Draw the "OFF" state (red button on left, green area blank)
void drawRedButton() {
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_RED);
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_WHITE);
  drawFrame();
  tft.setTextColor(TFT_BLACK);
  tft.setTextSize(FONT_SIZE);
  tft.setTextDatum(MC_DATUM);
  tft.drawString("OFF", REDBUTTON_X + (REDBUTTON_W / 2), REDBUTTON_Y + (REDBUTTON_H / 2));
  buttonState = true;   // Now showing OFF button (red)
}

// Draw the "ON" state (green button on right, red area blank)
void drawGreenButton() {
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_GREEN);
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_WHITE);
  drawFrame();
  tft.setTextColor(TFT_BLACK);
  tft.setTextSize(FONT_SIZE);
  tft.setTextDatum(MC_DATUM);
  tft.drawString("ON", GREENBUTTON_X + (GREENBUTTON_W / 2), GREENBUTTON_Y + (GREENBUTTON_H / 2));
  buttonState = false;  // Now showing ON button (green)
}

void setup() {
  Serial.begin(115200);
  Serial.println("ESP32 CYD Touchscreen Button Starting...");

  // Initialize touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  // Set landscape orientation (adjust if your touch is reversed)
  touchscreen.setRotation(1);  // Try 3 if touches are upside-down

  // Initialize display
  tft.init();
  tft.setRotation(1);           // Landscape mode
  tft.fillScreen(TFT_BLACK);

  // Draw initial button (LED starts OFF)
  drawGreenButton();

  // Configure LED pin
  pinMode(CYD_LED_GREEN, OUTPUT);
  digitalWrite(CYD_LED_GREEN, LOW);  // Start with LED off
}

void loop() {
  // Check for touch
  if (touchscreen.tirqTouched() && touchscreen.touched()) {
    TS_Point p = touchscreen.getPoint();

    // Map raw touch values to screen coordinates
    // These mapping values work for most CYD boards; adjust if needed
    touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    touchZ = p.z;

    printTouchToSerial(touchX, touchY, touchZ);

    // State machine: buttonState tracks which button is currently shown
    if (buttonState) {
      // Currently showing OFF button (red) – waiting for tap on green ON area
      Serial.println("State: OFF button visible");
      if ((touchX > GREENBUTTON_X) && (touchX < (GREENBUTTON_X + GREENBUTTON_W)) &&
          (touchY > GREENBUTTON_Y) && (touchY <= (GREENBUTTON_Y + GREENBUTTON_H))) {
        Serial.println(">> Green (ON) area tapped - Turning LED ON");
        drawGreenButton();               // Change display to ON button
        digitalWrite(CYD_LED_GREEN, HIGH); // Turn LED on
      }
    } else {
      // Currently showing ON button (green) – waiting for tap on red OFF area
      Serial.println("State: ON button visible");
      if ((touchX > REDBUTTON_X) && (touchX < (REDBUTTON_X + REDBUTTON_W)) &&
          (touchY > REDBUTTON_Y) && (touchY <= (REDBUTTON_Y + REDBUTTON_H))) {
        Serial.println(">> Red (OFF) area tapped - Turning LED OFF");
        drawRedButton();                  // Change display to OFF button
        digitalWrite(CYD_LED_GREEN, LOW);  // Turn LED off
      }
    }
    delay(200);  // Simple debounce
  }
}

Understanding the Key Parts

1. Touch Detection and Mapping

The touchscreen returns raw analog values (typically 200–3800). The map() function converts these to screen pixel coordinates:

cpp
touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);

Note: These values work for most CYD boards. If touches are misaligned, you may need to calibrate your screen (see our touch calibration guide).

2. Button Areas

The screen is divided into two touch zones:

  • Green button (ON) – Right half of the frame

  • Red button (OFF) – Left half of the frame

The code checks if a touch falls within these rectangular regions.

3. Visual State Feedback

The button appearance changes instantly:

  • ON state: Green button visible, red area blank

  • OFF state: Red button visible, green area blank

This gives clear, intuitive feedback that the system registered your touch.

4. Output Control

The built-in green LED (GPIO 16) turns on/off with the button. You can easily modify the code to control:

  • External relays via GPIO pins

  • Other LEDs (red/blue channels for RGB)

  • Virtual outputs in a connected IoT dashboard

Testing Your Project

  1. Upload the code to your ESP32 CYD

  2. Open Serial Monitor (115200 baud) to see touch coordinates

  3. Tap the green area – The button should change to “OFF” and the green LED on the back of the board should light up

  4. Tap the red area – The button changes back to “ON” and the LED turns off

If touches don’t align with buttons:

  • Try changing touchscreen.setRotation(1) to 3 in setup()

  • Adjust the mapping values (the numbers in map() functions)

Taking It Further: Project Ideas

This simple button is the foundation for countless real-world projects:

Smart Home Light Switch

Replace the LED control with a relay module connected to GPIO pins. Build a sleek wall-mounted touch panel to control room lights.

Motor Control Panel

Add more buttons to create a machine control interface. Use sliders for speed control (see our LVGL guide for advanced widgets).

Security System Keypad

Create a touch-based code entry system. Use multiple buttons and check combinations to trigger an output.

IoT Dashboard

Combine with Wi-Fi to control devices over the internet. The button could send MQTT messages to smart home hubs.


Build your first touchscreen control today—order your ESP32 CYD and start creating!

======================================

About ESP32S.com

Since 2016, ESP32S.com has grown to become a complete ecosystem partner for your IoT journey. Based in Shenzhen, a global hub for electronics innovation, we have helped hundreds of developers and businesses bring their ESP32-based ideas to life. Our team is dedicated to providing exceptional support and innovative solutions to help you achieve your IoT goals.
At ESP32S.com, we master the intricacies of developing an ESP32-based product, which involves multiple stages, from concept to market launch. That’s why we now offer comprehensive solutions covering the entire product lifecycle for ESP32-based devices. Whether you need help with PCB design, prototyping, production, or even marketing and fulfillment, we have you covered.

Contact Us

Ready to take your IoT project to the next level? Contact ESP32S.com today to learn more about our comprehensive solutions for ESP32-based devices. Let us be your trusted partner in bringing your innovative ideas to life. Contact us now to get started.
Related Posts
Start typing to see products you are looking for.
Shopping cart
Sign in

No account yet?

Shop
Wishlist
0 items Cart
My account