XPT2046_Touchscreen: reading a resistive touch panel
The resistive touch layer on most cheap SPI TFTs, including the 2.4 and 2.8 inch ILI9341 boards and the ESP32 Cheap Yellow Display, is read by an XPT2046 controller. Paul Stoffregen鈥檚 XPT2046_Touchscreen library asks it where the panel is being pressed and how hard.
Built in on Mokxi: #include <XPT2046_Touchscreen.h> and it builds, with nothing to install. Free, and no account needed.
What XPT2046_Touchscreen does
The controller shares the SPI bus with the screen but has its own chip select, marked T_CS on the module, plus an optional T_IRQ pin that goes low while the panel is touched. Only one device may have its chip select low at a time, so the screen鈥檚 CS and the touch鈥檚 T_CS must be different pins.
Readings are raw 12-bit numbers, roughly 200 to 3900 across each axis, not pixels. You turn them into screen coordinates with map(), using the raw values you read at the corners of your own panel, and you match the touch rotation to the screen鈥檚 so that x and y point the same way.
| Library Manager name | XPT2046_Touchscreen |
|---|---|
| Author | Paul Stoffregen |
| Include | #include <XPT2046_Touchscreen.h> |
| Boards | every board Mokxi compiles for but ATtiny85 |
| In the simulator | Simulated: it runs against the part the way it does on the bench. |
| Parts it drives | Touch TFT, 2.8 inch ILI9341 with XPT2046, Touch TFT, 3.5 inch ILI9488 with XPT2046, Touch TFT, 4 inch ST7796S with XPT2046 |
Install it
It builds on every board Mokxi compiles for but ATtiny85.
In Mokxi it is built in: #include <XPT2046_Touchscreen.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "XPT2046_Touchscreen" by Paul Stoffregen from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add XPT2046_Touchscreen to lib_deps in PlatformIO. Mokxi follows the calls of release 1.4, so a sketch written here builds there too.
ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
XPT2046_Touchscreen ts(TOUCH_CS, TOUCH_IRQ)
The touch controller on the given chip select. The IRQ pin is optional; with it, touched() can answer without an SPI transfer.
ts.begin()
Sets up the chip select and starts SPI. Call it after the screen鈥檚 own begin().
ts.setRotation(1)
Rotates the touch coordinates. Use the same value you give the screen鈥檚 setRotation().
ts.touched()
True while the panel is pressed hard enough to count.
TS_Point p = ts.getPoint()
The latest reading: p.x and p.y raw from about 200 to 3900, and p.z, the pressure.
if (ts.touched()) {
TS_Point p = ts.getPoint();
int x = map(p.x, 200, 3900, 0, 320);
int y = map(p.y, 240, 3800, 0, 240);
}ts.tirqTouched()
Checks the IRQ pin only, a cheap test to call often before deciding to read a full point.
Example: CYD touch paint
On the Cheap Yellow Display (ESP32-2432S028R). It runs in the browser exactly as printed.
// Touch paint: draw on the Cheap Yellow Display with a finger.
//
// The screen is TFT_eSPI with the board's setup. The touch controller, an
// XPT2046, is not on the screen's bus: the board wires it to GPIO 25 (CLK),
// 32 (DIN), 39 (DO) and 33 (CS), so it gets an SPI bus of its own, the way
// the CYD tutorials do it. Press the screen while the sketch runs to draw.
#include <SPI.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>
#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);
TFT_eSPI tft = TFT_eSPI();
const int kWidth = 320;
const int kHeight = 240;
const uint16_t kInks[4] = {TFT_YELLOW, TFT_CYAN, TFT_MAGENTA, TFT_GREEN};
int ink = 0;
void drawPalette()
{
for (int i = 0; i < 4; i++) {
tft.fillRect(i * 40, 0, 40, 30, kInks[i]);
}
tft.fillRect(160, 0, 160, 30, TFT_DARKGREY);
tft.setTextColor(TFT_WHITE, TFT_DARKGREY);
tft.drawCentreString("clear", 240, 8, 2);
}
void setup()
{
Serial.begin(115200);
touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreenSPI);
touchscreen.setRotation(1);
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
drawPalette();
}
void loop()
{
if (!touchscreen.tirqTouched() || !touchscreen.touched()) return;
TS_Point p = touchscreen.getPoint();
// The raw readings run about 200 to 3700 across the glass.
int x = map(p.x, 200, 3700, 0, kWidth - 1);
int y = map(p.y, 240, 3800, 0, kHeight - 1);
x = constrain(x, 0, kWidth - 1);
y = constrain(y, 0, kHeight - 1);
if (y < 30) {
if (x < 160) {
ink = x / 40;
} else {
tft.fillRect(0, 30, kWidth, kHeight - 30, TFT_BLACK);
}
delay(150);
return;
}
tft.fillCircle(x, y, 3, kInks[ink]);
}Open it in the editor, wired and ready to run 路 CYD touch paint: the project page
Common errors and how to fix them
x and y are swapped, or a touch on the left registers on the right
The touch rotation does not match the screen. Give ts.setRotation() the same number as tft.setRotation(), then swap or reverse the map() ranges if one axis still runs backward.
touched() is true all the time, or points jump around
The screen and the touch controller are both selected at once. Make sure CS and T_CS are separate pins and that every other SPI device has its chip select held high.
Touches land a few pixels away from the finger
The map() ranges are someone else鈥檚. Print the raw p.x and p.y while you press each corner of your own panel, and use those numbers as the input range.
Projects that use XPT2046_Touchscreen
Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.
Keep going
Learn
Parts
Try XPT2046_Touchscreen without installing anything
Open the example, change the sketch, and keep your version in a free account.