TFT_eSPI and Adafruit Touchscreens - not compatible - Resolved

Hi All

I can't get TFT_eSPI to to work with Adafruit touchscreens. I've spend a day googling, and so far I've boiled it down to the fact that the TFT_eSPI library uses the XPT2046 controller (an SPI touchscreen controller) and the Adafruit screens all use the STMPE610 controller, which has a very different way of going about things.

All I can think of is to rewrite the functions in the library to implement the Adafruit way of doing things. Has anyone cracked this problem yet? The discussions I've seen on this come from 2018, so I kind of hoped it'd been implemented in the last 5 years, but maybe I missed it. Please help ... this is starting to make my brain hurt.

Our project is in Squareline studio, which is tightly coupled to LVGL and TFT_eSPI. I'm using a RP2040 Connect and a genuine Adafruit 480x320 screen. I've proven everything from Squareline Studio through to getting a widget on the screen of my microcontroller, and tested the touchscreen with the Adafruit examples, so I'm confident my connections are sound.

I haven't downloaded Squareline Studio yet (no time) but are you sure it ties you to TFT_eSPI?
The display interface to LVGL is through disp_drv.flush_cb() so as long as your graphics driver can push out a screenbuffer of data, you should be able to use any underlying library.

FWIW, I've used both TFT_eSPI and Arduino_GFX_Library with LVGL. Adafruit_GFX likely has something similar to TFT_eSPI's pushColors();

See if this helps you: GitHub - adafruit/Adafruit_LvGL_Glue: “Glue” library between LittlevGL and Adafruit GFX (SPITFT)

Hi CedarLakeInstruments.

I can definitely recommend Squareline Studio - for me, it makes putting together quality guis a doddle (or rather it seems to at first use) ... but of course, I've hit this issue. I did try just swapping TFT_eSPI tft = TFT_eSPI() to the Adafruit_GFX equivalent, and ran slap-bang in to the pushColors() point you mentioned ... I knew it couldn't be that easy. There is an implmentation of pushColours out there, and I might try plugging it in. I get a little twitchy branching libraries but ho-hum - needs must.

What I've also found is that TFT_eSPI's driver choice seems to be because that's the driver used in nearly all Raspberry Pi screens. It's not a bad choice given the proliferation of these screens. I've ordered an Elegoo screen for experimentation - if this works it keeps my library chain neat and unmodified.

It's a pity because I like the Adafruit ecosystem, but we need to get these devices built. I will give LVGL_glue a look today.

Thanks for taking the time to reply.

Hi Again

I tried the LittlevGL library and push-colours, but it bombed. Reading the docs, Squareline doesn't go back from LVGL version 8.x.x. down to 7.x.x. and when you read the readme in LVGL_glue, it is only listed as compatible with versions 7.x.x, and when I tried to compile it, it bombed.

Right - fixed it and got it working. Here's the summary of what's required. Firstly, I retained TST_eSPI because it's so tightly coupled to LVLM via Squareline studio.

When it comes to handling touchpad inputs It turns out LVLM is quite well thought out. To summarise what needs to happen, you need some form of notice that the screen has been pressed, and to send an X and Y point to LVLM, all done inside the function that's already been created. For an Adafruit screen, the touch comes from a pressure value (point.z > something), and the library gives raw data for points x and y. Then, translate X and Y (as you normally would) and put the values in data->point.x and data->point.y;

So, include all the <Touchscreen.h> definitions you would need. In my case, it's this:

#include <TouchScreen.h>
/*Don't forget to set Sketchbook location in File/Preferencesto the path of your UI project (the parent foder of this INO file)*/

/*Change to your screen resolution*/
static const uint16_t screenWidth = 480;
static const uint16_t screenHeight = 320;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[screenWidth * screenHeight / 10];

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char *buf) {
  Serial.printf(buf);
  Serial.flush();
}
#endif
/*Change to your screen resolution*/
static const uint16_t screenWidth = 480;
static const uint16_t screenHeight = 320;

// screen pins
#define YP A2  // must be an analog pin, use "An" notation!
#define XM A3  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 8   // can be a digital pin

#define TS_MINX 101
#define TS_MINY 188
#define TS_MAXX 908
#define TS_MAXY 883

#define MINPRESSURE 100
#define MAXPRESSURE 1000

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

Then, there' only one place to make an alteration, which is in the "my_touchpad_read" function. All LVLM needs to be told is the x and y coordinate, after being scaled and translated for screen orientation. Here's my complete version of "my_touchpad_read":

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
  uint16_t touchX = 0, touchY = 0;

  //bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );
  TSPoint p = ts.getPoint();
  bool touched = !(p.z < MINPRESSURE || p.z > MAXPRESSURE);

  touchX = map(p.y, TS_MAXX, TS_MINX, 0, screenWidth - 1);
  touchY = map(p.x, TS_MINY, TS_MAXY, 0, screenHeight - 1);
  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;

  }
}

That's it - works a treat. LVLM now sees and acts on screen touch events through the widgets.

1 Like

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