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

Ethan Zaitchik |

Table of Contents

    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

    // Table of contents