Problems with Touch-controller XPT2046 / Somebody already using this 2.8inch 320x240 ESP32-display?

Hi everybody,

today two of these 2.8 inch 320x240 pixel color TFT--touch-displays with ESP32 arrived.
https://de.aliexpress.com/item/1005004502250619.html?spm=a2g0o.order_detail.order_detail_item.4.61486368fa7ENZ&gatewayAdapt=glo2deu

I connected with a USB-cable and the demo-code started to run. So the display and ESP32 are operating OK

On the website of the manufacturer I found a software and documentation package

ESP32-2432S028R download link:http://www.jczn1688.com/zlxz

Download passwort: jczn1688

download for 2.8 inch
http://www.jczn1688.com/filedownload/640056

chinese but I managed to download it

I copied the libraries from the downlaoded RAR-package into my library-folder
and compiled the 3_4_TFT_Rainbow.ino demo

compiling was successfull
So I took a deep breath and started compile and upload
upload was successfull raimbow demo is running.

So my opinion: a really nice combination of an ESP32 with a TFT-touch-display for a very low price
€11 plus 5€ shipment. Inlcuding SD-card-socket and an RGB-LED on the backside.

Now I have to explore how to use the touch-funtion and the SD-Card

best regards Stefan

I have not yet managed to make the touch-function work.
When delivered there was a demo-code on it that showed the touch is working.

I have tried this demo-code

but it did not work
The XY-values printed to the serial monitor stayed constant regardless of touching the screen or not.

Then I tried this code
.....\libraries\TFT_eSPI\examples\320 x 240\Keypad_240x320

The keypad is shown on the TFT but no touch-function
I assume (not knowing !) that if I touch the screen anywhere even with a wrong calibration at least there should be some reaction even if the reaction does not fit to the area that I have touched.

But maybe this assumption is wrong

In the usermanual to the 2,8" TFT-touch-display (file attached) on page 13 is written
Although the TFT_eSPI library has many advantages, it may also have a troublesome place for ordinary
users, that is, after the installation
It needs to be configured separately, I already have a configured file, as shown in the figure:

Copy the file and replace User_Setup.h in TFT_eSPI. The library location is generally
C:\Users<username>\sketchbook\libraries \TFT_eSPI .
If you want to take a closer look at the various setting options, you can follow my tutorial and set it up.
Go to the Arduino library file installation directory and open the location of the TFT_eSPI library. Taking
Windows as an example, the library installation directory is generally:
C:\Users<username>\ sketchbook\libraries \TFT_eSPI .
As shown:

A changed the pin-configuration acording to the getting started PDF
(PDF getting started is attached)
Getting started 2.8 Inch.pdf (6.4 MB)

#define TFT_BL   21            // LED back-light control pin
#define TFT_BACKLIGHT_ON HIGH  // Level to turn ON back-light (HIGH or LOW)

#define TFT_MISO 12 
#define TFT_MOSI 13 // In some display driver board, it might be written as "SDA" and so on.
#define TFT_SCLK 14
#define TFT_CS   15  // Chip select control pin
#define TFT_DC   2  // Data Command control pin
#define TFT_RST  -1  // Reset pin (could connect to Arduino RESET pin)
#define TFT_BL   21  // LED back-light

#define TOUCH_CS 33     // Chip select pin (T_CS) of touch screen

There are two schematics provided with the documentation


The pin-names on the touch-controller-chip XPT2046 are confusing me

can somebody check if the IO-pin assigments match to these numbers?
The only thing I understand in the schematic there is a pin named /CS which seems to be connected to IO33 and this seems to match with this
#define

#define TOUCH_CS 33     // Chip select pin (T_CS) of touch screen

inside the
F:\myData\Arduino\libraries\TFT_eSPI\User_Setup.h-file

How would you proceed in analysing / narrowing down the bug?
Does anybody know of another demo-code that only activates the touch-controller?

best regards Stefan

