Touch Not Working

Description

I just discovered that I can use the core lvgl library in arduino and not use the lv_arduino library. (According to these instructions).

Using the core lvgl I can build but I’m running into a touch pad issue… I’m using a FT6206 capacitive touch device and I know its working because I can print its touch point in the main loop.

But I’m not getting any input in the my_touchpad_read function to the point where I feel like the function\callback is not being called at all. To test this theory, I put a print statement into the function and saw nothing in my output console. So I switched back to the lv_arduino library (same exact code, no changes) and the print statement and touch code worked as expected.

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

  • ST Nucleo 144 (STM32F767zi)
  • Arduino on PlatformIO IDE
  • ILI9488 3.5" SPI screen (480*320) with FT6206 touch
  • TFT_eSPI library for screen

What do you experience?

my_touchpad_read() is not called when using the core lvgl library. But simply switching out to the lv_arduino library with no code changes, the my_touchpad_read() works as expected.

What do you expect?

my_touchpad_read() works in both lvgl and lv_arduino libraries.

Code to reproduce

//Created by Hamid Saffari @ Apr 2020. https://github.com/HamidSaffari/ Released into the public domain.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "lvgl.h"
#include <TFT_eSPI.h>
#include <Adafruit_FT6206.h>

#define LED_PIN PB0

TFT_eSPI tft = TFT_eSPI(); /* TFT instance */

static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];

// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 touch = Adafruit_FT6206();

lv_obj_t * slider_label;
int screenWidth = 480;
int screenHeight = 320;
  
  
/* By Bodmer in https://github.com/Bodmer/TFT_eSPI/issues/581
   faster and more efficient than previous one: */
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();
 #ifdef USE_DMA
   tft.pushImageDMA(area->x1, area->y1, w, h, &color_p->full);
   // Note: tft.endWrite(); must be called in my_lv_tick_handler when DMA is complete
 #else
   tft.setAddrWindow(area->x1, area->y1, w, h);
   tft.pushColors(&color_p->full, w * h, true);
   tft.endWrite();
 #endif

  lv_disp_flush_ready(disp);
}

bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
{

  // int16_t touchX, touchY;
  TS_Point tp = touch.getPoint();
  int16_t touchX = tp.x;
  int16_t touchY = tp.y;
  bool touched = false;
  if ((touchX > 0) || (touchY > 0)) {
    touched = true;
  }

  if(!touched)
  {
    data->state = LV_INDEV_STATE_REL;
    return false;
  }
  else
  {
    data->state = LV_INDEV_STATE_PR;
  }

  Serial.println(touchX);
  Serial.println(touchY);
  Serial.println(touched);
  Serial.println("==================\n");  

  return false; /*Return `false` because we are not buffering and no more data to read*/
}

void printEvent(String Event, lv_event_t event)
{
  
  Serial.print(Event);
  Serial.printf(" ");

  switch(event) {
      case LV_EVENT_PRESSED:
          Serial.printf("Pressed\n");
          break;

      case LV_EVENT_SHORT_CLICKED:
          Serial.printf("Short clicked\n");
          break;

      case LV_EVENT_CLICKED:
          Serial.printf("Clicked\n");
          break;

      case LV_EVENT_LONG_PRESSED:
          Serial.printf("Long press\n");
          break;

      case LV_EVENT_LONG_PRESSED_REPEAT:
          Serial.printf("Long press repeat\n");
          break;

      case LV_EVENT_RELEASED:
          Serial.printf("Released\n");
          break;
  }
}


void slider_event_cb(lv_obj_t * slider, lv_event_t event)
{

  printEvent("Slider", event);

  if(event == LV_EVENT_VALUE_CHANGED) {
      static char buf[4];                                 /* max 3 bytes  for number plus 1 null terminating byte */
      snprintf(buf, 4, "%u", lv_slider_get_value(slider));
      lv_label_set_text(slider_label, buf);               /*Refresh the text*/
	  int16_t value = lv_slider_get_value(slider);
	  value = map(value, 0, 100, 0, 255);
	  //analogWriteFrequency(2000); // Set PMW period to 2000 Hz instead of 1000
	  analogWrite(LED_PIN, value);//8-bit by default
  }
}


