The TTP223 turns a small copper pad into a clean digital touch button, and it runs happily at 3.3 V — so on the ESP32 DevKit V1 it needs just three wires and any input pin. The sketch uses each touch to toggle a virtual light, the usual job for these modules in switch-board projects.
The DevKit V1 also has capacitive touch built into the chip, so the sketch reads a bare coin or foil pad on GPIO33 at the same time. Compare the two: the TTP223 works through a plastic panel with no tuning, while the built-in pins cost nothing but need a threshold.
Wiring
| ESP32 DevKit V1 | TTP223 capacitive touch module | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | I/O swings to VCC, so 3V3 keeps it at a safe 3.3 V. Not VIN. |
| D4 | I/O | yellow | HIGH while touched with the default A/B pads open. |
| GND | GND | black |
2.0–5.5 V part, 3.3 V board. I/O drives to the supply voltage, so power it from 3.3 V on ESP32 and Pico and from 5 V on Uno. It runs happily at either.
Board quirks
- The ESP32 already has 10 capacitive touch channels. On the DevKit V1 header: D4 (T0), D2 (T2), D15 (T3), D13 (T4), D12 (T5), D14 (T6), D27 (T7), D33 (T8), D32 (T9). A coin on a wire to one of them plus
touchRead()often replaces the TTP223 entirely. - On the original ESP32 a touched pad reads lower (e.g. 60 → 15). The threshold in the sketch is a starting point — print the raw values with and without a finger and set it between them.
- Why still use a TTP223? It works through 2–3 mm of plastic or glass with a stable threshold, ignores long-wire noise and doesn’t need tuning — handy behind an enclosure panel.
- Solder pad A makes the output active-LOW; pad B makes it toggle on each touch. The sketch assumes both open (momentary, active-HIGH).
- The TTP223 calibrates itself at power-up — don’t touch the pad while the ESP32 boots, or it treats your finger as “nothing”.
Code
// TTP223 touch module on an ESP32 DevKit V1 — plus the ESP32's own touch sensor for comparison.
// TTP223: VCC → 3V3, I/O → D4 (GPIO4), GND → GND. Each touch toggles a virtual light.
// Optional: a coin or a square of foil on a wire to D33 (TOUCH8) — no module needed.
constexpr uint8_t TTP_PIN = 4;
constexpr uint8_t TOUCH_PAD = 33; // GPIO33 = TOUCH8
constexpr uint16_t TOUCH_THRESHOLD = 30; // ESP32 readings DROP when touched; tune for your pad
bool lightOn = false;
bool lastTtp = LOW;
void setup() {
Serial.begin(115200);
pinMode(TTP_PIN, INPUT); // the TTP223 drives its output actively, no pull needed
Serial.println("TTP223 on GPIO4, built-in touch pad on GPIO33");
}
void loop() {
bool ttp = digitalRead(TTP_PIN); // HIGH while touched (default jumper setting)
if (ttp == HIGH && lastTtp == LOW) {
lightOn = !lightOn;
Serial.printf("TTP223 touched → light %s\n", lightOn ? "ON" : "OFF");
}
lastTtp = ttp;
static uint32_t lastPrint = 0;
if (millis() - lastPrint >= 1000) {
lastPrint = millis();
uint16_t raw = touchRead(TOUCH_PAD);
Serial.printf("Built-in pad GPIO33: %u %s\n", raw, raw < TOUCH_THRESHOLD ? "(touched)" : "");
}
delay(20);
}// TTP223 touch module on an ESP32 DevKit V1 — plus the ESP32's own touch sensor for comparison.
// TTP223: VCC → 3V3, I/O → D4 (GPIO4), GND → GND. Each touch toggles a virtual light.
// Optional: a coin or a square of foil on a wire to D33 (TOUCH8) — no module needed.
constexpr uint8_t TTP_PIN = 4;
constexpr uint8_t TOUCH_PAD = 33; // GPIO33 = TOUCH8
constexpr uint16_t TOUCH_THRESHOLD = 30; // ESP32 readings DROP when touched; tune for your pad
bool lightOn = false;
bool lastTtp = LOW;
void setup() {
Serial.begin(115200);
pinMode(TTP_PIN, INPUT); // the TTP223 drives its output actively, no pull needed
Serial.println("TTP223 on GPIO4, built-in touch pad on GPIO33");
}
void loop() {
bool ttp = digitalRead(TTP_PIN); // HIGH while touched (default jumper setting)
if (ttp == HIGH && lastTtp == LOW) {
lightOn = !lightOn;
Serial.printf("TTP223 touched → light %s\n", lightOn ? "ON" : "OFF");
}
lastTtp = ttp;
static uint32_t lastPrint = 0;
if (millis() - lastPrint >= 1000) {
lastPrint = millis();
uint16_t raw = touchRead(TOUCH_PAD);
Serial.printf("Built-in pad GPIO33: %u %s\n", raw, raw < TOUCH_THRESHOLD ? "(touched)" : "");
}
delay(20);
}Expected serial output
TTP223 on GPIO4, built-in touch pad on GPIO33
Built-in pad GPIO33: 64
TTP223 touched → light ON
Built-in pad GPIO33: 12 (touched)
TTP223 touched → light OFFTTP223 on GPIO4, built-in touch pad on GPIO33 Built-in pad GPIO33: 64 TTP223 touched → light ON Built-in pad GPIO33: 12 (touched) TTP223 touched → light OFF
Common errors
Output stuck HIGH (or stuck LOW after power-up)
The module calibrated with a finger or metal near the pad. Power-cycle it with nothing touching it, and keep it away from the ESP32’s antenna end.
Built-in touch pad says “touched” all the time
Threshold too high for your wire length. Print the untouched value and set TOUCH_THRESHOLD to about two-thirds of it.
Touch on D2 or D15 stops the board from booting
Those are strapping pins. Use D4, D13, D27, D32 or D33 for touch pads.