Elecrow 5" and LVGL and Squareline - Full Working

The purpose of this Post is to share it with colleagues and also for myself.

Sometimes I even go back to the forum to see something I did and forgot.

The project below is the fully functional code of the Elecrow 5" RGB 24Bits Display

Working with LVGL and Squareline Studio.

This manufacter use Display Driver ILI6122 e ILI5960

Link the Display

This full code:
5Inch_LVGL_Ok.zip (74.7 KB)

And

Partial code:

#include <Arduino_GFX_Library.h>
#include <lvgl.h>
#include "ui.h"

//Função de start do Barramento do Display (Verificar pinos junto com o projeto de Hardware) e parametros do display:
      Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
          40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 0 /* PCLK */,
          45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
          5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
          8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */,

          0 /* hsync_polarity */, 210 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 43 /* hsync_back_porch */,
          0 /* vsync_polarity */, 22 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 12 /* vsync_back_porch */,
          0 /* pclk_active_neg */, 16000000 /* prefer_speed */);
          
          Arduino_RGB_Display *gfx = new Arduino_RGB_Display(800 /* width */, 480 /* height */, rgbpanel);
          #include "touch.h"

//Variaveis do LVGL
      #define TFT_BL 2
      //#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

      static uint32_t screenWidth = 800;
      static uint32_t screenHeight = 480;
      static lv_disp_draw_buf_t draw_buf;
      static lv_color_t *disp_draw_buf;
      static lv_disp_drv_t disp_drv;

//Calibração Touch
      uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600;
      uint8_t  touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0;


void setup(){
          Serial.begin(115200);
          f_SetupDisplay();
          ui_init();
}

void loop(){
      lv_timer_handler();
}

f_SetupDisplay():

void f_SetupDisplay(){
          gfx->begin();
          pinMode(TFT_BL, OUTPUT);
          digitalWrite(TFT_BL, HIGH);
          lv_init();
          touch_init();

          screenWidth = gfx->width();
          screenHeight = gfx->height();
          
          disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * screenHeight / 4, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
          lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 10);
          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.draw_buf = &draw_buf;
          lv_disp_drv_register(&disp_drv);

          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);

}

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);
      #if (LV_COLOR_16_SWAP != 0)
        gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
      #else
        gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
      #endif

        lv_disp_flush_ready(disp);
}

void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data){
      if (touch_has_signal()){
          if (touch_touched()){
            data->state = LV_INDEV_STATE_PR;
            data->point.x = touch_last_x;
            data->point.y = touch_last_y;
          }else if (touch_released()){
              data->state = LV_INDEV_STATE_REL;
          }
      }
      else{
        data->state = LV_INDEV_STATE_REL;
      }
}

and Touch.h

/*******************************************************************************
 * Touch libraries:
 * FT6X36: https://github.com/strange-v/FT6X36.git
 * GT911: https://github.com/TAMCTec/gt911-arduino.git
 * XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
 ******************************************************************************/

/* uncomment for FT6X36 */
// #define TOUCH_FT6X36
// #define TOUCH_FT6X36_SCL 38//19
// #define TOUCH_FT6X36_SDA 37//18
// #define TOUCH_FT6X36_INT 4//39
// #define TOUCH_SWAP_XY
// #define TOUCH_MAP_X1 800
// #define TOUCH_MAP_X2 0
// #define TOUCH_MAP_Y1 0
// #define TOUCH_MAP_Y2 480

/* uncomment for GT911 */
 #define TOUCH_GT911
 #define TOUCH_GT911_SCL 20//20
 #define TOUCH_GT911_SDA 19//19
 #define TOUCH_GT911_INT 10//-1
 #define TOUCH_GT911_RST 11
 
 //38
 #define TOUCH_GT911_ROTATION ROTATION_NORMAL
 #define TOUCH_MAP_X1 800//480
 #define TOUCH_MAP_X2 0
 #define TOUCH_MAP_Y1 480//272
 #define TOUCH_MAP_Y2 0

/* uncomment for XPT2046 */
// #define TOUCH_XPT2046
// #define TOUCH_XPT2046_SCK 12
// #define TOUCH_XPT2046_MISO 13
// #define TOUCH_XPT2046_MOSI 11
// #define TOUCH_XPT2046_CS 38
// #define TOUCH_XPT2046_INT 36
// #define TOUCH_XPT2046_ROTATION 0
// #define TOUCH_MAP_X1 4000
// #define TOUCH_MAP_X2 100
// #define TOUCH_MAP_Y1 100
// #define TOUCH_MAP_Y2 4000

int touch_last_x = 0, touch_last_y = 0;