Hi Stefan,
I'm having the same trouble with this board. It seems to me the fundemental problem is the TP interface is not directly connected to either SPI bus. Bodmers library assumes the TP is connected to the same bus as the TFT which is what most people seem to do.

I've been trying to get some sort of software SPI running to talk to the XPT2046 and put the recieved data out to the serial monitor without success. The idea is to then patch that into Bodmers touch extension/library. Being fairly new to this Cxx malarky that's not going well.
Hopefully Bodmer will get there first!!!

I have a suspicion other examples for this board which use the TP open up multiple instances of the TFT/TP library for the SD/TFT/TP components. I'm assuming the TP instance uses the pin multiplexer to access the 2046 'bus'.

I've written code to exercise the TFT and TP using seperate TFT/TP and ESP32 that works fine on the combined SPI bus using Bodmers library.
I might just resort to programming a PIC in assembler to get the 2046 running and translate that.

I have got this resolved.
The fundemental problem is that the TFT and touch busses are on different pins. Cutting tracks is a bit desperate, a software solution to live with the existing hardware is better.
I thought about trying to open up seperate instances of the library but given 'C' of any flavour is not my bag, that didn't last long.
In the end, I have tweaked Bodmers library - specifically Touch.cpp and setup.h - to include banging the touch screen lines in software.
I'm sure you 'C' gurus will find it quite horrible but it works.
If someone can give me a cretins guide as to how to post the resulting files on here I'll do just that.

I just got as far as this problem this weekend also. I can get HASPanelto run on this display, but Iam trying to get FreeTouchDeck to run on it - which leads me to the same problem you are experiencing. It would be great if you could share your fix.
You could always paste the 2 files in CODE braces on the forum?

I've copied the modified front end of Touch.ccp and the modified part of setup. There are lines top and bottom so you can align the paste. Hope this helps.

Here goes :-

This is my new Touch.cpp from the first line although only from Sspixfer has changed
There's a section for User_setup.h at the end



// The following touch screen support code by maxpautsch was merged 1/10/17
// https://github.com/maxpautsch

// Define TOUCH_CS is the user setup file to enable this code

// A demo is provided in examples Generic folder

// Additions by Bodmer to double sample, use Z value to improve detection reliability
// and to correct rotation handling

// See license in root directory.

/***************************************************************************************
** Function name:           begin_touch_read_write - was spi_begin_touch
** Description:             Start transaction and select touch controller
***************************************************************************************/
// The touch controller has a low SPI clock rate
inline void TFT_eSPI::begin_touch_read_write(void){
  DMA_BUSY_CHECK;
  CS_H; // Just in case it has been left low
  #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS)
    if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));}
  #else
    spi.setFrequency(SPI_TOUCH_FREQUENCY);
  #endif
  SET_BUS_READ_MODE;
  T_CS_L;
}

/***************************************************************************************
** Function name:           end_touch_read_write - was spi_end_touch
** Description:             End transaction and deselect touch controller
***************************************************************************************/
inline void TFT_eSPI::end_touch_read_write(void){
  T_CS_H;
  #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS)
    if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}}
  #else
    spi.setFrequency(SPI_FREQUENCY);
  #endif
  //SET_BUS_WRITE_MODE;
}

uint16_t SPIdout;
uint16_t SPIdin;
//uint16_t dout;

/**************************************************************************************
** Function name:           Legacy - deprecated
** Description:             Start/end transaction
***************************************************************************************/
void TFT_eSPI::spi_begin_touch() {begin_touch_read_write();}
void TFT_eSPI::spi_end_touch()   {  end_touch_read_write();}


/***************************************************************************************
** Function name:           Sspixfer
** Description:             software SPI transfer. 
***************************************************************************************/

