Skip to content

CrowPanel ESP32 4.3-inch with ESP-IDF

Overview


This example tutorial is a project for controlling the on and off of an LED. It demonstrates how to create a UI and how to control the on and off of an LED through buttons on the screen.

In this tutorial, we will show you how to design the UI with SquareLine Studio, and show you how to upload the code with ESP-IDF.

example

Hardware Preparation


CrowPanel ESP32 4.3'' HMI Crowtail-LED Dupont-wire
CrowPanel-ESP32-4.3inch CROWTAIL-LED 4-PIN-FEMALE-WIRE
BUYNOW BUYNOW BUYNOW

Design UI file with SquareLine Studio


Get Started with SquareLine Studio

Please click the card below to learn how to download the SquareLine Studio, and how to export the demo UI file.

GetStartedWithSquareLine

Design UI file with SquareLine Studio

Let's start learning how to create our own UI after getting an initial understanding of SquareLine Studio.

  1. In the earlier version of SLS, select "Arduino"->"Arduino with TFT_eSPI".

    SLS-UI-1

    Note:

    After using SLS to generate UI code, we then use different graphics libraries according to different hardware and modify the corresponding code to display the content you design.

    Set the name of the project, set the screen resolution to 480*272, set the color depth to 16bit, and keep other default settings. After setting, click CREATE to create the project.

    SLS-UI-2

    • 16-bit color depth: can represent 65,536 colors through RGB 5:6:5 sub-pixel representation, that is, each RGB channel occupies 5 bits and 1 bit (a total of 16 bits) to represent colors.
  2. After creation, enter the following interface with a blank background.

    SLS-UI-3

  3. In the "Assets" area, click "ADD FILE TO ASSETS" to add custom images or icons.

    Please click download to download the custom images used in this tutorial.

    Note:

    Images only support PNG format. The pixels of the image need to be smaller than the pixel size of the screen used in your project. The size of each image should not exceed 100k, preferably within 30k, to provide a smooth display effect.

  4. Add background.

    Find "Inspector"->"STYLE SETTING", click to expand "STYLE(MAIN)", then click the 2nd "Background". Check the "Bg Image" and select the background image.

    SLS-UI-5

    SLS-UI-6

  5. Add Button widget to control the LED.

    Click "Button" in the "Widgets" area, and "Button1" will be added to the current Screen.

    SLS-UI-12

    The position and size of the label can be adjusted by dragging the mouse. You can also directly enter numbers in the Inspector→BUTTON→Transform to adjust.

    SLS-UI-13

    Add an identification symbol to the button. The button in this tutorial controls the LED switch, so you only need to mark the button "on" and "off". You can add LABEL widgets or add a background images to the button. This tutorial will demonstrate how to add a background image to a button.

    Click the Button1, then find Inspector->STYLE SETTINGS ->STYLE(MAIN) ->Background, and select the image.

    SLS-UI-14

    In the same way, duplicate a Button widget. And drag it to the corresponding position to modify different background image.

    SLS-UI-16

    SLS-UI-17

    Set the status of the button to identify different states.

    In "Inspector"->"STYLE SETTINGS"->"STATE", set display white background color by DEFAULT and red when on the PRESSED state.

    SLS-UI-19

    SLS-UI-20

    Make the same settings for the "OFF" button.

  6. Add events to buttons.

    Note: Because the button controls the on and off of the LED, we can add any event here to generate the code framework for the button event when exporting the UI file. We will modify the code of the button event to control the LED latter.

    Select the button and click "ADD EVENT".

    SLS-UI-21

    Select "clicked" as the trigger condition, select a trigger event in "Action". It will be modified in the generated program to achieve the LED control function.

    SLS-UI-22

    Complete the event. Here I choose to change the screen, and the screen to be switched is Screen1.

    SLS-UI-23

    Add event to Button2 (OFF) in the same way.

    SLS-UI-24

  7. Export UI files.

    Click "File" -> "Project Settings" and make settings for the exported file.

    SLS-UI-25

    Set the export path of the file (set the path according to your own file).

    SLS-UI-26

    Fill in lvgl.h in LVGL Include Path. Check "Flat export(exports all files to one folder )".

    Then click "APPLY CHANGES".

    Tips: After selecting the flat export, the output files will be in the same folder, so that the output code does not need to modify the path in the program. If not, the output files will be classified and placed in different folders. The compiler may not be able to recognize different paths, which will cause some trouble. In this case, the user needs to modify it manually, so it is recommended to select all files to be output to the same folder.

    SLS-UI-27

    Export UI files. The exported files will be in the path we set earlier.

    SLS-UI-28

    SLS-UI-29

    You can click download to download the export UI files we provided.

