Here is a practical application example for the Touchscreen PCB.
First, a couple of caveats:
- I use GPIO13 to power the led on the ILI9341 screens. It’s typical to wire the led (backlight) to Vcc, but this works for me.
- My example uses arrays to position screen elements and to define touch area coordinates.
- A complete version of this application would likely include wifi, OTA upgrading, HTTP client so that you can access pHp servers etc and control things.
- Note that I have included Touch coordinates to suit the ST7789 displays that I also use. This might help someone…. (Refer to A Tale of two Screens for a more complete discussion.)
- The actual coordinates will vary according to different displays / resolutions and screen rotation!

Arduino code for Touch Menu
/*
ILI9341 and ESP32 Lolin demo http://www.lecity.edu.au
Credit to Bodmer's TFT_eSPI library https://github.com/Bodmer/TFT_eSPI
*/
#include "LittleFS.h" // LittleFS
#include "Free_Fonts.h" // Include the header file
#include <SPI.h>
#include <TFT_eSPI.h> // see https://github.com/Bodmer/TFT_eSPI Config in libraries User_Setup.h
#include <TJpg_Decoder.h>
#include <elapsedMillis.h>
TFT_eSPI tft = TFT_eSPI();
int Bx[15] = {0, 80, 160, 0, 80, 160, 0, 80, 160, 0, 80, 160, 0, 80, 160}; // Arrays for buttons drawing starts at 0
int By[15] = {0, 0, 0, 64, 64, 64, 128, 128, 128, 192, 192, 192, 256, 256, 256};
int tBx[15] = {0, 100, 200, 0, 100, 200, 0, 100, 200, 0, 100, 200, 0, 100, 200}; // Arrays for button touch coordinates
int tBy[15] = {0, 0, 0, 48, 48, 48, 96, 96, 96, 144, 144, 144, 192, 192, 192};
int pressed;
uint32_t keyStart, keyDelay = 500; // milliseconds betwen keypresses avoid bounce
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
if ( y >= tft.height() ) return 0;
tft.pushImage(x, y, w, h, bitmap);
return 1;
}
String swVersion = (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__);
void setup(void) {
Serial.begin(115200);
if (!LittleFS.begin()) {
Serial.println("LittleFS initialisation failed!");
}
pinMode(13, OUTPUT); // The pin needs to set to Output : HIGH screen on / LOW screen off //
digitalWrite(13, HIGH); // ILI9341's LED is driven from GPIO 13
tft.begin();
tft.setRotation(0);
tft.fillScreen(TFT_BLACK);
tft.drawRect(5, 5, 235, 315, TFT_YELLOW);
tft.drawRect(8, 8, 227, 307, TFT_GREEN);
tft.setFreeFont(FSS12);
tft.setCursor(20, 35);
tft.setTextColor(TFT_YELLOW);
Serial.println("Loading the splash screen");
tft.setCursor(20, 70);
tft.println("TFT Touch Menu");
tft.setCursor(20, 100);
tft.setTextColor(TFT_WHITE);
tft.setFreeFont(FSS9);
tft.println(swVersion);
/// Put Wifi, MQTT, httpGet , OTA init, EEPROM etc things in here too.
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
delay(1000);
mainMenu();
}
///////////////////////////////// Main Loop //////////////////////////////////////
void loop() {
uint16_t x, y; // Init touch
if (tft.getTouch(&x, &y) && millis() >= keyStart + keyDelay) {
getButton(x, y); // Evaluate press
Serial.println("Pressed: " + String(pressed));
if (pressed == 1) { //Button 1
mainMenu();
}
if (pressed == 2) { //Button 2
tft.fillScreen(TFT_BLACK);
// doAirCon things.....
tft.setCursor(20, 70);
tft.setTextColor(TFT_WHITE);
tft.println("Air Con menu etc");
delay(3000);
mainMenu();
}
if (pressed == 3) { //Button 3
tft.fillScreen(TFT_BLACK);
TJpgDec.drawFsJpg(0, 0, "/Picture.jpg", LittleFS);
delay(5000);
mainMenu();
}
keyStart = millis();
}
}
void mainMenu() {
tft.fillScreen(TFT_BLACK);
drawButton(1, "MAIN", TFT_YELLOW, TFT_GREEN);
drawButton(2, "AirCon", TFT_WHITE, TFT_GREEN);
drawButton(3, "Picture", TFT_WHITE, TFT_GREEN);
drawButton(4, "4", TFT_WHITE, TFT_GREEN);
drawButton(5, "5", TFT_WHITE, TFT_GREEN);
drawButton(6, "6", TFT_WHITE, TFT_GREEN);
drawButton(7, "7", TFT_WHITE, TFT_GREEN);
drawButton(8, "8", TFT_WHITE, TFT_GREEN);
drawButton(9, "9", TFT_WHITE, TFT_GREEN);
drawButton(10, "etc", TFT_WHITE, TFT_GREEN);
}
/////// Draw any of 15 Outline buttons /////
void drawButton(int buttonnumber, const String& textlabel, uint16_t fontColor, uint16_t background) {
tft.setFreeFont(FSS9);
tft.drawRoundRect(Bx[buttonnumber - 1], By[buttonnumber - 1], 79, 63, 6, background);
tft.setTextColor(fontColor);
tft.setCursor(Bx[buttonnumber - 1] + 8, By[buttonnumber - 1] + 32);
tft.print(textlabel);
}
uint16_t getButton(int x, int y) {
pressed = 0;
int vy = x, vx = 300 - y;
// if (displayType == "ST7789") {vy = 240 - x;} else {vy = x;} //vy=x for ILI9341 OR vy=240-x for ST7789
Serial.print("vx/vy:");
Serial.print(vx);
Serial.print("*");
Serial.println(vy);
for (int n = 0; n < 15; n++) {
if (vx > tBx[n] && vx < tBx[n] + 100 && vy > tBy[n] && vy < tBy[n] + 48) {
pressed = n + 1 ;
}
}
Serial.println(pressed);
return pressed;
}