Develop lvgl touch panel based on Arduino IDE

The first is how to configure vgl in the ArduinoIDE environment. You can refer to Arduino – LVGL documentationicon-default.png?t=N7T8https://docs.lvgl.io/master/get-started/platforms/ arduino.html#get-the-lvgl-arduino-library

For the ESP32 configuration of the touch panel, select the ESP32S3 Dev module: its configuration needs to be adjusted according to the following documents:

Sunton ESP32-S3 4.3 inch 800*400 IPS with Touch – Makerfabs Wiki

The libraries that need to be downloaded in ArduinoIDE are “GFX_Library_for_Arduino”, “lvgl”, “TFT_eSPI”, “TAMC_GT911”

The lvgl model in this article cannot be configured in the TFT_eSPI function, so it does not need to be turned on.

You only need to place the interface configured and output functions through the “SquareLine_Studio_1.3.0_Setup” software in the link:

https://pan.baidu.com/s/1thKSFWSKnEtGQOKIohUy6A?pwd=8888
Extraction code: 8888

In the downloaded folder, the specific location of the files output by the “SquareLine_Studio_1.3.0_Setup” software is to place the output “SquareLine_Project” file into the “src” folder of “Sunton_ESP32-8048S043-liu”, and then Place the “lvgl_conf.h” and “touch.h” files in the “sketch_jul30a” folder next to the ui.ino file, and modify the “ui.c” file in the src folder in the ui folder. The layout is as follows:

After the files and functions are located, the most important step is to copy all the functions above void setup() in “sketch_jul30a.ino” in the sketch_jul30a folder and replace the corresponding functions in “ui.ino” part, delete the redundant custom variables, and write the touch, TFT, and GFX initialization functions into the value setup. Please refer to the following main function code:

Note: Change the original “#include ” to “#include “src/ui.h””

#include <lvgl.h>
#include <TFT_eSPI.h>
#include "src/ui.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 = 800;
static const uint16_t screenHeight = 480;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * screenHeight / 10 ];
#define pin0 17
#define pin1 18

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

/****************************************************** ****************************
 * LVGL Widgets
 * This is a widgets demo for LVGL - Light and Versatile Graphics Library
 * import from: https://github.com/lvgl/lv_demos.git
 *
 * This was created from the project here
 * https://www.makerfabs.com/sunton-esp32-s3-4-3-inch-ips-with-touch.html
 *
 * Dependent libraries:
 * LVGL: https://github.com/lvgl/lvgl.git

 *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
 *
 * LVGL Configuration file:
 * Copy your_arduino_path/libraries/lvgl/lv_conf_template.h
 * to your_arduino_path/libraries/lv_conf.h
 * Then find and set:
 * #define LV_COLOR_DEPTH 16
 * #define LV_TICK_CUSTOM 1
 *
 * For SPI display set color swap can be faster, parallel screen don't set!
 * #define LV_COLOR_16_SWAP 1
 *
 * Optional: Show CPU usage and FPS count
 * #define LV_USE_PERF_MONITOR 1
 *************************************************** ****************************/
//#include "lv_demo_widgets.h"
#include <demos/lv_demos.h>
/****************************************************** ****************************
 *************************************************** ****************************/
#include <Arduino_GFX_Library.h>
#define TFT_BL 2
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
    GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
    40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* 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 */
);

// ST7262 IPS LCD 800x480
Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
    bus,
    800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
    480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
    1 /* pclk_active_neg */, 14000000 /* prefer_speed */, true /* auto_flush */);

#include "touch.h"

/* Change to your screen resolution */
static lv_disp_drv_t disp_drv;

/* Display flushing */
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 *) & amp;color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *) & amp;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;

      /*Set the coordinates*/
      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;
  }
}

void openleft(void)
{
  if(lv_obj_has_state(ui_Switchopenleft, LV_STATE_CHECKED)==1) // Return bool type, open-1; closed-2
  {
    pinMode(pin0,OUTPUT);
      
    digitalWrite(pin0,HIGH);
    
  }
}

void openright(void)
{
  if(lv_obj_has_state(ui_Switchopenright, LV_STATE_CHECKED)==1) // Return bool type, open-1; closed-2
  {
   
    pinMode(pin1,OUTPUT);
    
    digitalWrite(pin1,HIGH);
  }
}