Build the Project with ESP-IDF


Get Started with ESP-IDF

Please click the card below to learn how to install ESP-IDF. Create a blank project according to the "Get Started with ESP-IDF".

GetStartedWithESPIDF

You can click download to download the complete project we provided. This project can be used directly. You can also create the project by following the tutorial.

Add Libraries

Create a new folder and name the folder 'components'. Add the libraries we provided to this folder.

SLS-UI-36

Please click download to download the libraries we provided.

Setup UI file

Add the UI file we exported earlier in Squareline.

SLS-UI-42

The CMakeList.txt file in the UI file needs to be modified as follows:

Before modification

SET(SOURCES ui_comp_button2.c
   ui_comp.c
   ui_Screen1.c
   ui.c
   ui_comp_hook.c
   ui_helpers.c
   ui_events.c
   ui_img_background_png.c
   ui_img_on_png.c
   ui_img_off_png.c)

add_library(ui${SOURCES})

After modification

SLS-UI-37

Define a variable in the ui.h file. In the main program by judging the value of this variable, control the LED light on and off.

SLS-UI-38

Locate the FUNCTION location in the ui.c file. This is the code we generated when we added events to squareline. We modify the event implementation function to what we need.

SLS-UI-39

Delete the code in the red circle in the image above. Add new code to assign values to led variables.

When the key 1 (ON key) is pressed, set the LED value to 1.

SLS-UI-34

When key 2 (OFF key) is pressed, set the LED value to 0.

SLS-UI-35

Setup main file

The CMakeList.txt file contains the Settings for the library. All required libraries should be included by directory address.

SLS-UI-40

The main program is written in CrowPanel_ESP32_4.3.cpp file.

Library introduction

In this project, we will use the following libraries:

#include <lvgl.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include "ui.h"
#include "touch.h"
  • #include <lvgl.h>: Library for UI interaction
  • #include <SPI.h>: Screen driven library.
  • #include <Adafruit_GFX.h>: The Adafruit_GFX library is a graphics library provided by Adafruit for drawing graphics on various display devices.
  • #include "ui.h": is a custom header file that contain UI-related functions or definitions.****
  • #include "touch.h": Libraries related to touch

Code Explanation

Basic Definition

  • Backlight

    #define TFT_BL 2
    
  • Create a default Arduino_GFX object lcd

    #if defined(DISPLAY_DEV_KIT)
    Arduino_GFX *lcd = create_default_Arduino_GFX();
    #else /* !defined(DISPLAY_DEV_KIT) */
    
    
    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 */
    );
    // option 1:
    // ILI6485 LCD 480x272
    Arduino_RPi_DPI_RGBPanel *lcd = new Arduino_RPi_DPI_RGBPanel(
      bus,
      480 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 43 /* hsync_back_porch */,
      272 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 12 /* vsync_back_porch */,
      1 /* pclk_active_neg */, 7000000 /* prefer_speed */, true /* auto_flush */);
    
    #endif /* !defined(DISPLAY_DEV_KIT) */
    

    It uses a class called Arduino_ESP32RGBPanel to initialize a display bus object bus. This object is used to control the ESP32-based RGB display panel. Then, according to option 1 in the comments, it uses the Arduino_RPi_DPI_RGBPanel class to initialize a display object called lcd. This object is used to control an ILI6485 LCD with a resolution of 480x272 pixels.

  • Resolution

    /*Changing the screen resolution*/
    static uint32_t screenWidth;
    static uint32_t screenHeight;
    
  • Define a buffer variable to initialize the display driver of LVGL and prepare a buffer to store pixel data that will be rendered to the screen. The size of this buffer should be around 1/10 of the product of screen pixel values, which can balance the main control performance and the smoothness of screen display. Taking 10 as an example, the display will be smoother.

    static lv_disp_draw_buf_t draw_buf;
    static lv_color_t buf1[ screenWidth * screenHeight / 8 ];
    static lv_disp_drv_t disp_drv;
    
  • Define the led variable and the instance of the SPI library

int led;
SPIClass& spi = SPI;