void Sspixfer (uint16_t dout)    // Exchange 8 bits of data over SPI
{

//  uint16_t tmp;                    // Data in
uint16_t SPImask = 0x80;         // Set bit mask
SPIdout = dout;				 // Set data to go
for (uint8_t lpcnt = 0; lpcnt < 8; lpcnt ++)   // Do 8 bits
{
digitalWrite (TOUCH_MOSI, ((SPIdout & SPImask) ? HIGH:LOW)); // Set up data out
SPImask = (SPImask >> 1);        // Mask for next bit
digitalWrite(TOUCH_CLK,1);       // CLK = 1
//tmp = (tmp << 1);                // Shift existing data along
SPIdin = (SPIdin << 1);                // Shift existing data along
digitalWrite(TOUCH_CLK,0);       // CLK = 0
ets_delay_us(1);                 // Delay
// tmp |= digitalRead(TOUCH_MISO);  // Shift data in
SPIdin |= digitalRead(TOUCH_MISO);  // Shift data in
}                                // Go round again
}                                // All done


/***************************************************************************************
** Function name:           getTouchRaw
** Description:             read raw touch position.  Always returns true.
***************************************************************************************/
uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){
  uint16_t tmp;

#ifdef SOFTSPI

 digitalWrite(TOUCH_CS,0); 
  Sspixfer(0xD0);            // Start new YP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0xD0);            // Read last 8 bits and start new YP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0xD0);            // Read last 8 bits and start new YP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0xD0);            // Read last 8 bits and start new YP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0x90);            // Read last 8 bits and start new XP conversion

  *x  = SPIdin >>4;          // Transfer and re-align data  
  
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0x90);            // Read last 8 bits and start new XP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0x90);            // Read last 8 bits and start new XP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0x90);            // Read last 8 bits and start new XP conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0);               // Read last 8 bits

  *y  = SPIdin >>4;          // Transfer and re-align data 
  digitalWrite(TOUCH_CS,1);

#else

  begin_touch_read_write();
  
// Start YP sample request for x position, read 4 times and keep last sample
  spi.transfer(0xd0);        // Start new YP conversion
  spi.transfer(0);           // Read first 8 bits
  spi.transfer(0xd0);        // Read last 8 bits and start new YP conversion
  spi.transfer(0);           // Read first 8 bits
  spi.transfer(0xd0);        // Read last 8 bits and start new YP conversion
  spi.transfer(0);           // Read first 8 bits
  spi.transfer(0xd0);        // Read last 8 bits and start new YP conversion

  tmp = spi.transfer(0);     // Read first 8 bits
  tmp = tmp <<5;
  tmp |= 0x1f & (spi.transfer(0x90)>>3);  // Read last 8 bits and start new XP conversion

  *x = tmp;

// Start XP sample request for y position, read 4 times and keep last sample
  spi.transfer(0);            // Read first 8 bits
  spi.transfer(0x90);         // Read last 8 bits and start new XP conversion
  spi.transfer(0);            // Read first 8 bits
  spi.transfer(0x90);         // Read last 8 bits and start new XP conversion
  spi.transfer(0);            // Read first 8 bits
  spi.transfer(0x90);         // Read last 8 bits and start new XP conversion

  tmp = spi.transfer(0);      // Read first 8 bits
  tmp = tmp <<5;
  tmp |= 0x1f & (spi.transfer(0)>>3);    // Read last 8 bits

  *y = tmp;

  end_touch_read_write();

  #endif

  return true;
}

/***************************************************************************************
** Function name:           getTouchRawZ
** Description:             read raw pressure on touchpad and return Z value. 
***************************************************************************************/
uint16_t TFT_eSPI::getTouchRawZ(void){

#if defined SOFTSPI

  int16_t tz = 0xFFF;

 digitalWrite(TOUCH_CS,0); 
  Sspixfer(0xb0);            // Start new Z1 conversion
  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0xc0);            // Read last 8 bits and start Z2 conversion
  tz += (SPIdin >>4);

  Sspixfer(0);               // Read first 8 bits
  Sspixfer(0);               // Read last 8 bits
  tz -= (SPIdin >>4);

 digitalWrite(TOUCH_CS,1); 

