Conflict between grafics and touchscreen on display 4", 480x320

I would like to bring to the readers’ attention an apparent conflict between graphic and touch functions relating to a 4”, 480x320 px, tft touch screen display. This display is provided with ST7796S driver and XPT2046 touch controller and is available at:
https://it.aliexpress.com/item/4001122632293.html?spm=a2g0s.9042311.0.0.43634c4dxl9z6F
I have chosen this display because of its dimension which allows displaying all needed information in a clearly readable size, including a few buttons for setting purposes which require a working touch function. At the same link clear images of both side of the display are available and pin names are well visible.
On a breadboard I have placed an ESP32 WROOM MCU and the display and connected the two as follows:
Graphics
CS–>GPIO15; RESET –>GPIO2; DC –>GPIO4; SDI(MOSI)–> GPIO23; SCK–> GPIO18; LED–> pin 3V3; SDO(MISO)–> GPIO19.
Touchscreen
T_CLK–> GPIO18; T_CS–> GPIO1; T_DIN–> GPIO23; TDO–>GPIO19; T_IRQ not connected
I have carried out my tests using 4 sketches based on examples proposed by the various libraries I have used.
While the graphic and touch functions perform well individually, I am encountering serious problems in having them working together.
The test result are as follows:

-SKETCH 1
.libraries: SPI.h, XPT2046_Touchscreen.h
.result: touch function performs well
-SKETCH 2
.libraries: SPI.h, TFT_eSPI.h
.result: graphics performs well. No touch response, on serial monitor x=0, y=0, z=4095
-SKETCH 3
.libraries: SPI.h, TFT_eSPI.h, XPT2046_Touchscreen.h
.result: Graphics OK, no touch response, on serial monitor x=0, y=0, z=4095

-SKETCH 4
.libraries: SPI.h, Adafruit_GFX.h, Adafruit_ST7796S_kbv.h, XPT2046_Touchscreen.h
.result:
.if tft.begin() is uncommented and touch.begin commented then graphics is ok
.if tft.begin() is commented and touch.begin uncommented then touch is ok
.if both are uncommented and tft.begin() precedes touch.begin() in the code sequence
then graphics is ok, no touch response and serial monitor shows x=0, y=0, z=4095
.if viceversa there is no graphics and no touch response and on monitor x=0, y=0, z=4095
I like to point out here that the same 4 sketches provide both graphic and touch proper functionalities with a similar display of the same make and pinout but of the type ILI9341 2.8" 240x380 px, available at the same link cited above.
Here are the four sketches:

//SKETCH 1

#include <SPI.h>
#include <XPT2046_Touchscreen.h>

#define CS_PIN 21
XPT2046_Touchscreen ts(CS_PIN);

void setup() {
Serial.begin(115200);
ts.begin();
ts.setRotation(1);

}

void loop() {
if (ts.touched()) {
TS_Point p = ts.getPoint();
Serial.print("Pressure = ");
Serial.print(p.z);
Serial.print(", x = ");
Serial.print(p.x);
Serial.print(", y = ");
Serial.print(p.y);
delay(30);
Serial.println();
}
}




//SKETCH 2

#include <SPI.h>
#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

void setup(void) {
Serial.begin(115200);
Serial.println("\n\nStarting...");

tft.init();
tft.fillScreen(TFT_BLACK);
tft.setRotation(1);
tft.drawRoundRect(0, 0, 480 , 320, 4, TFT_WHITE);
tft.drawRoundRect(5, 5, 470 , 100, 4, TFT_RED);
tft.drawRoundRect(5,108, 470 , 53, 4, TFT_GREEN);
tft.drawRoundRect(5, 165, 122, 71, 4, TFT_YELLOW);
tft.drawRoundRect(131, 165,184 ,71,4, TFT_CYAN);
}


void loop() {
uint16_t x, y;
static uint16_t color;

if (tft.getTouch(&x, &y)) {

tft.setCursor(5, 5, 2);
tft.printf("x: %i ", x);
tft.setCursor(5, 20, 2);
tft.printf("y: %i ", y);

tft.drawPixel(x, y, color);
color += 155;
}
}




//SKETCH 3


#include <SPI.h>
#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>
#define CS_PIN 21
XPT2046_Touchscreen ts(CS_PIN);
TFT_eSPI tft = TFT_eSPI();

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

tft.init();
ts.begin();
tft.fillScreen(TFT_BLACK);
tft.setRotation(1);
tft.drawRoundRect(0, 0, 480 , 320, 4, TFT_WHITE);
tft.drawRoundRect(5, 5, 470 , 100, 4, TFT_RED);
tft.drawRoundRect(5,108, 470 , 53, 4, TFT_GREEN);
tft.drawRoundRect(5, 165, 122, 71, 4, TFT_YELLOW);
tft.drawRoundRect(131, 165,184 ,71,4, TFT_CYAN);
}

