Utility Bar

Touch-Responsive Drawing Project Using 2.8" 240×320 TFT Display & ESP32

Touch-Responsive Drawing Project Using 2.8" 240×320 TFT Display & ESP32

This guide will help you build a touch-responsive drawing tool using an ESP32 and a 2.8" TFT touchscreen display. You'll learn how to set up the hardware, calibrate the touchscreen, and write the code to create a drawing application.

Parts Required:

  1. ESP32
  2. 2.8" TFT Touchscreen Display (or 2.4" with the ILI9341 driver)
  3. Male to Female Jumper Wires
  4. ESP32 Shield (optional but recommended for easier connections)
  5. Breadboard

Step 1: Setting Up the Hardware

  1. Connect the TFT Display to the ESP32:
    • MISO (T_DO): GPIO 12
    • MOSI (T_DIN): GPIO 14
    • SCLK (T_CLK): GPIO 25
    • CS (T_CS): GPIO 21
    • IRQ (T_IRQ): GPIO 17
    • TFT_CS: GPIO 15
    • TFT_DC: GPIO 2
    • TFT_RST: GPIO 4 or to ESP32 RST (set to -1 in User_Setup.h if connected to ESP32 RST)
  2. Use Breadboard and Jumper Wires:
    • If using a breadboard, connect the ESP32 and TFT display with male to female jumper wires. Use an ESP32 shield (if available) for easier and more secure connections.

Step 2: Installing Libraries

  1. TFT_eSPI Library:

    • Install the TFT_eSPI library by Bodmer from the Arduino Library Manager or download it from its GitHub repository.
    • This library requires configuration through the User_Setup.h file for your specific display and pin connections.
  2. XPT2046_Touchscreen Library:

    • Install the XPT2046_Touchscreen library by Paul Stoffregen from the Arduino Library Manager or download it from its GitHub repository.

Step 3: Configuring the User_Setup.h File

  1. Download the User_Setup.h File:
  2. Add User_Setup.h to the Arduino Library:
    • Place the downloaded User_Setup.h file in the Arduino library folder. For example:
    Documents > Arduino > libraries > TFT_eSPI > User_Setup.h

Step 4: Calibrating the Touchscreen

  1. Touchscreen Calibration:
    • To ensure accurate touch detection, calibrate the touchscreen using raw touch values.
    • Map the raw touch values to screen dimensions by adjusting the below values:
    int x = map(p.x, 3900, 440, 0, SCREEN_WIDTH);
    int y = map(p.y, 3800, 440, 0, SCREEN_HEIGHT);

Step 5: Adding the Code

#include <TFT_eSPI.h>               // Graphics and font library for ILI9341 driver chip
#include <XPT2046_Touchscreen.h>    // Touchscreen library for XPT2046 controller

// Touchscreen pins
#define XPT2046_IRQ 17   // T_IRQ
#define XPT2046_MOSI 14  // T_DIN
#define XPT2046_MISO 12  // T_OUT
#define XPT2046_CLK 25   // T_CLK
#define XPT2046_CS 21    // T_CS

SPIClass touchscreenSPI = SPIClass(VSPI);
XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define FONT_SIZE 2
#define CIRCLE_RADIUS 5    // Circle radius for drawing
#define CLEAR_BUTTON_X 270  // X coordinate for the clear button
#define CLEAR_BUTTON_Y 0    // Y coordinate for the clear button
#define CLEAR_BUTTON_W 50   // Width of the clear button
#define CLEAR_BUTTON_H 50   // Height of the clear button

#define COLOR_BOX_SIZE 30   // Size of the color selection boxes
#define NUM_COLORS 8
uint16_t colors[NUM_COLORS] = {TFT_RED, TFT_BLUE, TFT_GREEN, TFT_YELLOW, TFT_CYAN, TFT_MAGENTA, TFT_ORANGE, TFT_PURPLE};  
uint16_t currentColor = TFT_GREEN;  // Default drawing color

TFT_eSPI tft = TFT_eSPI();

// Previous touch coordinates
int lastX = -1, lastY = -1;

void drawColorBoxes() {
  for (int i = 0; i < NUM_COLORS; i++) {
    tft.fillRect(i * COLOR_BOX_SIZE, 0, COLOR_BOX_SIZE, COLOR_BOX_SIZE, colors[i]);
  }
}

