Strange behavior of touch


currently working for a smart file manager GUI
i manage to build a simple GUI for file manager where i can access my SD card files using esp32 and SD card adapter.

What MCU/Processor/Board and compiler are you using?

ESP32 and ILI9341 Display

What LVGL version are you using?


What do you want to achieve?

how touch work properly after 10 clicks

What have you tried so far?

implementation of simple GUI.

Code to reproduce

The code block(s) should be formatted like:

#include "GUI.h"
#include <SD.h>
#include <FS.h>
TFT_Gui dir;

String nextFile;

TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
// TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
static lv_color_t buf2[LV_HOR_RES_MAX * 10];

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
  uint16_t c;
  tft.startWrite();                                    /* Start new TFT transaction */
  tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */
  for (int y = area->y1; y <= area->y2; y++)
    for (int x = area->x1; x <= area->x2; x++)
      c = color_p->full;
      tft.writeColor(c, 1);
  tft.endWrite();            /* terminate TFT transaction */
  lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */

bool my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
  uint16_t touchX, touchY;
  bool touched = tft.getTouch(&touchX, &touchY, 600U);
  if (!touched){
    // Serial.printf("touch false \r\n");
    return false;
  if (touchX > SCREEN_WIDTH || touchY > SCREEN_HIGHT) {
    Serial.println("Y or y outside of expected parameters..");
    Serial.print(" x:");
  }else {
    data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
    /*Set the coordinates (if released use the last pressed coordinates)*/
    data->point.x = touchX;
    data->point.y = touchY;
    Serial.printf(" data->point.x = %u \r\n",touchX);
    Serial.printf(" data->point.y = %u \r\n",touchY);
  return false; /*Return `false` because we are not buffering and no more data to read*/

void guiInIt() {

    tft.begin(); /* TFT init */

    //uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
    uint16_t calData[5] = {378U, 3539U, 743U, 2724U, 7U};
    lv_disp_buf_init(&disp_buf, buf, buf2, LV_HOR_RES_MAX * 10);
    /*Initialize the display*/
    lv_disp_drv_t disp_drv;
    disp_drv.hor_res = SCREEN_WIDTH;
    disp_drv.ver_res = SCREEN_HIGHT;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.buffer = &disp_buf;
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);          /*Descriptor of a input device driver*/
    indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;   /*Set your driver function*/
    lv_indev_drv_register(&indev_drv);      /*Finally register the driver*/

bool TFT_Gui::initSD() {
  if (!SD.begin(SS)) {
    return false;
  return true;

String TFT_Gui::openFile(String filename) {
  File file =;
  if (!file) {
    return "";
  String textData;
  while (file.available()) {
    textData += char(;
  return textData;

void TFT_Gui::lvErrorPage() {
  lv_obj_t *label = lv_label_create(lv_scr_act(), NULL);
  lv_label_set_text(label, "Please check your SD Card");
  lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);

void TFT_Gui::refreshList(String fileName) {
  if (list != NULL) {
  File root =;
  File file = root.openNextFile();
  while (file) {
      nextFile =;
      // Serial.printf("nextFile in file.isDirectory() = %s \r\n",nextFile.c_str());
      int n = nextFile.lastIndexOf('/');
      int m = nextFile.length();
      String tempName = nextFile.substring(n ,m);
      lv_obj_t * list_btn = lv_list_add_btn(list, LV_SYMBOL_DIRECTORY , (const char *)tempName.c_str());
      // Serial.printf("next directory is %s \r\n",nextFile.c_str());
      lv_obj_set_event_cb(list_btn, event_handler1);
    } else {
      String nextFile1 =;
      int n = nextFile1.lastIndexOf('/');
      int m = nextFile1.length();
      String tempName = nextFile1.substring(n ,m);
      lv_list_add_btn(list, LV_SYMBOL_FILE , (const char *)tempName.c_str());
    file = root.openNextFile();

void TFT_Gui::createTab1(lv_obj_t *parent,String fileName)
  //List Tab
  lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP);
  list = lv_list_create(parent, NULL);
  lv_obj_set_size(list, lv_obj_get_width(parent) - 20, lv_obj_get_height(parent) - 20);
  lv_obj_align(list, NULL, LV_ALIGN_IN_TOP_LEFT, 10, 10);


void TFT_Gui::lv_file_browser(String fileName)
    /* Create a window to use as the action bar */
    win = lv_win_create(lv_scr_act(), NULL);
    lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
    lv_win_set_title(win, "File Manager");
    lv_obj_t * up_btn = lv_win_add_btn(win, LV_SYMBOL_UP);
    lv_obj_set_event_cb(up_btn, go_up);
    lv_obj_t * home = lv_win_add_btn(win, LV_SYMBOL_HOME);
    lv_obj_set_event_cb(home, homeDir);
    lv_obj_t * win_content = lv_win_get_content(win);
    lv_cont_set_fit(lv_page_get_scrl(win_content), _LV_FIT_LAST);
    /* Create the list */
    main_list = lv_list_create(win, NULL);
    /* Fit the list inside the page, taking into account any borders. */
    lv_area_t page_area;
    lv_obj_get_coords(win_content, &page_area);
    lv_obj_get_inner_coords(win_content, &page_area);
    lv_obj_set_size(main_list, lv_area_get_width(&page_area), lv_area_get_height(&page_area));

static void event_handler1(lv_obj_t * obj, lv_event_t event)
    if(event == LV_EVENT_CLICKED) {
      // Serial.printf("Clicked: %s\n", lv_list_get_btn_text(obj));

static void homeDir(lv_obj_t * obj, lv_event_t event){
  if(event == LV_EVENT_CLICKED) {
    // Serial.printf("Clicked: %s\n", lv_list_get_btn_text(obj));

static void go_up(lv_obj_t * obj, lv_event_t event){
    if(event == LV_EVENT_CLICKED) {
      int n = nextFile.lastIndexOf('/');
      String backDir = nextFile.substring(0,n);
      Serial.printf("len is %d and  backDir is %s \r\n",n,backDir.c_str());
      if (n==0) {
        nextFile = backDir;

Screenshot and/or video

you can see at the and display got freeze
see this link

video link

I had something a little similar happen, albeit with sdcard detection and not the touch screen itself:

I narrowed it down to the breadboard, which I specifically bought because it was of reputable high quality.
As soon as I integrated the setup in to a custom board the “ghost” went away.

Check your jumper wires?

thanks for reply

i will try it .


i checked all jumper wires . All works perfectly.
issue arrived after 10 click every time.

Is my_touchpad_read still being called after 10 clicks? If so, the issue is probably outside of LVGL.

@embeddedt NO, my_touchpad_read didn’t call aafter 10 clicks.

when i set
#define LV_MEM_CUSTOM 1
than now i can click 25 times and after that screen and esp both are freezed.

It sounds like you are running out of heap space. Perhaps you are recreating an object somewhere and not deleting the previous one?

when i try to delete object
screen crashed and got blank page.

this object is static and creating again and again

@embeddedt you are right
thanks for the help
i added lv_obj_clean(win); at every windows that creating again and again and issue of heap space finally solved.

I hope you are deleting (not just cleaning) the previous window in that case! Otherwise you have just delayed the problem, since the windows will slowly eat up heap.

You may want to look into lv_mem_monitor and print out the memory information like this. It may slow down your program a bit but it’s entirely worth it for the extra debugging insight.

yes you are right sir @embeddedt
i will do it
thank you.