void brakeleft(void)
{
  if(lv_obj_has_state(ui_Switchbrakeleft, LV_STATE_CHECKED)==1) // Return bool type, on-1; off-2
  {
    pinMode(pin0,OUTPUT);
      
    digitalWrite(pin0,LOW);
    
  }
}

void brakeright(void)
{
  if(lv_obj_has_state(ui_Switchbrakeright, LV_STATE_CHECKED)==1) // Return bool type, on-1; off-2
  {
    
    pinMode(pin1,OUTPUT);
   
    digitalWrite(pin1,LOW);
  }
}
void setup()
{
    Serial.begin( 115200 ); /* prepare for possible serial debug */
      gfx->begin();
#ifdef TFT_BL
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);
#endif


    String LVGL_Arduino = "Hello Arduino! ";
    LVGL_Arduino + = String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();

    Serial.println(LVGL_Arduino);
    Serial.println( "I am LVGL_Arduino" );

    lv_init();
    delay(10);
  touch_init();


#if LV_USE_LOG != 0
    lv_log_register_print_cb( my_print ); /* register print function for debugging */
#endif

    tft.begin(); /* TFT init */
    tft.setRotation( 3 ); /* Landscape orientation, flipped */

    lv_disp_draw_buf_init( & amp;draw_buf, buf, NULL, screenWidth * screenHeight / 10 );

    /*Initialize the display*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init( & amp;disp_drv );
    /*Change the following line to your display resolution*/
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = & amp;draw_buf;
    lv_disp_drv_register( & amp;disp_drv );

    /*Initialize the (dummy) input device driver*/
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init( & amp;indev_drv );
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;
    lv_indev_drv_register( & amp;indev_drv );


    ui_init();
    Serial.println( "Setup done" );
    openleft();
    openright();
    brakeleft();
    brakeright();
    }

void loop()
{
    lv_timer_handler(); /* let the GUI do its work */
    delay(5);
}

Listed below are some module codes:

Switch function can refer to

LVGL Study Notes 17 – Switch Switch_lvgl switch_pq113_6’s Blog-CSDN Blog

The slider function can refer to:

LVGL(72)-v8–slider-CSDN Blog

For button module functions, please refer to:

lvgl-Button Learning Chapter (3)_lvgl Button_Wuwei Sweeping Monk’s Blog-CSDN Blog

For label functions, please refer to:

ESP32 Development Journey LVGL Chapter 4 – Introduction to Common Functions, Screen, Label_lvgl Setting Background Color – CSDN Blog

The calls to these functions need to be called in the ui.c file. Before calling, if you need to make some changes, go to the “screen.h” file first and see if the module you need to modify has overlapping commands. The ui.c code of this article:

// This file was generated by SquareLine Studio
// SquareLine Studio version: SquareLine Studio 1.3.0
// LVGL version: 8.3.6
// Project name: SquareLine_Project

#include "ui.h"
#include "ui_helpers.h"
/VARIABLES

// SCREEN: ui_Screen1
void ui_Screen1_screen_init(void);
void ui_event_Screen1(lv_event_t * e);
lv_obj_t * ui_Screen1;
lv_obj_t * ui_Left;
lv_obj_t * ui_Right;
lv_obj_t * ui_Switchopenleft;
lv_obj_t * ui_Label1;
lv_obj_t * ui_Switchopenright;
lv_obj_t * ui_Label2;
lv_obj_t * ui_Switchbrakeleft;
lv_obj_t * ui_Switchbrakeright;
lv_obj_t * ui_Leftslide;
lv_obj_t * ui_Rightslide;
lv_obj_t * ui_Label3;
lv_obj_t * ui_Label4;
lv_obj_t * ui_Label5;
lv_obj_t * ui_Label6;
lv_obj_t * ui_Label8;
lv_obj_t * ui_Stop;
lv_obj_t * ui_Label10;
lv_obj_t * ui_Label9;
lv_obj_t * ui_Image1;
lv_obj_t * ui_Label12;
lv_obj_t * ui_Label11;
lv_obj_t * ui_Label7;
lv_obj_t * ui_Label13;
lv_obj_t * ui_Label14;
lv_obj_t * ui_Leftspeed;
lv_obj_t * ui_Rightspeed;
lv_obj_t * ui_Label16;
lv_obj_t * ui_Label15;
lv_obj_t * ui____initial_actions0;
const lv_img_dsc_t * ui_imgset_337415967[1] = { & amp;ui_img_1806934165};
const lv_img_dsc_t * ui_imgset_392147749[3] = { & amp;ui_img_999838862, & amp;ui_img_355854617, & amp;ui_img_1807947869};
/TEST LVGL SETTINGS
#if LV_COLOR_DEPTH != 32
#endif
#if LV_COLOR_16_SWAP !=0
    #error "LV_COLOR_16_SWAP should be 0 to match SquareLine Studio's settings"
