The ESP32-2432S028R Hardware Spec Sheet & Pin Mapping

The Sunton ESP32-2432S028R, universally known in the maker community as the "Cheap Yellow Display" (CYD), is a 2.8-inch TFT development board that integrates an ESP32-WROOM-32, an ILI9341 display driver, and an XPT2046 resistive touch controller on a single PCB. Priced between $14 and $18 USD in 2026, it eliminates the wiring nightmare of standalone TFT shields. However, its shared SPI buses and undocumented pinouts frequently trap beginners.

The code and architecture in this guide explicitly target the ESP32-WROOM-32 (4MB Flash, Dual-Core 240MHz) variant of the 2432S028R. If your board has an 8MB or 16MB chip (often marked as ESP32-WROOM-32U or custom Sunton revisions), the TFT_eSPI configuration remains identical, but you must select the correct flash partition scheme in the Arduino IDE.

CYD Spec Sheet & Component Variants

ComponentPart Number / DriverInterfaceKey Limitation
MCUESP32-WROOM-32WiFi/BLE2.4GHz WiFi only; no native 5GHz
Display2.8" 320x240 TFT (ILI9341)SPI (VSPI)Resistive touch blocks multi-touch
TouchXPT2046SPI (HSPI)Requires calibration matrix
RGB LEDCommon CathodeGPIO 4, 16, 17Active HIGH; pulls ~20mA per channel
Light SensorGL5528 LDRADC (GPIO 34)Non-linear; requires voltage divider math

Critical Pin Mapping for TFT_eSPI

To use the CYD, you must override the default User_Setup.h in the TFT_eSPI library. Copy these exact definitions into your setup file:

FunctionGPIO PinNotes
TFT_MISO12Shared with SD card on some revisions
TFT_MOSI13Display data in
TFT_SCLK14Display clock
TFT_CS15Display chip select (Active LOW)
TFT_DC2Data/Command pin
TFT_RST-1Tied to ESP32 EN pin; use -1 in code
TFT_BL21Backlight PWM (Active HIGH)
TOUCH_CS33Touch chip select
TOUCH_IRQ36Touch interrupt (Input only)

Decision Tree: Which ESP32 2432S028R Project Fits Your Bench?

Not every ESP32 2432S028R project requires the same architecture. Use this decision matrix to select the right firmware baseline. We will build the default pick below.

Use Case ScenarioPower ConstraintNetwork NeedRecommended Project Baseline
Desktop Ambient ClockUSB 5V continuousWiFi (NTP only)NTP Clock with OpenWeather overlay
Remote Off-Grid Monitor18650 Li-ion / SolarLoRa / ESP-NOWDeep-Sleep ESP-NOW Sensor Receiver
Smart Home Control PanelUSB 5V continuousWiFi + MQTT BrokerMQTT Environment Dashboard (Default Pick)
Decision Default: If you are unsure, build the MQTT Environment Dashboard. It exercises the CYD's WiFi stack, TFT rendering, touch input, and onboard LDR simultaneously, providing a complete stress-test of the hardware.

Step-by-Step Build: MQTT Environment Dashboard

This project reads the onboard LDR, publishes ambient light percentages to an MQTT broker, and listens for commands to change the RGB LED color. It includes a watchdog timer to prevent brownout resets during WiFi reconnects.

Parts List

  • Board: Sunton ESP32-2432S028R (CYD)
  • Power: 5V 2A Micro-USB or USB-C power supply (do not use PC USB ports; the TFT backlight and WiFi spike to 450mA)
  • Software: Arduino IDE 2.x, ESP32 Board Package v2.0.14 or v3.x
  • Libraries: TFT_eSPI, PubSubClient (via knolleary/PubSubClient), ArduinoJson

Numbered Build Steps

  1. Configure TFT_eSPI: Open the library's User_Setup.h. Comment out all default display drivers. Uncomment #define ILI9341_DRIVER. Paste the pin mapping table from Section 1 into the file. Uncomment #define TOUCH_CS 33.
  2. Wire Power: Plug the CYD into a dedicated 5V 2A wall adapter. The ESP32 brownout detector will trigger if voltage drops below 2.4V on the 3V3 rail during WiFi transmission.
  3. Flash the Firmware: Upload the code below. Hold the BOOT button on the back of the CYD if the serial monitor hangs at "Connecting...".
  4. Verify MQTT: Open your MQTT explorer (e.g., MQTTX). Publish a JSON payload to cyd/led/set: {"r":255,"g":0,"b":0} to turn the LED red.

Complete Compilable Code

#include 
#include 
#include 
#include 
#include 

// --- PIN DEFINITIONS (CYD Specific) ---
#define LED_R 4
#define LED_G 16
#define LED_B 17
#define LDR_PIN 34
#define TFT_BL 21

// --- NETWORK & MQTT ---
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASS";
const char* mqtt_server = "192.168.1.100";
const int mqtt_port = 1883;
const char* mqtt_topic_pub = "cyd/sensor/light";
const char* mqtt_topic_sub = "cyd/led/set";

WiFiClient espClient;
PubSubClient client(espClient);
TFT_eSPI tft = TFT_eSPI();

// Watchdog timeout
#define WDT_TIMEOUT 10

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 40) {
    delay(500);
    attempts++;
  }
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi connection failed. Rebooting.");
    ESP.restart();
  }
  Serial.print("IP: "); Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  StaticJsonDocument<256> doc;
  DeserializationError error = deserializeJson(doc, payload, length);
  if (error) {
    Serial.print("JSON parse failed: "); Serial.println(error.c_str());
    return;
  }
  int r = doc["r"] | 0;
  int g = doc["g"] | 0;
  int b = doc["b"] | 0;
  
  // CYD RGB is Common Cathode (Active HIGH)
  analogWrite(LED_R, r);
  analogWrite(LED_G, g);
  analogWrite(LED_B, b);
  
  // Update UI
  tft.fillRect(10, 120, 300, 40, TFT_BLACK);
  tft.setCursor(10, 120);
  tft.printf("LED Set: R:%d G:%d B:%d", r, g, b);
}