//  tz += Sspixfer16(0xc0) >> 3;  // Read Z1 and start Z2 conversion
//  tz -= Sspixfer16(0x00) >> 3;  // Read Z2

#else

  begin_touch_read_write();

// Z sample request
  int16_t tz = 0xFFF;
 
 spi.transfer(0xb0);               // Start new Z1 conversion
  tz += spi.transfer16(0xc0) >> 3;  // Read Z1 and start Z2 conversion
  tz -= spi.transfer16(0x00) >> 3;  // Read Z2

#endif

  end_touch_read_write();

  if (tz == 4095) tz = 0;

  return (uint16_t)tz;
}

/***************************************************************************************
** Function name:           validTouch






This part into User_setup.h

// For ESP32 Dev board (only tested with ILI9341 display)
// The hardware SPI can be mapped to any pins

// #define TFT_MISO -1 
// #define TFT_MOSI 14
// #define TFT_SCLK 33
// #define TFT_CS   -1  // Chip select control pin
// #define TFT_DC    13  // Data Command control pin
// #define TFT_RST   12  // Reset pin (could connect to RST pin)
//#define TFT_RST  -1  // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST

// For ESP32 Dev board (only tested with GC9A01 display)
// The hardware SPI can be mapped to any pins

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Working display pins

#define TFT_MOSI 13 // Might be written as "SDA" and so on.
#define TFT_MISO 12
#define TFT_SCLK 14
#define TFT_CS   15  // Chip select control pin
#define TFT_DC   2  // Data Command control pin
#define TFT_RST  -1  // 12 Reset pin (could connect to Arduino RESET pin)
#define TFT_BL   21  // LED back-light

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//#define TFT_MOSI 32 
//#define TFT_SCLK 25
//#define TFT_CS   33  
//#define TFT_DC   2
//#define TFT_RST  39
//#define TFT_BL   21

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

#define TOUCH_CS 33     // Chip select pin (T_CS) of touch screen

#define SOFTSPI		// Uncomment for software SPI

#define TOUCH_MOSI 32
#define TOUCH_MISO 39
#define TOUCH_CLK 25


//#define TFT_WR 22    // Write strobe for modified Raspberry Pi TFT only






Many thanks. Took me a while to get working as I needed to set pinMode for the touchscreen pins:
I amended TFT_eSPI.cpp as follows:

// Configure chip select for touchscreen controller if present
#ifdef TOUCH_CS
  pinMode(TOUCH_CS, OUTPUT);
  digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
  
  pinMode(TOUCH_MOSI, OUTPUT);	
  pinMode(TOUCH_MISO, INPUT);
  pinMode(TOUCH_CLK, OUTPUT);
  
  
#endif

..might be somewhere better to do this but it works for now. Thanks again.

Sorry about that - as you gather, I setup the pin modes and output levels in the initial setup and I forgot to include that bit. The main thing is it works. I thought about trying to change the pins using the IO mux but details on how to do that are sketchy. The SW SPI seemed easiest and leaves the HW SPIs for the TFT and SD card.
Have fun!

Thank you so much, you made my day, I do some research and found that XPT2046 use a different SPI bus from ILI9431. and modify "Touch.cpp" and "User_setup.h" as you post get touch screen to work now.

Hi @s_nelson,

thank you very much for working out a solution.

I did a content-compare of the original touc.cpp and the code you posted in post #6

The orginal touch.cpp has more functions. Now I'm unsure what to replace and what not
Would you mind to post the full touch.cpp from the very first to the very last line of code
so opening the original touch.cpp
then
deleing the content with Ctrl-A, delete
copy the complete modified code of touch.cpp from a code-section
and paste it into the (now completely empty ) local copy of rouch.cpp)
then saving touch.cpp
makes sure that everying is correct?

Can this be done with the User_setup.h-file too?
or does the User_setup.h-file needs different modifications depending on (whatever?)

best regards Stefan

100% work
Touch.cpp
User_setup.h

Hi @ratthanin,

thank you very much.
After replacing the Touch.cpp and the user_setup.h
I successfully tested the Touch_button_ILI9341_LovyanGFX-example code
I added constants and if-conditions for setting up the correct values for height and width
dependand on the orientation

/////////////////////////////////////////////////////////////////
/*
  ESP32 | LVGL8 | Ep 0. GFX Setup (ft. LovyanGFX)
  Video Tutorial: https://youtu.be/IPCvQ4o_WP8
  Created by Eric N. (ThatProject)
*/
/////////////////////////////////////////////////////////////////
//To download the LovyanGFX library before use//
#include <lvgl.h>
#define LGFX_USE_V1
#include <LovyanGFX.hpp>