#if defined(TOUCH_FT6X36)
#include <Wire.h>
#include <FT6X36.h>
FT6X36 ts(&Wire, TOUCH_FT6X36_INT);
bool touch_touched_flag = true, touch_released_flag = true;

#elif defined(TOUCH_GT911)
#include <Wire.h>
#include <TAMC_GT911.h>
TAMC_GT911 ts = TAMC_GT911(TOUCH_GT911_SDA, TOUCH_GT911_SCL, TOUCH_GT911_INT, TOUCH_GT911_RST, max(TOUCH_MAP_X1, TOUCH_MAP_X2), max(TOUCH_MAP_Y1, TOUCH_MAP_Y2));

#elif defined(TOUCH_XPT2046)
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
XPT2046_Touchscreen ts(TOUCH_XPT2046_CS, TOUCH_XPT2046_INT);

#endif

#if defined(TOUCH_FT6X36)
void touch(TPoint p, TEvent e)
{
  if (e != TEvent::Tap && e != TEvent::DragStart && e != TEvent::DragMove && e != TEvent::DragEnd)
  {
    return;
  }
  // translation logic depends on screen rotation
#if defined(TOUCH_SWAP_XY)
  touch_last_x = map(p.y, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width());
  touch_last_y = map(p.x, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height());
#else
  touch_last_x = map(p.x, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width());
  touch_last_y = map(p.y, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height());
#endif
  switch (e)
  {
  case TEvent::Tap:
    Serial.println("Tap");
    touch_touched_flag = true;
    touch_released_flag = true;
    break;
  case TEvent::DragStart:
    Serial.println("DragStart");
    touch_touched_flag = true;
    break;
  case TEvent::DragMove:
    Serial.println("DragMove");
    touch_touched_flag = true;
    break;
  case TEvent::DragEnd:
    Serial.println("DragEnd");
    touch_released_flag = true;
    break;
  default:
    Serial.println("UNKNOWN");
    break;
  }
}
#endif

void touch_init()
{
#if defined(TOUCH_FT6X36)
  Wire.begin(TOUCH_FT6X36_SDA, TOUCH_FT6X36_SCL);
  ts.begin();
  ts.registerTouchHandler(touch);

#elif defined(TOUCH_GT911)
  Wire.begin(TOUCH_GT911_SDA, TOUCH_GT911_SCL);
  ts.begin();
  ts.setRotation(TOUCH_GT911_ROTATION);

#elif defined(TOUCH_XPT2046)
  SPI.begin(TOUCH_XPT2046_SCK, TOUCH_XPT2046_MISO, TOUCH_XPT2046_MOSI, TOUCH_XPT2046_CS);
  ts.begin();
  ts.setRotation(TOUCH_XPT2046_ROTATION);

#endif
}

bool touch_has_signal()
{
#if defined(TOUCH_FT6X36)
  ts.loop();
  return touch_touched_flag || touch_released_flag;

#elif defined(TOUCH_GT911)
  return true;

#elif defined(TOUCH_XPT2046)
  return ts.tirqTouched();

#else
  return false;
#endif
}

bool touch_touched()
{
#if defined(TOUCH_FT6X36)
  if (touch_touched_flag)
  {
    touch_touched_flag = false;
    return true;
  }
  else
  {
    return false;
  }

#elif defined(TOUCH_GT911)
  ts.read();
  if (ts.isTouched)
  {
#if defined(TOUCH_SWAP_XY)
    touch_last_x = map(ts.points[0].y, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width() - 1);
    touch_last_y = map(ts.points[0].x, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height() - 1);
#else
    touch_last_x = map(ts.points[0].x, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width() - 1);
    touch_last_y = map(ts.points[0].y, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height() - 1);
#endif
    return true;
  }
  else
  {
    return false;
  }

#elif defined(TOUCH_XPT2046)
  if (ts.touched())
  {
    TS_Point p = ts.getPoint();
#if defined(TOUCH_SWAP_XY)
    touch_last_x = map(p.y, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width() - 1);
    touch_last_y = map(p.x, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height() - 1);
#else
    touch_last_x = map(p.x, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width() - 1);
    touch_last_y = map(p.y, TOUCH_MAP_Y1, TOUCH_MAP_Y2, 0, gfx->height() - 1);
#endif
    return true;
  }
  else
  {
    return false;
  }

#else
  return false;
#endif
}

bool touch_released()
{
#if defined(TOUCH_FT6X36)
  if (touch_released_flag)
  {
    touch_released_flag = false;
    return true;
  }
  else
  {
    return false;
  }

#elif defined(TOUCH_GT911)
  return true;

#elif defined(TOUCH_XPT2046)
  return true;

#else
  return false;
#endif
}

