My arduino keeps on detecting a press, yet I cant seem to get it to stop randomly freezing my screen!
Here is the code I use.
#include <SPI.h>
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
// Drawing States
uint16_t currentColor = TFT_WHITE;
int brushRadius = 4;
// UI Layout Constraints
int canvasWidth;
int canvasHeight;
int paletteHeight = 40;
int sliderWidth = 50;
int blockWidth; // Made global so loop() can see it
// Hardware IRQ Pin (Nano D6 = Legacy GPIO 9)
#define TOUCH_IRQ 9
void setup() {
Serial.begin(115200);
// Set the IRQ pin as an input with an internal pull-up resistor
pinMode(TOUCH_IRQ, INPUT_PULLUP);
tft.init();
tft.setRotation(1);
canvasWidth = tft.width() - sliderWidth;
canvasHeight = tft.height() - paletteHeight;
blockWidth = tft.width() / 5; // Split equally among 5 palette options
// --- TOUCH CALIBRATION ---
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, tft.height() / 2 - 10, 4);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println("Tap the arrows to calibrate!");
uint16_t calData[5];
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
tft.setTouch(calData); // <--- CRITICAL FIX: Applies the calibration data!
// --- START THE ART APP ---
tft.fillScreen(TFT_BLACK);
drawPalette();
drawSlider();
}
void loop() {
// Check if physical IRQ indicates a touch event
if (digitalRead(TOUCH_IRQ) == LOW) {
uint16_t x, y;
// Threshold (600) forces the library to ignore phantom/noisy touches
bool pressed = tft.getTouch(&x, &y, 600);
if (pressed) {
// 1. TOUCHING THE PALETTE ZONE (Bottom Bar)
if (y > canvasHeight) {
int selection = x / blockWidth;
switch(selection) {
case 0: currentColor = TFT_RED; break;
case 1: currentColor = TFT_GREEN; break;
case 2: currentColor = TFT_BLUE; break;
case 3: currentColor = TFT_YELLOW; break;
case 4: currentColor = TFT_BLACK; break; // Eraser
}
delay(150); // Debounce UI selection
}
// 2. TOUCHING THE SLIDER ZONE (Right Bar)
else if (x > canvasWidth) {
if (y < canvasHeight) {
brushRadius = map(y, 20, canvasHeight - 20, 20, 1);
brushRadius = constrain(brushRadius, 1, 20);
drawSlider();
delay(50);
}
}
// 3. TOUCHING THE CANVAS ZONE (Drawing)
else {
if ((x - brushRadius > 0) && (x + brushRadius < canvasWidth) &&
(y - brushRadius > 0) && (y + brushRadius < canvasHeight)) {
tft.fillCircle(x, y, brushRadius, currentColor);
}
}
// ---> CRITICAL FIX <---
// Give the SPI bus and TFT controller 2 to 5 milliseconds to breathe.
// This prevents the screen from desyncing and freezing.
delay(3);
}
}
}
void drawPalette() {
tft.fillRect(0, canvasHeight, blockWidth, paletteHeight, TFT_RED);
tft.fillRect(blockWidth, canvasHeight, blockWidth, paletteHeight, TFT_GREEN);
tft.fillRect(blockWidth * 2, canvasHeight, blockWidth, paletteHeight, TFT_BLUE);
tft.fillRect(blockWidth * 3, canvasHeight, blockWidth, paletteHeight, TFT_YELLOW);
// Eraser Block
tft.fillRect(blockWidth * 4, canvasHeight, tft.width() - (blockWidth * 4), paletteHeight, TFT_BLACK);
tft.drawRect(blockWidth * 4, canvasHeight, tft.width() - (blockWidth * 4), paletteHeight, TFT_WHITE);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setCursor(blockWidth * 4 + 10, canvasHeight + 12, 2);
tft.print("ERASER");
}
void drawSlider() {
tft.fillRect(canvasWidth, 0, sliderWidth, canvasHeight, TFT_NAVY);
tft.drawRect(canvasWidth, 0, sliderWidth, canvasHeight, TFT_WHITE);
// Fixed mapping layout to reflect top-heavy size increments
int indicatorY = map(brushRadius, 20, 1, 20, canvasHeight - 20);
indicatorY = constrain(indicatorY, 20, canvasHeight - 20);
// Preview circle for brush size
tft.fillCircle(canvasWidth + (sliderWidth / 2), indicatorY, brushRadius > 15 ? 15 : brushRadius, TFT_WHITE);
tft.setTextColor(TFT_WHITE, TFT_NAVY);
tft.setCursor(canvasWidth + 20, 5, 2);
tft.print("+");
tft.setCursor(canvasWidth + 22, canvasHeight - 20, 2);
tft.print("-");
}
// See SetupX_Template.h for all options available
#define USER_SETUP_ID 21
#define ILI9488_DRIVER
//#define TFT_INVERSION_OFF
#define TFT_MISO 47 // (leave TFT SDO disconnected if other SPI devices share MISO)
#define TFT_MOSI 38
#define TFT_SCLK 48
#define TFT_CS 21 // select control pin
#define TFT_DC 17 //ta Command control pin
#define TFT_RST 18 //t pin (could connect to RST pin)
#define TOUCH_CS 10 //(legacy for d7 nano, makes the touch screen for XPT2046 work...)
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT
// #define SPI_FREQUENCY 20000000
#define SPI_FREQUENCY 27000000
// #define SPI_FREQUENCY 40000000
// #define SPI_FREQUENCY 80000000
// Optional reduced SPI frequency for reading TFT
#define SPI_READ_FREQUENCY 16000000
#define SPI_TOUCH_FREQUENCY 2500000