void loop() {
if (ts.touched()) {
TS_Point p = ts.getPoint();
Serial.print("Pressure = ");
Serial.print(p.z);
Serial.print(", x = ");
Serial.print(p.x);
Serial.print(", y = ");
Serial.print(p.y);
delay(30);
Serial.println();
}
}


//[u][b]SKETCH 4[/b][/u]

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
#include <XPT2046_Touchscreen.h>

#define TFT_DC 4
#define TFT_CS 15
#define TFT_RST 2
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_CLK 18
#define TOUCH_CS_PIN 21
Adafruit_ST7796S_kbv tft = Adafruit_ST7796S_kbv( TFT_CS,TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);//
XPT2046_Touchscreen touch( TOUCH_CS_PIN);//
void setup() {
Serial.begin( 115200 );
tft.begin();
touch.begin();
tft.setRotation(1);
tft.fillScreen(ST7796S_BLACK);
tft.drawRoundRect(0, 0, 480 , 320, 4, ST7796S_WHITE);
tft.drawRoundRect(5, 5, 470 , 100, 4, ST7796S_RED);
tft.drawRoundRect(5,108, 470 , 53, 4, ST7796S_GREEN);
tft.drawRoundRect(5, 165, 122, 71, 4, ST7796S_YELLOW);
tft.drawRoundRect(131, 165,184 ,71,4, ST7796S_CYAN);
}
TS_Point rawLocation;
void loop() {
while ( touch.touched() )
{
rawLocation = touch.getPoint();
Serial.print("x = ");
Serial.print(rawLocation.x);
Serial.print(", y = ");
Serial.print(rawLocation.y);
Serial.print(", z = ");
Serial.println(rawLocation.z);
}
}

Please edit your post to put the code inside code window. e.g. with the < / > icon (and formatted)

Then I will reply.

David.

nodar10
Thanks for asking how to correctly format your code, looks like you have already found out.

I dug out the ST7796S SPI display. And built for Hardware_SPI using my wiring on a 3.3V "Uno clone":

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ST7796S_kbv.h"
#include <XPT2046_Touchscreen.h>

#define TFT_DC 4
#define TFT_CS 15
#define TFT_RST 2
#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_CLK 18
#define TOUCH_CS_PIN 21
//Adafruit_ST7796S_kbv tft = Adafruit_ST7796S_kbv( TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO); //
//XPT2046_Touchscreen touch( TOUCH_CS_PIN);//
Adafruit_ST7796S_kbv tft = Adafruit_ST7796S_kbv(10, 9, 8); //Hardware SPI constructor
XPT2046_Touchscreen touch(3); //Hardware SPI constructor
void setup() {
    Serial.begin( 9600 );
    tft.begin();
    touch.begin();
    tft.setRotation(1);
    tft.fillScreen(ST7796S_BLACK);
    tft.drawRoundRect(0, 0, 480 , 320, 4, ST7796S_WHITE);
    tft.drawRoundRect(5, 5, 470 , 100, 4, ST7796S_RED);
    tft.drawRoundRect(5, 108, 470 , 53, 4, ST7796S_GREEN);
    tft.drawRoundRect(5, 165, 122, 71, 4, ST7796S_YELLOW);
    tft.drawRoundRect(131, 165, 184 , 71, 4, ST7796S_CYAN);
}
TS_Point rawLocation;
void loop() {
    while ( touch.touched() )
    {
        rawLocation = touch.getPoint();
        Serial.print("x = ");
        Serial.print(rawLocation.x);
        Serial.print(", y = ");
        Serial.print(rawLocation.y);
        Serial.print(", z = ");
        Serial.println(rawLocation.z);
    }
}

XPT2046_Touchscreen only uses Hardware SPI
Adafruit_xxxx libraries accept different constructors e.g. Software SPI, Hardware SPI, ...

You can have multiple SPI devices on the Hardware SPI pins e.g. TFT, XPT2046, SD card
However bit-banged SPI tends to just work with that particular library.

You can never mix hardware and software SPI on the same pins.

David.

p.s. Bodmer supports Hardware SPI for the ST7796 with TFT_eSPI. I don't think that he supports software SPI. But he does support the XPT2046 Touch controller on Hardware SPI.
You configure your wiring in User_Setup.h

If you have a problem with TFT_eSPI you should post a photo / schematic of your wiring.
And post the output from
C:\Users...\Documents\Arduino\libraries\TFT_eSPI\examples\Test and diagnostics\Read_User_Setup\Read_User_Setup.ino

Thanks David for your post.
I am working to provide a proper answer asap.

