Introduction
The ESP32 microcontroller includes a set of dedicated capacitive touch GPIOs that let you replace mechanical push-buttons with simple conductive surfaces — a piece of wire, a strip of aluminium foil, or even a copper pad on a PCB. Touching the surface with a finger is enough to trigger a detectable change in the pin's electrical reading.
These inputs are extremely versatile: these pins can be easily integrated into capacitive pads to replace mechanical buttons, and the touch pins can also be used as a wake-up source when the ESP32 is in deep sleep. In this guide we'll walk through the theory, the pinout, the wiring, and two complete working examples — reading raw touch values and using touch input to switch an LED on and off.
How Capacitive Touch Sensing Works
Human skin holds a small electrical charge. ESP32 uses the electrical properties of the human body as input — when the touch-sensing pin is touched with a finger, a small electric charge is drawn to the point of contact, triggering a capacitance variation that results in an analog signal. Two successive approximation ADCs (SAR ADCs) then convert this analog signal into a digital number that your program can read.
touches pad
changes
converts signal
returns lower value
Touch detection is not handled by the main CPU core alone — touch detection in ESP32 is managed by the ULP coprocessor, so these touch pins can also be used to wake the ESP32 from deep sleep, making them ideal for battery-powered wake-up buttons.
Touch-Capable Pins on the ESP32
The ESP32 has 10 capacitive touch GPIOs, labelled T0 through T9. Each touch channel is tied to a specific, fixed GPIO number that cannot be changed.
| Touch Channel | GPIO Pin |
|---|---|
| T0 | GPIO 4 |
| T1 | GPIO 0 |
| T2 | GPIO 2 |
| T3 | GPIO 15 |
| T4 | GPIO 13 |
| T5 | GPIO 12 |
| T6 | GPIO 14 |
| T7 | GPIO 27 |
| T8 | GPIO 33 |
| T9 | GPIO 32 |
Source: Touch0 is T0 - GPIO 4, Touch1 is T1 - GPIO 0, Touch2 is T2 - GPIO 2, Touch3 is T3 - GPIO 15, Touch4 is T4 - GPIO 13, Touch5 is T5 - GPIO 12, Touch6 is T6 - GPIO 14, Touch7 is T7 - GPIO 27, Touch8 is T8 - GPIO 33, Touch9 is T9 - GPIO 32.
Wiring the Touch Pad
Setting up a touch input is remarkably simple — no external resistors or components are required. No resistors, no other components are needed for the basic touch read. All you need is a single conductive object connected to a touch-capable GPIO.
What you need
- 1× ESP32 development board
- 1× male-to-male jumper wire
- (Optional) LED + short wire for output demo
- (Optional) Aluminium foil as a larger touch pad
Wiring steps
You can use everyday conductive materials as touch surfaces: aluminium is a good conductor, so you can use aluminium foil as a touch plate. Conductive paint, conductive cloth, or even a bare copper PCB pad also work well.
Reading Raw Touch Values
The core function used for touch sensing is touchRead(). In the Arduino IDE, you use the touchRead() function, which accepts as argument the GPIO you want to read: touchRead(GPIO). You can pass either the GPIO number or the T-channel name — you can either pass the touch sensor number (T0) or the GPIO number (4).
// ESP32 Touch Test — Reads Touch0 (GPIO 4) and prints the value void setup() { Serial.begin(115200); delay(1000); Serial.println("ESP32 Touch Test"); } void loop() { Serial.println(touchRead(4)); // GPIO 4 = Touch0 delay(1000); }
Uploading and Testing (Arduino IDE)
Visualizing Touch Data
Watching raw numbers scroll by in the Serial Monitor works, but it's much easier to spot the touch/no-touch threshold visually. You have two good options:
Arduino Serial Plotter
Built directly into the Arduino IDE — no extra download needed. It plots incoming numeric values in real time as a live line graph.
Third-party Serial Terminal
A lightweight standalone utility (such as a serial terminal / plotting tool) that can be run without installation and offers similar real-time graphing of serial data.
Using the Arduino Serial Plotter
This graphical view makes it very easy to pick a reliable numeric threshold that separates "touched" from "untouched" states for your specific wire, pad material, and length.
Using Touch as a Digital Switch (LED Control)
Once you know your threshold, you can use a simple if comparison to turn the touch pad into a
digital button that drives an output — for example, an LED, a relay, or any other load.
// Touch-controlled LED example const int touchPin = 4; // GPIO 4 = Touch0 const int ledPin = 2; // Built-in LED on many boards const int threshold = 40; void setup() { Serial.begin(115200); pinMode(ledPin, OUTPUT); } void loop() { int touchValue = touchRead(touchPin); Serial.println(touchValue); if (touchValue < threshold) { digitalWrite(ledPin, HIGH); // Touched → LED ON } else { digitalWrite(ledPin, LOW); // Not touched → LED OFF } delay(100); }
This mirrors the classic touch-sense pattern used across ESP32 projects: based on the values, we can set a threshold, so that when the reading drops below the threshold, we will toggle the LED.
Uploading and Testing
Real-World Applications
Because touch pins behave like ordinary digital inputs once thresholded, they can substitute for mechanical buttons almost anywhere: you can use these GPIOs to update existing simple push button projects or to create light switches, musical instruments, or custom interactive surfaces.
🔌 Touch light switches
Replace a mechanical wall switch with a hidden copper pad behind a panel.
📋 Menu / navigation buttons
Build sleek, seamless control panels for IoT devices with no moving parts.
😴 Deep-sleep wake source
Wake a battery-powered ESP32 from deep sleep with a single touch.
🎹 Interactive surfaces
Create touch-sensitive musical instruments or gesture pads.
(foil / wire)
touchRead()
Comparison
Menu Action