#endif

/ ANIMATIONS

/FUNCTIONS

void ui_event_Screen1(lv_event_t * e)
{
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);
    if(event_code == LV_EVENT_CLICKED) {
        (e);
    }
}
//brake switch
void ui_event_Switchbrakeleft(lv_event_t * e)//Left brake
{
  lv_event_code_t event_code = lv_event_get_code(e);
  lv_obj_t * target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
     {
       if(lv_obj_has_state(target,LV_STATE_CHECKED) == true )
         {
           lv_obj_add_state(target, LV_STATE_CHECKED);//Set brake to open state. At this time, open is invalid and the slider is 0
           lv_obj_add_state(ui_Switchopenleft, LV_STATE_DISABLED);
           lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
           lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
          
           
         }
       else{lv_obj_clear_state(target, LV_STATE_CHECKED);//Set brake to off state, open will take effect at this time
            lv_obj_clear_state(ui_Switchopenleft, LV_STATE_DISABLED);}
       }
}
void ui_switchbrakeleft()
{
  lv_obj_clear_state(ui_Switchbrakeleft, LV_STATE_CHECKED); //brake initial value is closed
  lv_obj_add_event_cb(ui_Switchbrakeleft,ui_event_Switchbrakeleft,LV_EVENT_VALUE_CHANGED,NULL);
}

//brake switch
void ui_event_Switchbrakeright(lv_event_t * e)//right brake
{
  lv_event_code_t event_code = lv_event_get_code(e);
  lv_obj_t * target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
     {
       if(lv_obj_has_state(target,LV_STATE_CHECKED) == true )
         {
           
           lv_obj_add_state(target, LV_STATE_CHECKED);//Set brake to open state. At this time, open is invalid and the slider is 0
           lv_obj_add_state(ui_Switchopenright, LV_STATE_DISABLED);
           lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
           lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
         }
       else{lv_obj_clear_state(target, LV_STATE_CHECKED);//Set brake to off state, open will take effect at this time
            lv_obj_clear_state(ui_Switchopenright, LV_STATE_DISABLED);}
       }
}
void ui_switchbrakeright()
{
  lv_obj_clear_state(ui_Switchbrakeright, LV_STATE_CHECKED);//brake initial value is closed
  lv_obj_add_event_cb(ui_Switchbrakeright,ui_event_Switchbrakeright,LV_EVENT_VALUE_CHANGED,NULL);
}

//open switch
void ui_event_leftopenswitch(lv_event_t * e) //Left switch
{
   lv_event_code_t event_code = lv_event_get_code(e);
   lv_obj_t * target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
     {
       if(lv_obj_has_state(target,LV_STATE_CHECKED) == 1 )
         {
          
           lv_obj_add_state(target, LV_STATE_CHECKED);
            ui_slideleftspeed();
           lv_obj_clear_state(ui_Switchbrakeleft, LV_STATE_DISABLED);
           
         }
        if(lv_obj_has_state(target,LV_STATE_CHECKED) == 0){
           lv_obj_add_state(ui_Switchbrakeleft, LV_STATE_DISABLED);
           lv_obj_clear_state(target, LV_STATE_CHECKED);
           lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
           lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
           
              }
      }
}
void ui_leftopenswitch(void)
{
  
  lv_obj_add_state(ui_Switchopenleft, LV_STATE_CHECKED); // open
    ui_slideleftspeed();
  lv_obj_add_event_cb(ui_Switchopenleft,ui_event_leftopenswitch,LV_EVENT_VALUE_CHANGED,NULL);
}