void setup() {

  Serial.begin(115200); /* prepare for possible serial debug */
  pinMode(LED_PIN, OUTPUT);
  pinMode(PF14, OUTPUT);
  digitalWrite(PF14, HIGH);
  delay(2000);
  
  lv_init();

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

  if (!touch.begin(40)) {  // pass in 'sensitivity' coefficient
    Serial.println("Couldn't start FT6206 touchscreen controller");
  } else {
    Serial.println("FT6206 touchscreen controller CONNECTED!");
  }
  

  lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

  /*Initialize the display*/
  lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.buffer = &disp_buf;
  lv_disp_drv_register(&disp_drv);

  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*/

  //Set the theme..
  //lv_theme_t * th = lv_theme_night_init(210, NULL);     //Set a HUE value and a Font for the Night Theme
  //lv_theme_set_current(th);

  lv_obj_t * scr = lv_cont_create(NULL, NULL);
  lv_disp_load_scr(scr);

  //lv_obj_t * tv = lv_tabview_create(scr, NULL);
  //lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));

  /* Create simple label */
  lv_obj_t *label = lv_label_create(lv_scr_act(), NULL);
  lv_label_set_text(label, "PB6 LED DIMMER");
  lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, -50);

  /* Create a slider in the center of the display */
  lv_obj_t * slider = lv_slider_create(lv_scr_act(), NULL);
  lv_obj_set_width(slider, screenWidth-50);                        /*Set the width*/
  lv_obj_set_height(slider, 50);
  lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 0);    /*Align to the center of the parent (screen)*/
  lv_obj_set_event_cb(slider, slider_event_cb);         /*Assign an event function*/

  /* Create a label below the slider */
  slider_label = lv_label_create(lv_scr_act(), NULL);
  lv_label_set_text(slider_label, "0");
  lv_obj_set_auto_realign(slider, true);
  lv_obj_align(slider_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);

}

void loop() {

  lv_task_handler(); /* let the GUI do its work */
  delay(5);
}

Screenshot and/or video

If possible, add screenshots and/or videos about the current issue.

Hi,

Using the lvgl repo is not tested yet, so I’m very happy to hear your feedback.

It’s very strange because both the display refreshing and TP handling happens in lv_task_handler(). If the screen is refreshed my_touchpad_read should be called at least.

Some questions:

  • Might sound stupid, but are you sure that the display is working and not just the last frame has remained there from lv_ardunio testing.
  • Have you set LV_TICK_CUSTOM and LV_TICK_CUSTOM_SYS_TIME_EXPR is (millis())?

cc @Pablo2048

  • Might sound stupid, but are you sure that the display is working and not just the last frame has remained there from lv_ardunio testing.
  • After successfully uploading, I cut power to the device and turned it back on, assuming that clears the screen buffer and saw the screen I was expecting.
  • I’ve also changed the TFT rotation and can see the screen change after uploading, again assuming that the visual change on screen means that the disp flush function is working.
  • Finally, I put a print statement in the disp flush function and saw the output at device startup, on both the lv_arduino and lvgl compiled versions.
  • Have you set LV_TICK_CUSTOM and LV_TICK_CUSTOM_SYS_TIME_EXPR is (millis()) ?
  • I have not changed any of this. this is what my lv_conf.h looks like:
/* 1: use a custom tick source.
 * It removes the need to manually update the tick with `lv_tick_inc`) */
#define LV_TICK_CUSTOM     0
#if LV_TICK_CUSTOM == 1
#define LV_TICK_CUSTOM_INCLUDE  "Arduino.h"         /*Header for the system time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis())     /*Expression evaluating to current system time in ms*/
#endif   /*LV_TICK_CUSTOM*/

I’d be happy to help test this how ever I can, just let me know what I can do. I’d love to get a solid product running on lvgl, but have been running into some hardware\setup issues the last few weeks. If my help can push the library into the direction to get my setup running, I’m happy to help out with that. :slight_smile:

