Building an ESP32-based Smart Switch with LVGL Display: Part 1 - Basic Setup and Display

Esp32 10 Th08 2024

Project Intro

Welcome to our series on building a sophisticated ESP32-based smart switch! Our final product will feature a touch-enabled LVGL display, WiFi connectivity, MQTT integration for remote control, and audio feedback. This powerful device will allow you to control your home appliances with style and ease.

In this first post, we'll focus on setting up the foundation of our project: configuring the ESP32 and getting a basic display up and running. By the end of this tutorial, you'll have a working ESP32 setup with a simple LVGL interface displayed on screen.

Let's dive in!

wt32-sc01-basic-setup-and-display
Part 1 - Basic Setup and Display

Important Note on Libraries and Hardware

This project utilizes the following libraries and hardware:

ArduinoGFX Library: Version 1.4.7 (the latest as of this writing)
LVGL Library: Version 8.3.11
While newer versions (9.x) of LVGL exist, we're using 8.3.11 for two reasons:
* Compatibility with the Squareline software, which will be used in later parts of this series.
* Long-term support for the 8.x versions.
Hardware: WT32SC01 board (standard version, not the Plus variant)

While this guide is tailored for the WT32SC01 board, you can make minor adjustments to adapt it for other hardware. The principles and most of the code will remain applicable across various ESP32-based boards with suitable displays.

WT32-SC01 Board Config

TFT (ST7796)

  • TFT_RST=22
  • TFT_SCLK=14
  • TFT_DC=21
  • TFT_CS=15
  • TFT_MOSI=13
  • TFT_MISO=-1
  • TFT_BCKL=23

Touch (FT6336U)

  • TOUCH_SDA=18
  • TOUCH_SCL=19
  • I2C_TOUCH_ADDRESS=0x38

Step-by-step Instruction

Step 1: Setting up the Arduino IDE and ESP32 board

First, ensure you have the Arduino IDE installed and configured for ESP32 development. If you haven't done this yet, follow these steps:

  1. Download and install the Arduino IDE from the official website.
  2. Open Arduino IDE, go to File > Preferences (or Arduino > Settings in MacOS).
  3. In "Additional Board Manager URLs", add:
    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  4. Go to Tools > Board > Boards Manager, search for "esp32" and install the ESP32 board package.
  5. Select your ESP32 board from Tools > Board > ESP32 Arduino.
arduino-ide-open-preferences
Arduino IDE - Open Preferences

Step 2: Installing Required Libraries

We'll need two main libraries for this part of the project:

  1. Arduino_GFX: A hardware-agnostic graphics library.
  2. LVGL: A powerful and easy-to-use embedded GUI library.

To install these:

  1. Go to Tools > Manage Libraries in the Arduino IDE.
  2. Search for "arduino gfx" and install the version 1.4.7.
  3. Search for "lvgl" and install the version 8.3.11.

After installing LVGL v8.3.11, you will need to configure the lv_conf.h in the folder Arduino > libraries with this attached lv_conf.h. (download > replace the old file)

GitHub - moononournation/Arduino_GFX: Arduino GFX developing for various color displays and various data bus interfaces
Arduino GFX developing for various color displays and various data bus interfaces - moononournation/Arduino_GFX
Arduino GFX Repository
arduino-gfx-v1.4.7
Arduino GFX v1.4.7
GitHub - lvgl/lvgl at release/v8.3
Embedded graphics library to create beautiful UIs for any MCU, MPU and display type. - GitHub - lvgl/lvgl at release/v8.3
LVGL Repository
lvgl-v8.3.11
LVGL v8.3.11

Step 3: Basic Code Structure

Let's start with the basic structure of our Arduino sketch:

#include <Arduino.h>
#include <Arduino_GFX_Library.h>
#include <lvgl.h>

#define GFX_BL 23 // Backlight control pin

// Display setup
Arduino_DataBus *bus = new Arduino_ESP32SPI(21 /* DC */, 15 /* CS */, 14 /* SCK */, 13 /* MOSI */, GFX_NOT_DEFINED /* MISO */);
Arduino_GFX *gfx = new Arduino_ST7796(bus, 22 /* RST */, 3 /* rotation */, false /* IPS */);

static const uint32_t screenWidth = 480;  // Screen width
static const uint32_t screenHeight = 320; // Screen height

static lv_disp_draw_buf_t draw_buf;    // LVGL draw buffer
static lv_color_t *disp_draw_buf;      // LVGL color buffer
static lv_disp_drv_t disp_drv;         // LVGL display driver

// Function declarations
void initDisplay();     // Initialize display
void initLVGL();        // Initialize LVGL
void setupLVGLBuffer(); // Setup LVGL buffer
void setupLVGLDriver(); // Setup LVGL driver
void createSimpleUI(); // Create a simple user interface

// Callback function to flush data from LVGL buffer to the display
void my_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);

void setup() {
  Serial.begin(115200);
  
  initDisplay();
  initLVGL();
  createSimpleUI();
}

void loop() {
  lv_timer_handler(); // Handle LVGL tasks
  delay(5);
}

// Initialize and configure the display
void initDisplay() {
  gfx->begin();
  gfx->fillScreen(BLACK);

  #ifdef GFX_BL
    pinMode(GFX_BL, OUTPUT);
    digitalWrite(GFX_BL, HIGH);
  #endif
}

// Initialize LVGL and related components
void initLVGL() {
  lv_init();
  setupLVGLBuffer();
  setupLVGLDriver();
}

// Setup buffer for LVGL
void setupLVGLBuffer() {
    uint32_t bufSize = screenWidth * 40;
    disp_draw_buf = (lv_color_t *)heap_caps_malloc(bufSize * sizeof(lv_color_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
    if (!disp_draw_buf) {
        Serial.println("LVGL disp_draw_buf allocate failed!");
        return;
    }
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, bufSize);
}

// Setup display driver for LVGL
void setupLVGLDriver() {
  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);
}

// Create a simple user interface with a label
void createSimpleUI() {
  lv_obj_t * label = lv_label_create(lv_scr_act());
  lv_label_set_text(label, "Hello, ESP32-WT32SC01!");
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
}

// Callback function to flush data from LVGL buffer to the display
void my_disp_flush(lv_disp_drv_t *disp_drv, 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_drv);
}

Step 4: Upload and Test

Compile and upload this code to your ESP32. If everything is set up correctly, you should see "Hello, ESP32-WT32SC01!" displayed on your screen.

Congratulations! You've successfully set up the basic structure for our ESP32 smart switch project. You now have a working ESP32 with a display showing a simple LVGL interface.

wt32sc01-board-setup
WT32SC01 Board Setup to Compile

Code Explain

Unlock the secrets of this project! Subscribe for a detailed code walkthrough.

Tags

Tony Phạm

Là một người thích vọc vạch và tò mò với tất cả các lĩnh vực từ khoa học tự nhiên, lập trình, thiết kế đến ... triết học. Luôn mong muốn chia sẻ những điều thú vị mà bản thân khám phá được.