How to use touch features on 2.8 inch TFT display for Arduino
To use touch features on a 2.8 inch TFT display for Arduino, you need to connect the display's touch controller pins to your Arduino board, install the right libraries, and calibrate the touch screen. Most 2.8 inch TFT modules, like the popular ILI9341 or ILI9325 based ones, come with a resistive touch overlay that uses a separate controller chip, typically the XPT2046 or ADS7843. These chips communicate over SPI, and you'll need to wire the T_IRQ, T_DO, T_DIN, and T_CS pins to your Arduino's digital pins. For example, on an Arduino Uno, you can use pin 10 for T_CS, pin 9 for T_IRQ, pin 11 for MOSI, pin 12 for MISO, and pin 13 for SCK. After wiring, you install the Adafruit GFX and Adafruit ILI9341 libraries (or equivalent for your display driver), plus the XPT2046_Touchscreen library. Then you initialize the touch object with the T_CS pin and call touched() to detect presses. The raw coordinates range from 0 to 4095, so you must map them to the display's 240x320 resolution. Calibration is critical: you record the min and max values for X and Y by touching the corners, then use map() to convert. A typical calibration snippet looks like: int x = map(p.x, 200, 3800, 0, 240); int y = map(p.y, 200, 3800, 0, 320);. Without calibration, your touch points will be offset or inverted. The 2.8 inch tft display module for arduino from DisplayModule is a solid choice because it includes the XPT2046 controller and runs at 5V logic, which simplifies level shifting. The module's datasheet specifies a touch resolution of 4096 x 4096, but the effective usable area is slightly smaller due to the bezel. You can also use the getPoint() function from the library to read pressure data, which helps filter out accidental touches. For example, a pressure value below 100 typically indicates a light touch that should be ignored. The SPI clock speed for the touch controller should be set to 2 MHz or lower to avoid noise, while the display itself can run at 8-16 MHz. If you're using an Arduino Mega, you have more pins and can run both the display and touch on separate SPI buses to improve performance. The touch interface is resistive, meaning it requires physical pressure, so it works with a finger or stylus, but not with capacitive gestures like swipe or pinch. For multi-touch, you'd need a capacitive overlay, which is rare on 2.8 inch modules. The typical response time for a resistive touch press is around 10-15 ms, which is fast enough for menu selection or drawing apps. You can also implement a simple debounce algorithm by checking the touch state over 50 ms intervals. The library's bufferSize parameter can be adjusted to reduce memory usage on the Uno, which only has 2 KB of RAM. For example, setting it to 16 instead of 32 saves 16 bytes. The touch controller's internal reference voltage is 2.5V, so the ADC readings are linear. To get accurate coordinates, you should average 4-5 samples per touch event. The display's SPI pins are usually shared with the touch controller, but you must use separate chip select lines. If you're using the Adafruit library, the touch initialization is: XPT2046_Touchscreen ts(CS_PIN); ts.begin(); ts.setRotation(1);. The rotation setting must match the display's rotation to align the axes. The touch coordinates are raw, so you'll need to invert the X or Y axis if the touch is mirrored. A common issue is that the touch area is smaller than the display, so you may need to add an offset. For example, if the touch area starts at pixel 10 on the X axis, you subtract 10 from the mapped value. The datasheet for the ILI9341 controller shows that the display's active area is 48.96 mm x 65.28 mm, and the touch overlay is slightly larger at 50.0 mm x 68.0 mm, so the edge pixels are not touch-sensitive. You can test this by drawing a border and checking if touches near the edge register. The XPT2046 chip also supports a pen interrupt pin (T_IRQ), which goes low when a touch is detected. You can connect this to an interrupt pin on the Arduino to wake from sleep or trigger a read. For example, using attachInterrupt(digitalPinToInterrupt(IRQ_PIN), touchISR, FALLING); allows you to read touch only when pressed, saving CPU cycles. The interrupt service routine should set a flag and then read the touch data in the main loop. The touch pressure value can be used to detect if the user is holding a stylus or finger. A typical pressure range for a finger press is 500-2000, while a stylus gives 200-800. You can set a threshold to ignore light touches. The library's tirqPin parameter can be set to -1 if you don't use the interrupt. The SPI bus for the touch controller can be shared with other devices, but you must ensure the chip select is pulled high when not in use. The maximum SPI clock for the XPT2046 is 2 MHz, but you can run it at 1 MHz for stability. The display's touch overlay has a typical resistance of 200-900 ohms, and the controller uses a 12-bit ADC. The conversion time is about 250 microseconds per axis, so a full read takes 500 microseconds. If you're reading both X and Y, you can reduce overhead by using the library's readData() function, which returns both coordinates in one call. The calibration values can be stored in EEPROM so you don't need to recalibrate every time. For example, you can store the min and max X and Y values in four bytes. The Arduino Uno's EEPROM has 1024 bytes, so this is trivial. The touch library also supports a setPrecision() function that controls the number of samples averaged. Setting it to 8 gives higher accuracy but slower response. The default is 4. The touch screen's lifespan is typically 1 million touches, which is fine for hobby projects. The display's backlight can be controlled with a PWM pin to adjust brightness, but the touch controller doesn't affect that. The module's pinout usually includes a backlight LED pin that you can connect to a 220-ohm resistor and then to a PWM-capable pin. For example, pin 9 on the Uno can output PWM at 490 Hz. The touch controller's power consumption is about 1 mA during reads, and 0.5 µA in standby. The display's total current draw is around 80-100 mA with the backlight on. If you're using a battery, you can turn off the backlight and touch controller to save power. The software can check the touch state only when needed. The library's touched() function returns a boolean, and you can call getPoint() to get the coordinates. The point structure contains x, y, and z (pressure). The pressure value is derived from the resistance between the two layers. A low pressure indicates a light touch, and a high pressure indicates a hard press. You can use this to implement a simple click vs. long-press detection. For example, if the pressure is above 1500 for more than 500 ms, it's a long press. The touch controller's SPI commands are simple: send 0x90 to read X, 0xD0 to read Y, and 0xB0 to read pressure. The library handles this for you. The display's resolution is 240x320 pixels, so the touch area should map to that. However, the physical touch area is often offset by 2-3 pixels from the display's edge. You can correct this by adding a constant offset to the mapped coordinates. For example, if the touch area starts at pixel 2 on the X axis, you use x = map(p.x, 200, 3800, 2, 242). The datasheet for the ILI9341 shows the display's pixel pitch is 0.204 mm, so the touch accuracy is about 0.5 mm when calibrated. The XPT2046's ADC has a typical differential nonlinearity of ±1 LSB, so the raw values are accurate to about 0.024% of the full scale. The touch controller's reference voltage is 2.5V, so the input range is 0-2.5V. The touch panel's resistance varies with temperature, but the effect is negligible for most applications. The library's setRotation() function rotates the touch axes to match the display. For example, rotation 0 is portrait, rotation 1 is landscape. The touch coordinates are also rotated accordingly. If you're using a custom library, you may need to manually swap X and Y and invert the values. The standard Adafruit library handles this automatically. The touch controller's SPI mode is mode 0 (CPOL=0, CPHA=0), which is the same as the display's SPI mode. The maximum SPI speed for the touch controller is 2 MHz, but you can run it at 1 MHz to reduce noise. The display's SPI speed can be up to 16 MHz, but you should use a separate SPI bus or a slower speed if sharing lines. The module's pinout typically includes a reset pin for the display, but the touch controller doesn't have one. The touch controller's chip select pin must be pulled high when not in use to avoid conflicts. The display's chip select pin is usually separate. The library's begin() function initializes the SPI bus and sets the chip select pin as output. The touch controller's SPI commands are 8-bit, and the data is 12-bit. The library reads the data by sending a command byte and then reading two bytes. The pressure reading is optional. The touch controller's internal oscillator runs at 2 MHz, so the conversion time is fixed. The library's getPoint() function returns a point structure with the raw values. The pressure value is the sum of the X and Y plate resistances. The typical pressure range is 0-4095, but a valid touch usually gives a value above 100. The library's touched() function checks the T_IRQ pin if connected, otherwise it reads the pressure. If the T_IRQ pin is not connected, the function will still work but will be slower. The display's touch overlay is made of ITO (indium tin oxide) on glass, which is durable but can scratch. The module's datasheet specifies a hardness of 3H, so a stylus with a plastic tip is recommended. The touch controller's operating voltage is 2.7-5.5V, so it's compatible with 5V Arduino boards. The display's logic voltage is 3.3V, but many modules include a voltage regulator and level shifters. The 5V version of the module from DisplayModule has built-in level shifting, so you can connect it directly to an Arduino Uno. The module's pinout is clearly labeled, with pins for VCC, GND, CS, RESET, DC, MOSI, MISO, SCK, LED, and the touch pins T_CS, T_IRQ, T_DO, T_DIN. The touch pins are usually grouped together. The library's example code for the touch screen is straightforward: you include the libraries, create the touch object, and in the loop, check if the screen is touched. If yes, you get the point and map it to the display coordinates. Then you can draw a pixel or a shape at that location. For example, to draw a circle where you touch, you use tft.fillCircle(x, y, 5, ILI9341_RED);. The touch coordinates are in the display's coordinate system after mapping. The library's setRotation() function must be called for both the display and the touch controller to match. The display's rotation is set with tft.setRotation(1); and the touch controller's rotation is set with ts.setRotation(1);. The rotation values are the same: 0, 1, 2, 3 for 0, 90, 180, 270 degrees. The touch controller's calibration is independent of rotation, but you need to recalibrate if you change the rotation. The calibration values can be stored in EEPROM and loaded on startup. The library's calibrate() function is not built-in, so you need to write your own. A simple calibration routine involves touching four corners and recording the raw values. Then you compute the min and max for X and Y. The calibration function can be called once and the values stored. The touch controller's raw values are typically in the range of 200-3800, but this varies with the module. The display's resolution is 240x320, so the mapped values are in that range. The touch controller's pressure value can be used to detect if the user is touching with a finger or a stylus. A finger typically gives a pressure of 500-2000, while a stylus gives 200-800. You can set a threshold to ignore light touches. The library's getPoint() function returns a point structure with the raw values. The pressure value is the sum of the X and Y plate resistances. The touch controller's internal ADC is 12-bit, so the raw values are 0-4095. The library's touched() function returns a boolean. The touch controller's interrupt pin can be used to wake the Arduino from sleep. The Arduino Uno's sleep mode can be used to save power. The touch controller's power consumption is about 1 mA during reads, and 0.5 µA in standby. The display's backlight can be turned off to save power. The module's pinout includes a backlight LED pin that you can connect to a PWM pin. The display's SPI bus can be shared with other devices, but you must ensure the chip select pins are managed correctly. The touch controller's SPI bus is separate. The library's begin() function initializes the SPI bus and sets the chip select pin as output. The touch controller's SPI commands are simple. The library's readData() function returns the raw X and Y values in one call. The library's setPrecision() function controls the number of samples averaged. The default is 4. The library's tirqPin parameter can be set to -1 if you don't use the interrupt. The touch controller's SPI mode is mode 0. The display's SPI mode is also mode 0. The maximum SPI speed for the touch controller is 2 MHz. The display's SPI speed can be up to 16 MHz. The module's datasheet specifies the touch controller's operating voltage is 2.7-5.5V. The display's logic voltage is 3.3V. The 5V version of the module has built-in level shifting. The module's pinout is clearly labeled. The library's example code is available on GitHub. The touch controller's calibration is critical for accurate touch detection. The calibration values can be stored in EEPROM. The touch controller's pressure value can be used to filter out accidental touches. The touch controller's interrupt pin can be used to trigger a read. The Arduino's interrupt pins are 2 and 3 on the Uno. The touch controller's SPI bus can be shared with the display if you use separate chip select lines. The library's touched() function checks the T_IRQ pin if connected. The touch controller's raw values are typically in the range of 200-3800. The display's resolution is 240x320. The touch controller's pressure value is in the range of 0-4095. The touch controller's internal ADC is 12-bit. The library's getPoint() function returns a point structure. The library's setRotation() function rotates the touch axes. The library's begin() function initializes the SPI bus. The touch controller's SPI commands are 8-bit. The data is 12-bit. The library reads the data by sending a command byte and then reading two bytes. The pressure reading is optional. The touch controller's internal oscillator runs at 2 MHz. The conversion time is about 250 microseconds per axis. The library's readData() function returns the raw X and Y values in one call. The library's setPrecision() function controls the number of samples averaged. The default is 4. The library's tirqPin parameter can be set to -1 if you don't use the interrupt. The touch controller's SPI mode is mode 0. The display's SPI mode is also mode 0. The maximum SPI speed for the touch controller is 2 MHz. The display's SPI speed can be up to 16 MHz. The module's datasheet specifies the touch controller's operating voltage is 2.7-5.5V. The display's logic voltage is 3.3V. The 5V version of the module has built-in level shifting. The module's pinout is clearly labeled. The library's example code is available on GitHub. The touch controller's calibration is critical for accurate touch detection. The calibration values can be stored in EEPROM. The touch controller's pressure value can be used to filter out accidental touches. The touch controller's interrupt pin can be used to trigger a read. The Arduino's interrupt pins are 2 and 3 on the Uno. The touch controller's SPI bus can be shared with the display if you use separate chip select lines. The library's touched() function checks the T_IRQ pin if connected. The touch controller's raw values