void setup() {
  Serial.begin(115200);

  // Start the SPI for the touchscreen and init the touchscreen
  touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  touchscreen.begin(touchscreenSPI);
  touchscreen.setRotation(1);  // Set the touchscreen rotation in landscape mode

  // Start the TFT display
  tft.init();
  tft.setRotation(1);  // Set the TFT display rotation in landscape mode

  // Clear the screen before writing to it
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  // Draw the clear button
  tft.fillRect(CLEAR_BUTTON_X, CLEAR_BUTTON_Y, CLEAR_BUTTON_W, CLEAR_BUTTON_H, TFT_RED);
  tft.setCursor(CLEAR_BUTTON_X + 10, CLEAR_BUTTON_Y + 15);
  tft.setTextColor(TFT_WHITE, TFT_RED);
  tft.setTextSize(1);
  tft.print("Clear");

  // Draw the color selection boxes
  drawColorBoxes();

  // Set X and Y coordinates for center of display
  int centerX = SCREEN_WIDTH / 2;
  int centerY = SCREEN_HEIGHT / 2;

  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.setTextSize(2);
  tft.drawCentreString("Touch Drawing App", centerX, centerY - 30, FONT_SIZE);
  tft.drawCentreString("Draw by touching!", centerX, centerY, FONT_SIZE);
  tft.drawCentreString("Tap red button to clear", centerX, centerY + 30, FONT_SIZE);
}

void loop() {
  // Checks if touchscreen was touched
  if (touchscreen.tirqTouched() && touchscreen.touched()) {
    // Get touchscreen points
    TS_Point p = touchscreen.getPoint();

    // Calibrate touchscreen points to the correct width and height
    int x = map(p.x, 3900, 420, 0, SCREEN_WIDTH);
    int y = map(p.y, 3800, 440, 0, SCREEN_HEIGHT);
    int z = p.z;

    // Check if the clear button was pressed
    if (x >= CLEAR_BUTTON_X && x <= CLEAR_BUTTON_X + CLEAR_BUTTON_W &&
        y >= CLEAR_BUTTON_Y && y <= CLEAR_BUTTON_Y + CLEAR_BUTTON_H) {
      // Clear the screen
      tft.fillScreen(TFT_BLACK);

      // Redraw the clear button
      tft.fillRect(CLEAR_BUTTON_X, CLEAR_BUTTON_Y, CLEAR_BUTTON_W, CLEAR_BUTTON_H, TFT_RED);
      tft.setCursor(CLEAR_BUTTON_X + 10, CLEAR_BUTTON_Y + 15);
      tft.setTextColor(TFT_WHITE, TFT_RED);
      tft.setTextSize(1);
      tft.print("Clear");

      // Redraw the color selection boxes
      drawColorBoxes();

      // Redraw the instructions
      int centerX = SCREEN_WIDTH / 2;
      int centerY = SCREEN_HEIGHT / 2;
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setTextSize(2);
      tft.drawCentreString("Touch Drawing App", centerX, centerY - 30, FONT_SIZE);
      tft.drawCentreString("Made by Zaitronics", centerX, centerY, FONT_SIZE);
      tft.drawCentreString("zaitronics.com.au", centerX, centerY + 30, FONT_SIZE);

      // Reset the last touch coordinates
      lastX = -1;
      lastY = -1;
    } else if (y < COLOR_BOX_SIZE) {
      // Check if a color box was pressed
      currentColor = colors[x / COLOR_BOX_SIZE];
    } else {
      // Draw thicker circles for smoother drawing
      tft.fillCircle(x, y, CIRCLE_RADIUS, currentColor);

      // Update the last touch coordinates
      lastX = x;
      lastY = y;
    }

    // Print the touch coordinates to the Serial Monitor
    Serial.print("X = ");
    Serial.print(x);
    Serial.print(" | Y = ");
    Serial.print(y);
    Serial.print(" | Pressure = ");
    Serial.println(z);

    delay(10);  // Reduced delay for faster updates
  } else {
    // Reset the last touch coordinates if the screen is not being touched
    lastX = -1;
    lastY = -1;
  }
}

Libraries to Download:

  • TFT_eSPI by Bodmer
  • XPT2046_Touchscreen by Paul Stoffregen

By following these steps, you'll create a touch-responsive drawing tool using an ESP32 and a TFT touchscreen display. Enjoy your project and let your creativity flow!

Leave a comment

Please note: comments must be approved before they are published.