class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ILI9341     _panel_instance;
    lgfx::Bus_SPI       _bus_instance;   // SPI bus instance // SPIバスのインスタンス
    lgfx::Light_PWM     _light_instance;
    lgfx::Touch_XPT2046     _touch_instance;

  public:
    LGFX(void)
    {
      { // バス制御の設定を行います。
        auto cfg = _bus_instance.config();    // Gets the structure for bus configuration. // バス設定用の構造体を取得します。
        cfg.spi_host = HSPI_HOST;     // Select the SPI to use // 使用するSPIを選択  (VSPI_HOST or HSPI_HOST)
        cfg.spi_mode = 0;             // Set SPI communication mode (0 ~ 3) // SPI通信モードを設定 (0 ~ 3)
        cfg.freq_write = 55000000;    // SPI clock at the time of transmission (up to 80MHz, rounded to the value obtained by dividing 80MHz by an integer) // 送信時のSPIクロック (最大80MHz, 80MHzを整数で割った値に丸められます)
        cfg.freq_read  = 20000000;    // SPI clock when receiving // 受信時のSPIクロック
        cfg.spi_3wire  = false;       // Set true when receiving with MOSI pin // 受信をMOSIピンで行う場合はtrueを設定
        cfg.use_lock   = true;        // Set to true when using transaction lock // トランザクションロックを使用する場合はtrueを設定
        cfg.dma_channel = 1;          // Set the DMA channel (1 or 2. 0=disable) // 使用するDMAチャンネルを設定 (0=DMA不使用)
        cfg.pin_sclk = 14;            // Set SPI SCLK pin number // SPIのSCLKピン番号を設定
        cfg.pin_mosi = 13;            // Set SPI MOSI pin number // SPIのMOSIピン番号を設定
        cfg.pin_miso = 12;            // Set SPI MISO pin number (-1 = disable) // SPIのMISOピン番号を設定 (-1 = disable)
        cfg.pin_dc   = 2;             // Set SPI D / C pin number (-1 = disable) // SPIのD/Cピン番号を設定  (-1 = disable)

        _bus_instance.config(cfg);    // The set value is reflected on the bus. // 設定値をバスに反映します。
        _panel_instance.setBus(&_bus_instance);      // Set the bus on the panel. // バスをパネルにセットします。
      }

      { // Set the display panel control.//表示パネル制御の設定を行います。
        auto cfg = _panel_instance.config();    // Gets the structure for display panel settings.// 表示パネル設定用の構造体を取得します。
        cfg.pin_cs           =    15;  // Pin number to which CS is connected (-1 = disable) // CSが接続されているピン番号   (-1 = disable)
        cfg.pin_rst          =    -1;  // Pin number to which RST is connected (-1 = disable) // RSTが接続されているピン番号  (-1 = disable)
        cfg.pin_busy         =    -1;  // Pin number to which BUSY is connected (-1 = disable) // BUSYが接続されているピン番号 (-1 = disable)
        cfg.memory_width     =   240;  // Maximum width supported by driver IC // ドライバICがサポートしている最大の幅
        cfg.memory_height    =   320;  // Maximum height supported by driver IC // ドライバICがサポートしている最大の高さ
        cfg.panel_width      =   240;  // Actually displayable width // 実際に表示可能な幅
        cfg.panel_height     =   320;  // Actually displayable height // 実際に表示可能な高さ
        cfg.offset_x         =     0;  // Amount of X-direction offset of the panel // パネルのX方向オフセット量
        cfg.offset_y         =     0;  // Amount of Y-direction offset of the panel // パネルのY方向オフセット量
        cfg.offset_rotation  =     0;  // Offset of values in the direction of rotation 0 ~ 7 (4 ~ 7 are upside down) // 回転方向の値のオフセット 0~7 (4~7は上下反転)
        cfg.dummy_read_pixel =     8;  // Number of dummy read bits before pixel reading // ピクセル読出し前のダミーリードのビット数
        cfg.dummy_read_bits  =     1;  // Number of bits of dummy read before reading data other than pixels // ピクセル以外のデータ読出し前のダミーリードのビット数
        cfg.readable         =  true;  // Set to true if data can be read // データ読出しが可能な場合 trueに設定
        cfg.invert           = false;  // Set to true if the light and darkness of the panel is reversed // パネルの明暗が反転してしまう場合 trueに設定
        cfg.rgb_order        = false;  // Set to true if the red and blue of the panel are swapped // パネルの赤と青が入れ替わってしまう場合 trueに設定
        cfg.dlen_16bit       = false;  // Set to true for panels that send data length in 16-bit units // データ長を16bit単位で送信するパネルの場合 trueに設定
        cfg.bus_shared       =  true;  // If the bus is shared with the SD card, set to true (bus control is performed with drawJpgFile etc.) // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います)

        _panel_instance.config(cfg);
      }

      { // Set the backlight control. (Delete if not needed // バックライト制御の設定を行います。(必要なければ削除)
        auto cfg = _light_instance.config();    // Gets the structure for the backlight setting. // バックライト設定用の構造体を取得します。

        cfg.pin_bl = 21;              // Pin number to which the backlight is connected // バックライトが接続されているピン番号
        cfg.invert = false;           // True if you want to invert the brightness of the backlight // バックライトの輝度を反転させる場合 true
        cfg.freq   = 44100;           // Backlight PWM frequency // バックライトのPWM周波数
        cfg.pwm_channel = 7;          // PWM channel number to use // 使用するPWMのチャンネル番号

        _light_instance.config(cfg);
        _panel_instance.setLight(&_light_instance);  // Set the backlight on the panel. // バックライトをパネルにセットします。
      }

      { // Set the touch screen control. (Delete if not needed) // タッチスクリーン制御の設定を行います。(必要なければ削除)
        auto cfg = _touch_instance.config();
        cfg.x_min      = 0;    // Minimum X value (raw value) obtained from touch screen // タッチスクリーンから得られる最小のX値(生の値)
        cfg.x_max      = 239;  // Maximum X value (raw value) obtained from the touch screen // タッチスクリーンから得られる最大のX値(生の値)
        cfg.y_min      = 0;    // Minimum Y value (raw value) obtained from touch screen // タッチスクリーンから得られる最小のY値(生の値)
        cfg.y_max      = 319;  // Maximum Y value (raw value) obtained from the touch screen // タッチスクリーンから得られる最大のY値(生の値)
        cfg.pin_int    = 36;   // Pin number to which INT is connected // INTが接続されているピン番号
        cfg.bus_shared = true; // Set to true if you are using the same bus as the screen // 画面と共通のバスを使用している場合 trueを設定
        cfg.offset_rotation = 0;// Adjustment when the display and touch orientation do not match Set with a value from 0 to 7 // 表示とタッチの向きのが一致しない場合の調整 0~7の値で設定
        cfg.spi_host = VSPI_HOST;// Select the SPI to use (HSPI_HOST or VSPI_HOST) // 使用するSPIを選択 (HSPI_HOST or VSPI_HOST)
        cfg.freq = 2500000;     // Set SPI clock // SPIクロックを設定
        cfg.pin_sclk = 25;     // Pin number to which SCLK is connected // SCLKが接続されているピン番号
        cfg.pin_mosi = 32;     // Pin number to which MOSI is connected // MOSIが接続されているピン番号
        cfg.pin_miso = 39;     // Pin number to which MISO is connected // MISOが接続されているピン番号
        cfg.pin_cs   = 33;     // Pin number to which CS is connected // CSが接続されているピン番号

        _touch_instance.config(cfg);
        _panel_instance.setTouch(&_touch_instance);  // Set the touch screen on the panel. // タッチスクリーンをパネルにセットします。
      }
      setPanel(&_panel_instance); // Set the panel to be used. // 使用するパネルをセットします。
    }
};