void reconnect() {
  if (!client.connected()) {
    String clientId = "CYD-" + String(random(0xffff), HEX);
    if (client.connect(clientId.c_str())) {
      client.subscribe(mqtt_topic_sub);
    } else {
      Serial.printf("MQTT connect failed, rc=%d\n", client.state());
      delay(5000);
      ESP.restart(); // Hard reset on persistent MQTT failure
    }
  }
}

void setup() {
  Serial.begin(115200);
  esp_task_wdt_init(WDT_TIMEOUT, true);
  esp_task_wdt_add(NULL);

  pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT);
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);

  tft.init();
  tft.setRotation(1); // Landscape
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_YELLOW, TFT_BLACK);
  tft.setTextSize(2);
  tft.setCursor(10, 10);
  tft.println("CYD MQTT Dashboard");

  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  
  // Set PWM frequency for LEDs (ESP32 Arduino Core v2.x)
  analogWriteFrequency(5000);
}

void loop() {
  esp_task_wdt_reset(); // Feed the watchdog
  
  if (!client.connected()) reconnect();
  client.loop();

  static unsigned long lastPub = 0;
  if (millis() - lastPub > 2000) {
    lastPub = millis();
    int rawLDR = analogRead(LDR_PIN);
    // LDR on CYD is inverted: high light = low voltage
    int lightPct = map(rawLDR, 4095, 0, 0, 100);
    lightPct = constrain(lightPct, 0, 100);
    
    char msg[16];
    snprintf(msg, sizeof(msg), "%d", lightPct);
    client.publish(mqtt_topic_pub, msg);
    
    tft.fillRect(10, 60, 300, 40, TFT_BLACK);
    tft.setCursor(10, 60);
    tft.printf("Ambient Light: %d%%", lightPct);
  }
}

Debugging the CYD: First Three Things to Check When It Fails

The CYD is notorious for silent failures due to misconfigured libraries and power delivery issues. If your build fails, execute this diagnostic path immediately.

1. The "White Screen" or Compiler Failure

Exact Error String: fatal error: User_Setup.h: No such file or directory (or a blank white screen on upload).

Ranked Causes:

  1. Multiple TFT_eSPI installs: You have the library installed in both your sketchbook and the IDE core. Fix: Delete all instances of TFT_eSPI and reinstall only via the Library Manager.
  2. Wrong User_Setup.h: You edited the wrong file. Fix: In Arduino IDE, go to Sketch > Show Sketch Folder, navigate up to libraries/TFT_eSPI, and ensure the pins from Section 1 are active.
  3. Backlight Pin Float: GPIO 21 is not driven HIGH. Fix: Add digitalWrite(21, HIGH); in setup().

2. Touch Axis Inversion

Symptom: Touching the top-right registers as bottom-left.

Ranked Causes:

  1. Rotation Mismatch: The ILI9341 display rotation and XPT2046 touch rotation are out of sync. Fix: If tft.setRotation(1), ensure your touch calibration matrix matches landscape mode. Use the Touch_Calibrate sketch included in the TFT_eSPI examples to generate the exact 8-digit calibration array for your specific unit.

3. Random Reboots During WiFi Transmission

Exact Error String: MQTT connect failed, rc=-2 followed by rst:0xc (SW_CPU_RESET) in the serial monitor.

Ranked Causes:

  1. USB Cable Voltage Drop: Thin Micro-USB cables drop 0.5V under the 450mA WiFi TX spike, triggering the ESP32 brownout detector. Fix: Use a short, 20AWG USB cable and a 5V 2A+ brick.
  2. Backlight + WiFi Current Spike: Running the TFT backlight at 100% PWM while transmitting starves the 3V3 LDO. Fix: Limit backlight PWM to 80% (analogWrite(TFT_BL, 200);).

Extending and Simplifying Your CYD Build

Once the baseline MQTT dashboard is stable, you must decide whether to scale up the sensor network or strip it down for local control.

How to Extend the Build (Adding I2C Sensors)

The CYD exposes a 4-pin connector labeled P3 on the back. This is your I2C bus.

  • SDA: GPIO 27
  • SCL: GPIO 22
  • Action: Solder a 4-pin JST-SM pigtail to P3. Connect a BME280 temperature/humidity sensor. In your code, initialize Wire.begin(27, 22); before calling bme.begin(0x76). This adds real environmental telemetry to your MQTT payload without occupying the main SPI bus.

How to Simplify the Build (Local Touch Control)

If you want to eliminate the WiFi/MQTT dependency and the associated router latency, strip the network stack entirely.

  • Action: Remove PubSubClient and WiFi.h. Use tft.getTouch(&x, &y) in the main loop to draw three virtual buttons (Red, Green, Blue) on the TFT. When a coordinate zone is tapped, directly drive the RGB LED GPIOs. This reduces flash usage by ~400KB, drops power consumption to ~110mA, and yields a sub-10ms touch-to-light latency.
Safety & Hardware Caveat: Never connect 5V logic directly to the CYD's GPIO pins (including the P3 I2C lines). The ESP32-WROOM-32 is strictly a 3.3V device. If integrating 5V I2C sensors like the older Adafruit SHT31 breakouts, use a bidirectional logic level shifter (e.g., Texas Instruments TXS0108E) to prevent frying the ESP32's input protection diodes.