# How to wire 2.8" TFT display to Arduino using custom pins?

**URL:** <https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567>\
**Category:** Programming\
**Created:** [June 29, 2025, 7:37pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567 "2025-06-29T19:37:13Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![MaxMaker](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/maxmaker/32/1013044_2.png) [@MaxMaker](https://forum.arduino.cc/u/MaxMaker)\
**Post date:** [June 29, 2025, 7:37pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/1 "2025-06-29T19:37:13Z")

</div>

Hi all, I am currently building a scale with two stepper motors. Right now I am only trying to get the display and touch controls working, but I am struggling a lot today. I have a CNC shield on a Arduino Mega and I use the ELEGOO 2.8" Touch Screen but using ribbon cables. That's because I cannot attach two Shields on one Arduino.

The following code is working and the display shows some buttons and text. However, the touch input does not work yet. That's what I ask for your help with. I managed to find the right library and pinout, otherwise the displays would not be working. I asked ChatGPT a bunch for advise, but it is pretty useless with this. It keeps telling me to connect physical touch pins, but they don´t exist on my TFT. This Adafruit article gives some insights on those pins, but I don't get it. [Touchscreen Paint Example | 2.8" TFT Touch Shield | Adafruit Learning System](https://learn.adafruit.com/2-8-tft-touch-shield/touchscreen-paint-example)

Anyway the touchscreen worked, but only when it was connected as a shield. Not with ribbon cables. Any ideas what I am doing wrong?

 ![IMG_7053.HEIC](https://europe1.discourse-cdn.com/arduino/original/4X/4/b/8/4b8ad98b17c4b769e417e45a0878872e3def8d9a.jpeg)  
 ![IMG_7052.HEIC](https://europe1.discourse-cdn.com/arduino/original/4X/7/c/a/7cabb3d7a9fc681ae854a754bd42a1b2262b39e9.jpeg)  
 ![IMG_7051.HEIC](https://europe1.discourse-cdn.com/arduino/original/4X/3/5/7/357766e9c1701d27d36cfd8d4f3cd713a39a4b5b.jpeg)  
 ![IMG_7050.HEIC](https://europe1.discourse-cdn.com/arduino/original/4X/9/7/4/974cea1d1acf9ce17108ed86848b2cca509ff259.jpeg)

```arduino

#include <Adafruit_GFX.h>

#include <Adafruit_TFTLCD.h>

#include <TouchScreen.h>

#include <AccelStepper.h>

#include <HX711.h>

// Color definitions

#define BLACK 0x0000

#define WHITE 0xFFFF

#define RED 0xF800

#define GREEN 0x07E0

#define BLUE 0x001F

#define CYAN 0x07FF

#define MAGENTA 0xF81F

#define YELLOW 0xFFE0

// ===================== Pin Mapping =====================

#define LCD_CS A8 // Chip Select

#define LCD_CD A9 // Command/Data

#define LCD_WR A10 // Write

#define LCD_RD A11 // Read

#define LCD_RESET A12 // Reset

// Data D0–D7 -> Mega pins 22..29

// Touchscreen (4-wire resistive) breakout wiring (paint example)

#define YP A2 // must be analog pin

#define XM A3 // must be analog pin

#define YM 9 // can be digital pin

#define XP 8 // can be digital pin

#define TS_MINX 120

#define TS_MAXX 900

#define TS_MINY 70

#define TS_MAXY 920

#define MINPRESSURE 10

#define MAXPRESSURE 1000

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Instantiate TFT TouchScreen(XP, YP, XM, YM, 300);

// Instantiate TFT

typedef uint16_t color_t;

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

// Steppers

#define stepPinX 2

#define dirPinX 5

#define EndstopX 9

AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);

#define stepPinY 3

#define dirPinY 4

#define EndstopY 11

AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);

// HX711 scale

#define DOUT 32

#define CLK 33

HX711 scale;

#define RelayPin 12

// UI state

String inputText = "";

int Wunschanzahl = 0;

float WunschgewichtTotal = 0;

float GewichtEineSchraube = 0;

bool runPressed = false;

bool stopPressed = false;

bool WeighingComplete = false;

// Generic button drawer

void drawButton(int x, int y, int w, int h, const char\* label, color_t bg, color_t fg) {

tft.fillRect(x, y, w, h, bg);

tft.drawRect(x, y, w, h, fg);

tft.setTextSize(2);

int16_t textW = 6 \* strlen(label) \* 2; // char width 6px \* size

int16_t textH = 8 \* 2; // char height 8px \* size

int16_t tx = x + (w - textW) / 2;

int16_t ty = y + (h - textH) / 2;

tft.setCursor(tx, ty);

tft.setTextColor(fg);

tft.print(label);

}

// Draw keypad & controls with adjusted sizes

void drawKeypad() {

tft.fillScreen(BLACK);

  // Numeric keys: narrower

const int numW = 40, numH = 40, numSX = 45, numSY = 45;

static const char\* keys\[4\]\[3\] = {{"1","2","3"},{"4","5","6"},{"7","8","9"},{"Del","0","OK"}};

for(int r=0; r<4; r++) {

for(int c=0; c<3; c++) {

int x = c \* numSX;

int y = r \* numSY;

drawButton(x, y, numW, numH, keys\[r\]\[c\], BLACK, WHITE);

}

}

    // Control keys: wider (moved left)

const int ctrlW = 70, ctrlH = 40;

const int ctrlX = 150; // moved left from 180

drawButton(ctrlX, 0, ctrlW, ctrlH, "Enter", BLACK, WHITE);

drawButton(ctrlX, 50, ctrlW, ctrlH, "Run", GREEN, BLACK);

drawButton(ctrlX, 100, ctrlW, ctrlH, "Stop", RED, BLACK);

drawButton(ctrlX, 150, ctrlW, ctrlH, "TARE", CYAN, BLACK);

}

// Update numeric displays

void updateDisplays() {

tft.fillRect(0, 200, 320, 60, BLACK);

tft.setTextSize(2);

tft.setCursor(0, 200);

tft.setTextColor(GREEN);

tft.print("Wunschzahl: "); tft.print(Wunschanzahl);

tft.setCursor(0, 220);

tft.setTextColor(CYAN);

tft.print("Eingabe: "); tft.print(inputText);

tft.setCursor(0, 240);

tft.setTextColor(YELLOW);

tft.print("g/Stk: "); tft.print(GewichtEineSchraube, 2);

}

// Live weight feedback

void updateWeightDisplay(float w) {

tft.fillRect(0, 280, 320, 20, BLACK);

tft.setTextSize(2);

tft.setCursor(0, 280);

float delta = abs(WunschgewichtTotal - w);

float tol = WunschgewichtTotal \* 0.01;

color_t col = (delta <= tol) ? GREEN : ((delta <= GewichtEineSchraube\*3) ? YELLOW : RED);

tft.setTextColor(col);

tft.print("Gewicht: "); tft.print(w, 2);

}

// Homing routines

void HomingX() {

stepperX.setMaxSpeed(500);

stepperX.setSpeed(-500);

while(digitalRead(EndstopX)==HIGH) stepperX.runSpeed();

stepperX.stop(); delay(200);

stepperX.setCurrentPosition(0);

}

void HomingY() {

stepperY.setMaxSpeed(500);

stepperY.setSpeed(-500);

while(digitalRead(EndstopY)==HIGH) stepperY.runSpeed();

stepperY.stop(); delay(200);

stepperY.setCurrentPosition(0);

}

// Button press handler

void handleKey(const char\* label) {

if(!strcmp(label,"Del") && inputText.length()) inputText.remove(inputText.length()-1);

else if(!strcmp(label,"OK")) { Wunschanzahl=inputText.toInt(); inputText=""; }

else if(!strcmp(label,"Enter")) { scale.tare(); delay(500); WunschgewichtTotal=scale.get_units(20); GewichtEineSchraube=WunschgewichtTotal/Wunschanzahl; }

else if(!strcmp(label,"TARE")) scale.tare();

else if(!strcmp(label,"Run")) { runPressed=true; stopPressed=false; }

else if(!strcmp(label,"Stop")) { stopPressed=true; runPressed=false; }

else inputText+=label;

updateDisplays();

}

// Run sequence

void checkRunSequence() {

if(runPressed && !WeighingComplete) {

HomingX();

while(!WeighingComplete && !stopPressed) {

stepperX.setMaxSpeed(2000);

stepperX.move(10000); while(stepperX.distanceToGo()) stepperX.run(); delay(300);

stepperX.move(-10000); while(stepperX.distanceToGo()) stepperX.run(); delay(1000);

float cw=scale.get_units(20); updateWeightDisplay(cw);

float rem=WunschgewichtTotal-cw;

if(rem<=GewichtEineSchraube\*3) {

stepperX.move(8000); while(stepperX.distanceToGo()) stepperX.run();

for(int i=0;i<4;i++){ stepperX.move(500); while(stepperX.distanceToGo()) stepperX.run(); delay(400); }

}

if(abs(cw-WunschgewichtTotal)<WunschgewichtTotal\*0.01) { WeighingComplete=true; HomingY(); }

}

    runPressed=false;

}

}

void setup() {

Serial.begin(9600);

pinMode(RelayPin,OUTPUT);

pinMode(EndstopX,INPUT_PULLUP);

pinMode(EndstopY,INPUT_PULLUP);

stepperX.setAcceleration(9000); stepperX.setMaxSpeed(4500);

stepperY.setAcceleration(1000); stepperY.setMaxSpeed(3500);

tft.reset(); uint16_t id=tft.readID(); tft.begin(id); tft.setRotation(0);

drawKeypad(); updateDisplays();

scale.begin(DOUT,CLK); scale.set_scale(); scale.tare();

}

void loop() {

  TSPoint p=ts.getPoint(); pinMode(XP,OUTPUT); pinMode(YP,OUTPUT);

if(p.z>MINPRESSURE&&p.z<MAXPRESSURE) {

int x=map(p.x,TS_MINX,TS_MAXX,0,tft.width());

int y=map(p.y,TS_MINY,TS_MAXY,0,tft.height());

static const char\* keys\[4\]\[3\]={{"1","2","3"},{"4","5","6"},{"7","8","9"},{"Del","0","OK"}};

for(int r=0;r<4;r++) for(int c=0;c<3;c++){

int bx=c\*45,by=r\*45;

if(x>bx&&x<bx+40&&y>by&&y<by+40){ handleKey(keys\[r\]\[c\]); delay(300); }

}

if(x>150 && x<150+70){

if(y<40) handleKey("Enter");

else if(y<90) handleKey("Run");

else if(y<140) handleKey("Stop");

else if(y<190) handleKey("TARE");

delay(300);

}

}

float lw=scale.get_units(10); updateWeightDisplay(lw); checkRunSequence(); delay(200);

}

```

---

<div class="post-metadata">

**Author:** ![LarryD](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/larryd/32/215550_2.png) [@LarryD](https://forum.arduino.cc/u/LarryD)\
**Post date:** [June 29, 2025, 7:44pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/2 "2025-06-29T19:44:37Z")

</div>

> [@MaxMaker](#):
>
> Not with ribbon cables

- 1st confirm the continuity of each ribbon cable wire.

---

<div class="post-metadata">

**Author:** ![MaxMaker](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/maxmaker/32/1013044_2.png) [@MaxMaker](https://forum.arduino.cc/u/MaxMaker)\
**Post date:** [June 29, 2025, 8:32pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/3 "2025-06-29T20:32:14Z")

</div>

I spent 6 hours troubleshooting. I even checked continuity on those tiny access tabs on the connectors.

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [June 29, 2025, 9:20pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/4 "2025-06-29T21:20:17Z")

</div>

If you have the touchscreen pins correct for using the display as a shield:

```arduino
#define YP A2 // must be analog pin
#define XM A3 // must be analog pin
#define YM 9 // can be digital pin
#define XP 8 // can be digital pin

```

Then they should be wired as follows. I'm not sure which pins you are using for the LCD data lines, and you appear to be calling LCD\_RS by another name. The pins are shared with the display, which is why YP and XM have to be set back to output mode immediately after calling the ts.getPoint() function. (although you seem to be setting XP to output mode instead of XM, it should be whichever pins of the touchscreen are connected to LCD\_RS and LCD\_CS).

```arduino
YP = same as LCD_RS
XM = same as LCD_CS
YM = same as LCD_D1
XP = same as LCD_D0
```

\< edit \> Oops, had YM and XP wrong, had trouble matching the picture to a UNO pinout.

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [June 29, 2025, 9:40pm UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/5 "2025-06-29T21:40:50Z")

</div>

> [@LarryD](#):
>
> 1st confirm the continuity of each ribbon cable wire.

The touch screen shares pins with the TFT display, if the display is working then the wiring is OK.

---

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [June 30, 2025, 3:12am UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/6 "2025-06-30T03:12:58Z")

</div>

> [@MaxMaker](#):
>
> touchscreen worked, but only when it was connected as a shield

Read the library intro.

---

<div class="post-metadata">

**Author:** ![van\_der\_decken](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/van_der_decken/32/1006976_2.png) [@van\_der\_decken](https://forum.arduino.cc/u/van_der_decken)\
**Post date:** [June 30, 2025, 4:41am UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/7 "2025-06-30T04:41:10Z")

</div>

```arduino
// Touchscreen (4-wire resistive) breakout wiring (paint example)
#define YP A2 // must be analog pin
#define XM A3 // must be analog pin
#define YM 9 // can be digital pin
#define XP 8 // can be digital pin

```

 ![image](https://europe1.discourse-cdn.com/arduino/original/4X/8/9/b/89b1ae38a44e5e12c33fe4804067981332660f5c.jpeg)

 ![image](https://europe1.discourse-cdn.com/arduino/original/4X/f/1/0/f10ca047abd5536b906c4ee1c7c477beeaddbb5e.jpeg)

You have no connection to any of the touchscreen pins that you have defined. That's why the touchscreen doesn't work.

As @david_2018 has already pointed out, the touchscreen pins on the shield are shared between the display and the touchscreen and do double duty. You will have to redefine the touchscreen pins to be whatever you've moved the corresponding display pin to. And LCD\_RS (YP) and LCD\_CS (XM) must be on analog pins.

---

<div class="post-metadata">

**Author:** ![MaxMaker](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/maxmaker/32/1013044_2.png) [@MaxMaker](https://forum.arduino.cc/u/MaxMaker)\
**Post date:** [June 30, 2025, 8:39am UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/8 "2025-06-30T08:39:13Z")

</div>

I am using A8-A12 instead of A1-A5. Thank you for your explanations. How am I supposed to know which pin is X and Y? I read the tutorials and manual many times. I never found that information.

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [June 30, 2025, 10:02am UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/9 "2025-06-30T10:02:36Z")

</div>

I though you said the touchscreen worked when it was connected as a shield. If it was working at that time, then you can tell by the sketch which pins were being used for the touchscreen.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [December 27, 2025, 10:03am UTC](https://forum.arduino.cc/t/how-to-wire-2-8-tft-display-to-arduino-using-custom-pins/1392567/10 "2025-12-27T10:03:15Z")

</div>

Closed on December 27, 2025, 10:03am UTC

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