void ui_event_rightopenswitch(lv_event_t * e) //right switch
{
   lv_event_code_t event_code = lv_event_get_code(e);
   lv_obj_t * target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
    {
     if(lv_obj_has_state(target,LV_STATE_CHECKED) == 0 )
     {
        lv_obj_add_state(ui_Switchbrakeright, LV_STATE_DISABLED);
        lv_obj_clear_state(target, LV_STATE_CHECKED);
        lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
        lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
      }
     if(lv_obj_has_state(target,LV_STATE_CHECKED) == 1){
           \t
           lv_obj_clear_state(ui_Switchbrakeright, LV_STATE_DISABLED);
           lv_obj_add_state(target, LV_STATE_CHECKED);
           ui_sliderightspeed();}
     }
}
void ui_rightopenswitch(void)
{
  lv_obj_add_state(ui_Switchopenright, LV_STATE_CHECKED); // open
    ui_sliderightspeed();
  lv_obj_add_event_cb(ui_Switchopenright,ui_event_rightopenswitch,LV_EVENT_VALUE_CHANGED,NULL);
}


//button stop
void ui_event_stop(lv_event_t * e)
{
   lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
  if(event_code == LV_EVENT_PRESSED) {
        lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
        lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
        lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
        lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
      }
}


void ui_stop(void)
{
   lv_obj_add_event_cb(ui_Stop,ui_event_stop,LV_EVENT_PRESSED,NULL);
}
//Slider part
void ui_slideleftspeed(void) //Initial value of left slider, range setting
{
lv_slider_set_value(ui_Leftslide,000,LV_ANIM_OFF);
lv_slider_set_range(ui_Leftslide, 0, 800); //Set the slider value change range 0-800
lv_obj_add_event_cb(ui_Leftslide, ui_event_receive_left, LV_EVENT_VALUE_CHANGED, NULL);
        
}



void ui_sliderightspeed(void) //right slider initial value, range setting
{
lv_slider_set_value(ui_Rightslide,000,LV_ANIM_OFF);
lv_slider_set_range(ui_Rightslide, 0, 800); //Set the slider value change range 0-800
  
lv_obj_add_event_cb(ui_Rightslide, ui_event_receive_right, LV_EVENT_VALUE_CHANGED,NULL);
}

void ui_event_receive_left(lv_event_t *e) //Left slider label data display
{
   lv_event_code_t event_code = lv_event_get_code(e);
   lv_obj_t *target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
   {
    if(lv_obj_has_state(ui_Switchopenleft,LV_STATE_CHECKED) == 1)
      {
          if(lv_obj_has_state(ui_Switchbrakeleft,LV_STATE_CHECKED) == 0 )
          {
             
         lv_label_set_text_fmt(ui_Leftspeed,"%d",lv_slider_get_value(target));
        
          }
      }
   }
}

void ui_event_receive_right(lv_event_t *e) //Right slider label data display
{
  lv_event_code_t event_code = lv_event_get_code(e);
  lv_obj_t *target = lv_event_get_target(e);
   if(event_code == LV_EVENT_VALUE_CHANGED)
   {
      if(lv_obj_has_state(ui_Switchopenright,LV_STATE_CHECKED) == 1)
      {
      if(lv_obj_has_state(ui_Switchbrakeright,LV_STATE_CHECKED) == 0 )
       {
      
             lv_label_set_text_fmt(ui_Rightspeed,"%d",lv_slider_get_value(target));
         
        }
      }
    }
}

void ui_event_speedback(void)
{
  lv_label_set_text_fmt(ui_Label16,"%d",50);
  lv_label_set_text_fmt(ui_Label15,"%d",300);
}

/SCREENS

void ui_init(void)
{
    lv_disp_t * dispp = lv_disp_get_default();
    lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
                                               false, LV_FONT_DEFAULT);
    lv_disp_set_theme(dispp, theme);
    ui_Screen1_screen_init();
    ui____initial_actions0 = lv_obj_create(NULL);
    lv_disp_load_scr(ui_Screen1);
    ui_event_speedback();
    ui_stop();
    ui_leftopenswitch();
    ui_rightopenswitch();
    ui_switchbrakeleft();
    ui_switchbrakeright();
    
}

Remember to put the function written earlier in the ui_init() function.

There may be errors in the “screen.c” file. One is that the font can only use the default value 14, so change them all to “&lv_font_montserrat_14”, so just change it.

The “ui.c” file also has a pitfall, that is, just delete the “ERROR” part under “LV_COLOR_DEPTH|=32”.

After writing, the functions that need to be referenced separately must be declared in the ui.h header file, and then called into the main function.