LGFX tft;

/*Change to your screen resolution*/
static const uint32_t screenWidth  = 240;
static const uint32_t screenHeight = 320;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * 10 ];

/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  tft.startWrite();
  tft.setAddrWindow( area->x1, area->y1, w, h );
  //tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
  tft.writePixels((lgfx::rgb565_t *)&color_p->full, w * h);
  tft.endWrite();

  lv_disp_flush_ready( disp );
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
  uint16_t touchX, touchY;
  bool touched = tft.getTouch( &touchX, &touchY);
  if ( !touched )
  {
    data->state = LV_INDEV_STATE_REL;
  }
  else
  {
    data->state = LV_INDEV_STATE_PR;

    /*Set the coordinates*/
    data->point.x = touchX;
    data->point.y = touchY;

    Serial.print( "Data x " );
    Serial.println( touchX );

    Serial.print( "Data y " );
    Serial.println( touchY );
  }
}

const byte portrait_connector_top    = 0;
const byte landscape_connector_left  = 1;
const byte portrait_connector_bottom = 2;
const byte landscape_connector_right = 3;

byte screenOrientation = landscape_connector_right;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  tft.begin();
  tft.setRotation(screenOrientation);
  tft.setBrightness(255);
  uint16_t calData[] = { 239, 3926, 233, 265, 3856, 3896, 3714, 308};
  tft.setTouchCalibrate(calData);
  //touch_calibrate();//屏幕校准
  lv_init();
  lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 10 );

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);


  if (     screenOrientation == portrait_connector_top
           || screenOrientation == portrait_connector_bottom) {
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
  }
  else {
    disp_drv.hor_res = screenHeight;
    disp_drv.ver_res = screenWidth;
  }

  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

  lv_example_get_started_1();
}