I think this may be solved. The very last step in the instructions (#6) says to set LV_TICK_CUSTOM in lv_conf.h to 1. Which I did not do. After doing so, the touch function started firing off the print statement as expected.

I’m currently trying out a different display without touch, so I’ll need to spend some time to get my other touch display wired back up. As soon as I do and can verify, I’ll report back. But I’m pretty sure things will be working as expected.

Thanks

Just to follow up, touch is working for me now. The issue was as stated in the previous post: I forgot to set LV_TICK_CUSTOM = 1 in lv_conf.h.

Great news! Thanks for the feedback! :slightly_smiling_face:

So now we know that the example is working and lvgl can be used as an Arduino lib on its own.

The lv_examples repo is prepared in the same way so it also should work as an Arduino library. Could you give it a try as well?
After adding it you should be able to call e.g. lv_ex_btn1()

I’ve already been using the lv_examples repo along side the lvgl repo in the Arduino framework (using PlatformIO) and I can say that most of them work. :slight_smile: I believe two threw errors. I’ll try to get those errors reported later tonight.

Nice! Looking forward to see the issues.

Below are the results. I’d really like to figure out the benchmark issue so I can see how well my setup is doing.

lv_demo_widgets: WORKS
lv_demo_keypad_encoder: WORKS
lv_demo_stress: WORKS
lv_ex_style_#: ALL SEEM TO WORK
lv_ex_get_started_#: ALL WORK

lv_demo_benchmark: FAILED TO BUILD

...
c:/users/jc78/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\nucleo_f767zi\lib0f4\liblv_examples.a(lv_demo_benchmark.c.o): in function `img_argb_zoom_aa_cb':
lv_demo_benchmark.c:(.text.img_argb_zoom_aa_cb+0x38): undefined reference to `img_cogwheel_argb'
c:/users/jc78/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: .pio\build\nucleo_f767zi\lib0f4\liblv_examples.a(lv_demo_benchmark.c.o): in function `sub_img_cb':
lv_demo_benchmark.c:(.text.sub_img_cb+0x44): undefined reference to `img_cogwheel_argb'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nucleo_f767zi\firmware.elf] Error 1

lv_demo_printer: FAILED TO BUILD

...
Compiling .pio\build\nucleo_f767zi\lib0f4\lv_examples\lv_ex_style\lv_ex_style_11.c.o
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:113:17: note: each undeclared identifier is reported only once for each function it appears in
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:113:41: error: 'lv_font_montserrat_22' undeclared (first use in this function); did you 
mean 'lv_font_montserrat_16'?
  113 |             0, &lv_font_montserrat_14, &lv_font_montserrat_22, 
      |                                         ^~~~~~~~~~~~C~ompiling 
.pio\build\nucleo_f767zi\lib0f4\lv_examples\lv_ex_style\lv_ex_style_2.c.o
~~~~~~~~
      |                                         lv_font_montserrat_16
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:114:14: error: 'lv_font_montserrat_28' undeclared (first use in this function); did you 
mean 'lv_font_montserrat_16'?
  114 |             &lv_font_montserrat_28, &lv_font_montserrat_32);   
      |              ^~~~~~~~~~~~~~~~~~~~~
      |              lv_font_montserrat_16
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:114:38: error: 'lv_font_montserrat_32' undeclared (first use in this function); did you 
mean 'lv_font_montserrat_16'?
  114 |             &lv_font_montserrat_28, &lv_font_montserrat_32);   
      |                                      ^~~~~~~~~~~~~~~~~~~~~     
      |                                      lv_font_montserrat_16     
In file included from d:\dropbox\projects\st\st_nucleo_test02\lib\lvgl\lvgl.h:24,
                 from lib\lv_examples\src\lv_demo_printer\../../lv_examples.h:19,
                 from lib\lv_examples\src\lv_demo_printer\lv_demo_printer.h:16,
                 from lib\lv_examples\src\lv_demo_printer\lv_demo_printer_theme.h:16,
                 from lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:9:
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c: At top level:   
lib\lv_examples\src\lv_demo_printer\lv_demo_printer.c:50:21: warning: 'scan_ready_event_cb' declared 'static' but never defined [-Wunused-function]
   50 | LV_EVENT_CB_DECLARE(scan_ready_event_cb);
      |                     ^~~~~~~~~~~~~~~~~~~
d:\dropbox\projects\st\st_nucleo_test02\lib\lvgl\src/lv_core/lv_obj.h:1432:47: note: in definition of macro 'LV_EVENT_CB_DECLARE'
 1432 | #define LV_EVENT_CB_DECLARE(name) static void name(lv_obj_t * obj, lv_event_t e)
      |                                               ^~~~
*** [.pio\build\nucleo_f767zi\lib0f4\lv_examples\lv_demo_printer\lv_demo_printer.c.o] Error 1

The first issue appears to be that the files in the lv_examples/assets directory don’t get compiled. I have no idea how to fix that for PlatformIO.

The second issue can be solved by enabling the appropriate font sizes in lv_conf.h. In your case it looks like 22px, 28px, and 32px need to be enabled.

1 Like