Not able to detect gesture on ESP32 with CST816S

What do you want to achieve?

I want to detect swipe gestures (left, right, up, down) on my CST816S touch display. My ultimate goal is to use these gestures to navigate between different screens.

What have you tried so far?

I have followed the instructions from this doc.

My touch driver for the CST816S is working. I can successfully detect both LV_EVENT_PRESSED and LV_EVENT_PRESSING and can read the correct x,y coordinates. However, gestures are not being detected.

Not mentioned in docs but have also enabled LV_USE_GESTURE_RECOGNITION also in lv_conf.h

Code to reproduce

// main.cpp

#include <Arduino.h>
#include "app/app.h"
#include <lvgl.h>
#include "hal/display/display_setup.h"
#include "hal/display/touch_setup.h"
#include "hal/display/lvgl_setup.h"
#include "app/ui/home/home_fragment.h"

App myApp;

void home()
{
    lv_obj_t *root = lv_obj_create(lv_screen_active());
    lv_obj_set_size(root, 240, 240);
    auto *manager = lv_fragment_manager_create(NULL);
    lv_fragment_t *fragment = lv_fragment_create(HomeFragment::getLvFragment(), NULL);
    lv_fragment_manager_push(manager, fragment, &root);
}

static void debug_touch_cb(lv_event_t *e)
{
    lv_point_t p;
    lv_indev_get_point(lv_event_get_indev(e), &p);
    Serial.printf("Touch: x=%d y=%d\n", p.x, p.y);
}

static void gesture_event_cb(lv_event_t *e)
{
    lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_active());
    switch (dir)
    {
    case LV_DIR_LEFT:
        Serial.println("Gesture: Swipe Left");
        break;
    case LV_DIR_RIGHT:
        Serial.println("Gesture: Swipe Right");
        break;
    case LV_DIR_TOP:
        Serial.println("Gesture: Swipe Up");
        break;
    case LV_DIR_BOTTOM:
        Serial.println("Gesture: Swipe Down");
        break;
    default:
        Serial.println("Gesture: None");
        break;
    }
}

void create_touch_test_screen()
{
    lv_obj_t *root = lv_obj_create(lv_scr_act());
    lv_obj_set_size(root, 240, 240);
    lv_obj_center(root);

    lv_obj_remove_flag(root, LV_OBJ_FLAG_SCROLLABLE);
    lv_obj_set_scroll_dir(root, LV_DIR_NONE);
    lv_obj_set_scrollbar_mode(root, LV_SCROLLBAR_MODE_OFF);

    lv_obj_add_event_cb(root, gesture_event_cb, LV_EVENT_GESTURE, NULL);
    lv_obj_add_event_cb(root, debug_touch_cb, LV_EVENT_PRESSED, NULL);
    lv_obj_add_event_cb(root, debug_touch_cb, LV_EVENT_PRESSING, NULL);
}

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

    displaySetup();
    touchSetup();
    lvglSetup();

    // home();
    create_touch_test_screen();
}

void loop()
{
    lv_timer_handler();
    delay(10);
}

// Callback function(lv_indev_set_read_cb)

void touchCallback(lv_indev_t *indev, lv_indev_data_t *data)
{
    if (touchpad.available())
    {
        uint16_t x = touchpad.x;
        uint16_t y = touchpad.y;
        data->point.x = x;
        data->point.y = y;
        data->state = LV_INDEV_STATE_PRESSED;
    }
    else
    {
        data->state = LV_INDEV_STATE_RELEASED;
    }
}

Screenshot and/or video

Environment

  • MCU/MPU/Board: ESP32 Dev Board
  • LVGL version: 9.3.0

You are not reading gestures from the touch screen. you are only reading points…

I don’t understand, could you please elaborate?

FYI, the attached video might be confusing as it prints x, y coordinates from LV_EVENT_PRESSED and LV_EVENT_PRESSING events.

I dont get anything from LV_EVENT_GESTURE callback.

code ref,

lv_obj_add_event_cb(root, gesture_event_cb, LV_EVENT_GESTURE, NULL); // DOES NOT WORK
lv_obj_add_event_cb(root, debug_touch_cb, LV_EVENT_PRESSED, NULL); // works
lv_obj_add_event_cb(root, debug_touch_cb, LV_EVENT_PRESSING, NULL); // works

https://docs.lvgl.io/master/details/main-modules/indev.html#multi-touch-gestures-overview

Thank you @kdschlosser for pointing me to this info. I’m very new to LVGL and embedded programming in general, so the example in the docs wasn’t fully clear to me.

I spent 2 days trying to set up gesture recognition as shown in the docs but haven’t been successful yet.

Here’s what I changed in my callback,

void touchCallback(lv_indev_t *indev, lv_indev_data_t *data)
{
    lv_indev_touch_data_t cur;
    if (touchpad.available())
    {
        cur.point.x = touchpad.x;
        cur.point.y = touchpad.y;
        cur.state = LV_INDEV_STATE_PRESSED;
    }
    else
    {
        cur.point.x = 0;
        cur.point.y = 0;
        cur.state = LV_INDEV_STATE_RELEASED;
    }

    cur.timestamp = lv_tick_get();
    cur.id = 0; // I want single finger swipe

    data->state = cur.state;
    data->point.x = cur.point.x;
    data->point.y = cur.point.y;

    // passing 1 as I want single finger swipe
    lv_indev_gesture_recognizers_update(indev, &cur, 1); 
    lv_indev_gesture_recognizers_set_data(indev, data);
}

I’m still not able to detect gestures.
Please help me in getting this resolved. Thanks