Hi David
Sorry for not reacting immediately to your post, but I need some time.
I made the test with the sketch proposed by you and this is the result on the monitor:

[color=#000000]TFT_eSPI ver = 2.3.54[/color]
[color=#000000]Processor = ESP32[/color]
[color=#000000]Frequency = 240MHz[/color]
[color=#000000]Transactions = Yes[/color]
[color=#000000]Interface = SPI[/color]
[color=#000000]Display driver = 7796[/color]
[color=#000000]Display width = 3 20[/color]
[color=#000000]Display height = 480[/color]

 
[color=#000000]MOSI = GPIO 23[/color]
[color=#000000]MISO = GPIO 19[/color]
[color=#000000]SCK = GPIO 18[/color]
[color=#000000]TFT_CS = GPIO 15[/color]
[color=#000000]TFT_DC = GPIO 4[/color]
[color=#000000]TFT_RST = GPIO 2[/color]
[color=#000000]TOUCH_CS = GPIO 21[/color]

 
[color=#000000]Font GLCD loaded[/color]
[color=#000000]Font 2 loaded[/color]
[color=#000000]Font 4 loaded[/color]
[color=#000000]Font 6 loaded[/color]
[color=#000000]Font 7 loaded[/color]
[color=#000000]Font 8 loaded[/color]
[color=#000000]Smooth font enabled[/color]

 
[color=#000000]Display SPI frequency = 27.00[/color]
[color=#000000]Touch SPI frequency = 2.50[/color]
[color=#000000]

This is a foto of the breadboard assembled by me:

This is the drawing of the physical connections:

Since the display graphic and touch functions work individually and fail together, could be a solution to have SPI working in multiple bus mode?

Thanks for the Fritzing and thanks for the actual photo.

I would expect to see something like this from Read_User_Setup.ino e.g. this is my Setup :

TFT_eSPI ver = 2.3.59
Processor    = ESP32
Frequency    = 240MHz
Transactions = Yes
Interface    = SPI
Display driver = 9341
Display width  = 240
Display height = 320

MOSI    = GPIO 23
MISO    = GPIO 19
SCK     = GPIO 18
TFT_CS   = GPIO 5
TFT_DC   = GPIO 13
TFT_RST  = GPIO 12
TOUCH_CS = GPIO 16

Font GLCD   loaded
Font 2      loaded
Font 4      loaded
Font 6      loaded
Font 7      loaded
Font 8      loaded
Smooth font enabled

Display SPI frequency = 8.00
Touch SPI frequency   = 2.50

Don't worry about my 8MHz Display SPI. That is temporary for my Logic Analyser.

Your Fritzing wiring looks fine. (But you should connect VCC to 5V if you are using the voltage Regulator on the Display board)

Personally I put XPT2046 and TFT on the same hardware SPI bus.

David.

Thank you for your post.
The monitor output I forwarded was confused due to some mistake in copy/paste.
I have downloaded the latest version of TFT_eSPI, which is 2.3.60, and changed the connections between ESP32 and display according to your expectation. Now I get on the monitor exactly what you expected, excepted the type of display, which is ST7796S in my case and not ILI9341, together with its px counts, that are 320x480.
I have also tested the wiring with my test sketches and nothing has changed with respect to my previous test results.
Since the results of my tests with an ILI9341 (which has same make, same pinout and same touch controller as the ST7796S ) are OK with both TFT_eSPI and Adafruit_GFX, I cannnot understand where the problem is hidden.

I plugged in my ST7796S screen. And set my User_Setup for ST7796S and 27MHz :

TFT_eSPI ver = 2.3.59
Processor    = ESP32
Frequency    = 240MHz
Transactions = Yes
Interface    = SPI
Display driver = 7796
Display width  = 320
Display height = 480

MOSI    = GPIO 23
MISO    = GPIO 19
SCK     = GPIO 18
TFT_CS   = GPIO 5
TFT_DC   = GPIO 13
TFT_RST  = GPIO 12
TOUCH_CS = GPIO 16

Font GLCD   loaded
Font 2      loaded
Font 4      loaded
Font 6      loaded
Font 7      loaded
Font 8      loaded
Smooth font enabled

Display SPI frequency = 27.00
Touch SPI frequency   = 2.50

Ran Test_Touch. Serial shows typical X=0, Y=3450, Z=25 when there is no touch.
If I touch the screen, I get X=x_adc, Y=y_adc, Z=1000 (e.g. 400-2000 depending on pressure)

Ran Touch_calibrate. Serial reports:

// Use this calibration code in setup():
  uint16_t calData[5] = { 290, 3647, 226, 3597, 7 };
  tft.setTouch(calData);

I suggest that you check all your wires.

David.

This topic was automatically closed after 46 days. New replies are no longer allowed.