The heart of the code is here:

This code is what makes the RGB display work, you need to know exactly the parameters of the display used. According to the manufacturer.

This part is the standard LVGL code.

Most often used with TFT

1 Like

Awesome! Thank you for sharing!

Hey there,
I’m trying to get basically the same display but one size bigger to work.

On the Arduino IDE i’ve installed all the libraries from the manufacturers Google drive page
Elecrow Libs
GFX Library for Arduino V 1.2.8
LovyanGFX V 0.4.18
TAMC_GT911 V 1.0.2
TFT_eSPI V 2.5.0
XPT2046 Touchscreen V 1.4
lvgl by kisvegabor V 8.3.6
and some more like SD, DHT or BLE

After i tried to compile your sketch, the IDE says:

Compilation error: no matching function for call to 'Arduino_ESP32RGBPanel::Arduino_ESP32RGBPanel(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int)'

which i’ve already had when the Libs had the wrong version.

Could you please tell me, which versions of the Libs you’re using?

The only things i nearly got running on the Display are some example codes. But everytime i power the Display on, it goes from white to black and back while in the middle of the whole fading thing, it actually shows the desired content (like touch coordinates).

So I had this problem and I don’t remember how I solved it.

The ideal is for you to isolate things and advance with each Lib/Step slowly.

First test only the Arduino_GFX_Library.h lib

Which is the one that actually has the driver for this screen.

When this is working, the other items will be inserted: in order:

LVGL and then Touch.

TFT_eSPI is not a library used with this display. so don’t keep her with that example.

Hi Bro, awesome work! I tried to get the code on the display but I always got this problem with the Arduino_ESP32RGBPanel

C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\5Inch_LVGL_Ok.ino:6:7: error: ‘Arduino_ESP32RGBPanel’ does not name a type; did you mean ‘Arduino_ESP32SPI’?
Arduino_ESP32RGBPanel rgbpanel = new Arduino_ESP32RGBPanel(
^~~~~~~~~~~~~~~~~~~~~
Arduino_ESP32SPI
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\5Inch_LVGL_Ok.ino:16:11: error: ‘Arduino_RGB_Display’ does not name a type
Arduino_RGB_Display gfx = new Arduino_RGB_Display(800 / width /, 480 / height /, rgbpanel);
^~~~~~~~~~~~~~~~~~~
In file included from C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\5Inch_LVGL_Ok.ino:17:
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\touch.h: In function ‘bool touch_touched()’:
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\touch.h:165:71: error: ‘gfx’ was not declared in this scope
touch_last_x = map(ts.points[0].x, TOUCH_MAP_X1, TOUCH_MAP_X2, 0, gfx->width() - 1);
^~~
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\f_Display.ino: In function ‘void f_SetupDisplay()’:
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\f_Display.ino:2:11: error: ‘gfx’ was not declared in this scope
gfx->begin();
^~~
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\f_Display.ino: In function 'void my_disp_flush(lv_disp_drv_t
, const lv_area_t
, lv_color_t*)':
C:\Users\fritz\Desktop\ESP32 Display\5Inch_LVGL_Ok\f_Display.ino:34:9: error: ‘gfx’ was not declared in this scope
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
^~~
Multiple libraries were found for “SPI.h”
Used: C:\Users\fritz\Documents\Arduino\libraries\SPI
Not used: C:\Users\fritz\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.14\libraries\SPI
Multiple libraries were found for “Wire.h”
Used: C:\Users\fritz\Documents\Arduino\libraries\Wire
Not used: C:\Users\fritz\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.14\libraries\Wire
exit status 1

Compilation error: ‘Arduino_ESP32RGBPanel’ does not name a type; did you mean ‘Arduino_ESP32SPI’?

Do you have any solutions for that problem?

Thank you very much!

Best wishes

Tobi

As build issues were reported multiple times I’ve asked Elecrow to take a look at this topic.

Hello friends, this may be due to version incompatibility or incomplete library . In order to be able to use the latest version of the Arduino IDE and the latest version of the ESP32 package, we have updated the existing libraries as well as the examples. Please refer to this link CrowPanel-Lib – Google Drive for the libraries. For the examples, please refer to the attachment.
LvglWidgets-5.0-NOSPEAK.zip (11.8 KB)

I apologize for my absence.

The problem is that when I posted this working example.

I had the Arduino IDE working on my Windows.

And as a programmer I ended up migrating to Linux and ESP IDF.

So I no longer have this perfect “Working Code” running.

That’s why I wasn’t able to come here and update the topic.

However, the absence of this function is due to the library not being in the correct version.

The code is right. Need to get the library right.