void loop() {
  lv_timer_handler(); /* let the GUI do its work */
  delay( 5 );
}

static void btn_event_cb(lv_event_t * e) {
  lv_event_code_t code = lv_event_get_code(e);
  lv_obj_t * btn = lv_event_get_target(e);

  if (code == LV_EVENT_CLICKED) {
    static uint8_t cnt = 0;
    cnt++;

    /*Get the first child of the button which is the label and change its text*/
    lv_obj_t * label = lv_obj_get_child(btn, 0);
    lv_label_set_text_fmt(label, "Button: %d", cnt);
  }
}

// Create a button with a label and react on click event.
void lv_example_get_started_1(void) {
  lv_obj_t * btn = lv_btn_create(lv_scr_act());     /*Add a button the current screen*/
  lv_obj_set_size(btn, 120, 50);                          /*Set its size*/
  lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);
  lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);           /*Assign a callback to the button*/

  lv_obj_t * label = lv_label_create(btn);          /*Add a label to the button*/
  lv_label_set_text(label, "Button");                     /*Set the labels text*/
  lv_obj_center(label);
}

best regards Stefan

I posted only the new front end of Touch.cpp. Find the last line of my posted file in the original Touch.cpp and delete up to there. Then paste in the post and you have a new Touch.cpp.
You're replacing everything from the start up to that line.

