Skip to content

CrowPanel ESP32 2.8-inch with ESP-IDF

Overview


The example tutorial is an environmental monitoring project, demonstrate how to create a UI and use a DHT20 sensor to obtain the environment temperature and humidity and display it on the screen; and how to control the LED on and off by the 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.

img1

Hardware Preparation


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

Design UI file 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. Open the SquareLine Studio and create a project.

    img1-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 320*240, set the color depth to 16bit, and keep other default settings. After setting, click CREATE to create the project.

    img13

    • 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.

    img14

  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.

    img16

    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.

    img17

    img18

  5. Add Label widget to display temperature and humidity.

    Click "Label" in the "Widgets" area, and "Label1" will be added to the current Screen.

    img19

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

    img20

    You can set the font colour and other attributes in STYLE SETTING→STYLE(MAIN).

    img21

    Add a Label2 to display the humidity value in the same way. You can also directly right-click the Label1 to duplicate it.

    img22

    Then set different positions for the Label2.

    img23

    Modify the text content to display a default value.

    img24

  6. Add Button widget to control the LED.

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

    img25

    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.

    img26

    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.

    img27

    img28

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

    img29

    img30

    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.

    img31

    img32

    Make the same settings for the "OFF" button.

  7. 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".

    img33

    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.

    img34

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

    img35

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

    img36

  8. Export UI files.

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

    img37

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

    img38

    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.

    img39

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

    img40

    img41

    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".

img43

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.

img45

Setup UI file

Add the UI file we exported earlier in Squareline.

img47

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

img48

Setup main file

The CMakeList.txt file contains the Settings for the library. All required libraries should be included by directory address. The CPP file of DHT20 has an additional column.

img53

The main program is written in CrowPanel_ESP32_2.4_2.8.cpp file.

Library introduction

In this project, we will use the following libraries:

#include <lvgl.h>
#include <DHT20.h>
#include <TFT_eSPI.h>
#include <Arduino.h>
#include "ui.h"
  • #include <lvgl.h>: Library for UI interaction.
  • #include <DHT20.h>: The library of temperature and humidity sensors.
  • #include <TFT_eSPI.h>: Screen driven library.
  • #include <Arduino.h>: This is the core Arduino header file. It must be included when using the Arduino framework.
  • #include "ui.h": is a custom header file that contain UI-related functions or definitions.

Code Explanation

Basic Definition

  • Set the screen cache
#define SCREEN_WIDTH  320
#define SCREEN_HEIGHT 240
#define LVGL_TICK_PERIOD 5


uint16_t calData[5] = {189, 3416, 359, 3439, 1};


TFT_eSPI lcd = TFT_eSPI(); 
DHT20 dht20;

// Screen buffer (suggested to be 1/10 to 1/4 of the screen size)
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 8)
lv_color_t draw_buf[DRAW_BUF_SIZE];

// LVGL display and input devices
static lv_display_t *disp;
static lv_indev_t *indev;
  • Automatically refresh temperature and humidity data in real time.
// Real-time temperature and humidity label objects
lv_obj_t *temp_label;
lv_obj_t *humi_label;

// Sensor update
void update_sensor_values() {
  int temperature = dht20.getTemperature();
  int humidity = dht20.getHumidity();

  // If you have corresponding labels in ui.h, you can uncomment the following lines to update the UI:
  lv_label_set_text_fmt(temp_label, "%d", temperature);
  lv_label_set_text_fmt(humi_label, "%d", humidity);

  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.println(" °C");

  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.println(" %");
}
  • Touch reading function
// Touch reading
uint16_t touchX, touchY;
void my_touchpad_read(lv_indev_t *indev, lv_indev_data_t *data) {
  if (lcd.getTouch(&touchX, &touchY)) {
    data->state = LV_INDEV_STATE_PRESSED;
    data->point.x = touchX;
    data->point.y = touchY;
  } else {
    data->state = LV_INDEV_STATE_RELEASED;
  }
}
  • Refresh function
// Refresh function
void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);
  lcd.pushImage(area->x1, area->y1, w, h, (uint16_t *)px_map);
  lv_display_flush_ready(disp);
}
  • Obtain the tick time
// Get tick time
uint32_t my_tick() {
  return millis();
}

Set Up Part

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


    // IO pin setup
    pinMode(25, OUTPUT);
    digitalWrite(25, LOW);

  // Initialize I2C
  Wire.setPins(22, 21);
  Wire.begin();
  dht20.begin();

  // Initialize LCD
  lcd.begin();
  lcd.setRotation(1);        // Adjust screen orientation as needed
  lcd.setSwapBytes(true);    // Swap RGB and BGR data
  lcd.fillScreen(TFT_BLACK);
  delay(300);

  // Backlight control
  pinMode(27, OUTPUT);
  digitalWrite(27, HIGH);
  lcd.setTouch(calData);

  // Initialize LVGL
  lv_init();
  lv_tick_set_cb(my_tick);

  // Create display driver
  disp = lv_display_create(SCREEN_WIDTH, SCREEN_HEIGHT);
  lv_display_set_flush_cb(disp, my_disp_flush);
  lv_display_set_buffers(disp, draw_buf, NULL, sizeof(draw_buf), LV_DISPLAY_RENDER_MODE_PARTIAL);

  // Register touch input device
  indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  lv_indev_set_read_cb(indev, my_touchpad_read);

  // Initialize UI
  ui_init();


  // Create temperature label
  temp_label = lv_label_create(lv_screen_active());
  lv_obj_set_style_text_font(temp_label, &lv_font_montserrat_14, 0);  // Can be replaced with a larger font
  lv_obj_align(temp_label, LV_ALIGN_CENTER, -20, -50);  // Centered and offset upward
  lv_label_set_text(temp_label, "--");

  // Create humidity label
  humi_label = lv_label_create(lv_screen_active());
  lv_obj_set_style_text_font(humi_label, &lv_font_montserrat_14, 0);
  lv_obj_align(humi_label, LV_ALIGN_CENTER, -20, 25);   // Centered and offset downward
  lv_label_set_text(humi_label, "--");

}

Main Program Part

void loop() {
  static unsigned long last_update = 0;

  if (millis() - last_update > 2000) {
    update_sensor_values();
    last_update = millis();
  }

  lv_timer_handler();  // Handle LVGL tasks
  delay(5);
}

// Entry point for ESP-IDF
extern "C" void app_main() {
  setup();
  while (true) {
    loop();
  }
}

Setup board

img54

img55

All required configuration options are defined in the "sdkconfig.defaults" file.

img58

Download the program

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

img65

After confirming the serial port, select the UART mode.

img66

After the program is successfully downloaded, connect the DHT20 sensor to the IIC port and the LED to GPIO_D (IO25), the temperature and humidity values will be displayed on the screen. Click the ON button on the screen and the LED will turn on. Click the OFF button and the LED will turn off.

img67