Function

  • The my_disp_flush() function is used for display flushing. It receives a display driver pointer disp of type lv_disp_drv_t. An lv_area_t structure pointer area representing the refresh area, and an lv_color_t type pointer color_p pointing to the color data. In the function, first calculate the width w and height h of the refresh area. Depending on whether the LV_COLOR_16_SWAP macro is defined, different methods are selected to draw color data to the display device. If the LV_COLOR_16_SWAP macro is defined, use the draw16bitBeRGBBitmap() method to draw color data; Otherwise, use the draw16bitRGBBitmap() method. Finally, the lv_disp_flush_ready() function is called to notify LittlevGL that the display has been flushed.

    /* Display Refresh */
    /* 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)
      lcd->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
    #else
      lcd->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
    #endif
    
      lv_disp_flush_ready(disp);
    }
    
  • The my_touchpad_read() function is used for processing touch input. It receives an input device driver pointer indev_driver of type lv_indev_drv_t, and a pointer to an lv_indev_data_t structure representing input data, data. In the function, first check whether the touch screen has a signal. If there is a signal, further check whether the touch is pressed or released. If the touch is pressed, set the input state to LV_INDEV_STATE_PR and set the coordinates of the input point to the coordinates of the last touch on the touch screen. If the touch is released, set the input state to LV_INDEV_STATE_REL. If the touch screen does not have a signal, set the input state to LV_INDEV_STATE_REL, indicating that the input device is in a released state.

  • ```c 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;       Serial.print( "Data x :" );       Serial.println( touch_last_x );

    Serial.print( "Data y :" );       Serial.println( touch_last_y );     }     else if (touch_released())     {       data->state = LV_INDEV_STATE_REL;     }   }   else   {     data->state = LV_INDEV_STATE_REL;   } } ```

Set Up Part

extern "C" void app_main()
  {
    Serial.begin( 9600 ); /*Initializing the Serial Port*/

    //IO Port Pins
    pinMode(38, OUTPUT);
    digitalWrite(38, LOW);
    pinMode(0, OUTPUT);//TOUCH-CS


    lv_init(); // LVGL initialization

    // Init Display
    lcd->begin();
    lcd->setTextSize(2);
    lcd->fillScreen(BLACK);

   //Initialize touch
    touch_init();

   //Backlight Pins
    pinMode(27, OUTPUT);
    digitalWrite(27, HIGH);
    lcd.setRotation(1);

    /*Obtain the width and height of the screen, and initialize the drawing buffer.*/
    screenWidth = lcd.width();
    screenHeight = lcd.height();

    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * screenHeight / 8);

    /* Initialize the display */
    lv_disp_drv_init(&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 = &draw_buf;
    lv_disp_drv_register(&disp_drv);

    /* Initialize the (dummy) input device driver */
    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);

    /*Initialize UI */
    ui_init();
    lcd->fillScreen(BLACK);

    Serial.println("Setup done");

    while (1)
    {
        if(led == 1)
            digitalWrite(38, HIGH);
        if(led == 0)
            digitalWrite(38, LOW);
        lv_timer_handler();
        delay(10);
    }
  }   

Main Program Part

    while (1)
    {
    /* In the ui.c program, press the "ON" button, then set the led to 1, and the led is turned on*/
    if(led == 1)
    digitalWrite(38, HIGH);
    /* In the ui.c program, press the "OFF" button, then set the led to 0, and the led is turned off*/     
    if(led == 0)
    digitalWrite(38, LOW);
    /*Run GUI*/
    lv_timer_handler(); /* let the GUI do its work */
    delay( 10 );
    }

Setup board

ESP-IDF-1

ESP-IDF-2

ESP-IDF-3

ESP-IDF-4

Click Menuconfig to enter the Settings

ESP-IDF-5

Flash memory setting

ESP-IDF-6

Partition table setting. The second point requires manual input.

ESP-IDF-7

ESP32 setting

ESP-IDF-8

ESP-IDF-9

LVGL setting, uncheck

ESP-IDF-10

Save the setting

ESP-IDF-11

Download the program

Connect the ESP32 Display to the PC and compile the program.

ESP-IDF-12

After confirming the serial port, select the UART mode.

ESP-IDF-13

After the program is successfully downloaded, connect the LED to GPIO_D. Click the ON button on the screen and the LED will turn on. Click the OFF button and the LED will turn off.

example