Find the first and last line of my post in the original User_Setup.h and paste in my modified section. Delete between the two and paste in the new.

Then of course you have to add pin configuration/setup to your program.

Maybe I sould have posted the complete files - thanks ratthanin.

One of the benefits of this solution is that it leaves the hardware SPI ports free to service the TFT and SD ports.

Hallo liebe Programmierer,
ich habe ebenfalls das Board 2432S028 und damit das gleiche Problem.
Ich habe die beiden Dateien von Frau Ratthanin benutzt und es funktioniert auch bei mir.
Der Touch-Bus muss mit einer zusätzlichen Änderung in TFT_eSPI.cpp initialisiert werden.
Das kann an der Stelle bei der der CS-Ausgang gesetzt wird geschehen.
VG

#ifdef TOUCH_CS
  if (TOUCH_CS >= 0) {
    pinMode(TOUCH_CS, OUTPUT);
    digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
    pinMode(TOUCH_MOSI, OUTPUT);	
    digitalWrite(TOUCH_MOSI, HIGH); // Chip select high (inactive)
    pinMode(TOUCH_MISO, INPUT);
    pinMode(TOUCH_CLK, OUTPUT);
    digitalWrite(TOUCH_CLK, HIGH); // Chip select high (inactive)
  }
#endif

Ich habe eine Bitte:

Kannst du die gesamte Datei mit Nennung des Dateipfades und Dateinamens posten in der diese Änderung gemacht wird ?

Wenn da nur dieser Code-Schnipsel steht macht sich jeder neu auf die Suche nach der Datei und der Stelle in der Datei an der das dann sinnvollerweise eingefügt wird.

vgs

Hallo liebe Maker,
ich benutze linux mint + VSC + platformio.
Bei mir ist der Pfad + Dateiname wie folgt:

/Dokumente/PlatformIO/Projects/Esp32TFT-2432SO28-R-Tst-Touch/.pio/libdeps/esp32dev/TFT_eSPI/TFT_eSPI.cpp

in der ursprünglichen Datei "TFT_eSPI.cpp" steht an Zeile 542 folgender Code:

// Configure chip select for touchscreen controller if present
#ifdef TOUCH_CS
  if (TOUCH_CS >= 0) {
    pinMode(TOUCH_CS, OUTPUT);
    digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
  }
#endif

Diesen Code habe ich erweitert zu:

// Configure chip select for touchscreen controller if present
#ifdef TOUCH_CS
  if (TOUCH_CS >= 0) {
    pinMode(TOUCH_CS, OUTPUT);
    digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
    pinMode(TOUCH_MOSI, OUTPUT);	
    digitalWrite(TOUCH_MOSI, HIGH);
    pinMode(TOUCH_MISO, INPUT);
    pinMode(TOUCH_CLK, OUTPUT);
    digitalWrite(TOUCH_CLK, HIGH);
  }
#endif

Vermutlich genügt auch folgendes:

// Configure chip select for touchscreen controller if present
#ifdef TOUCH_CS
  if (TOUCH_CS >= 0) {
    pinMode(TOUCH_CS, OUTPUT);
    digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive)
    pinMode(TOUCH_MOSI, OUTPUT);	
    pinMode(TOUCH_MISO, INPUT);
    pinMode(TOUCH_CLK, OUTPUT);
  }
#endif

Jetzt ist die Datei "TFT_eSPI.cpp" um drei Zeilen länger.

Mit dieser Lösung steht in der Haupt-Datei "main.cpp" unter "setup" nichts von

pinMode(TOUCH_MOSI, OUTPUT);

usw., was mir besser gefällt.

Als Testprogramm habe ich "OnOffButton" aus der Lib "TFT_eSPI" verwendet.
Dabei muss man darauf achten an welche Position der Button bemalt wird:

// Switch position and size für ein 320x240-Display

#define FRAME_X 220

#define FRAME_Y 120

#define FRAME_W 80

#define FRAME_H 30

VG Hans

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