Skip to content
Buy 10+ on select items — save 10% auto-applied
Free US shipping on orders $35+
Order by 3pm ET — ships same-day from the US
Skip to main content

ESP32 LVGL Display: Touchscreen Smart Switch UI | ShillehTek

June 13, 2026 8 views

ESP32 LVGL Display: Touchscreen Smart Switch UI | ShillehTek
Project

Build an ESP32 LVGL touchscreen smart switch UI with relay control, a DHT22 temperature gauge, and MQTT updates for Home Assistant using ShillehTek parts.

Intermediate5 parts
ESP32 LVGL 2.8-inch resistive touchscreen smart display showing a smart switch-style UI

Project Overview

ESP32 + LVGL touchscreen display smart switch UI: Build a slick touchscreen interface on an ESP32 LVGL 2.8-inch Smart Display that can toggle a relay, show live temperature data, and publish state to Home Assistant over MQTT.

Using the LVGL graphics library gets you modern UI widgets (buttons, sliders, gauges, charts) and smooth partial redraws that feel closer to commercial panels. The trade-off is higher RAM usage, but the ESP32 has enough SRAM for typical LVGL projects.

  • Time: About 30 minutes
  • Skill level: Intermediate
  • What you will build: A working ESP32 touchscreen smart switch UI with relay control, sensor display, and MQTT publishing

Parts List

From ShillehTek

External

  • USB-C cable - to power and program the ESP32 display board.
  • An MQTT broker - Mosquitto on a Raspberry Pi or Home Assistant's built-in broker.
  • Arduino IDE 2.x with the ESP32 board package and LVGL / TFT_eSPI libraries.

Note: The ESP32 LVGL display board referenced here is a single PCB with ESP32-WROOM-32, a 240x320 ILI9341 TFT, and an XPT2046 resistive touch controller. Use the product page pinout and library configuration for your specific board revision.

Step-by-Step Guide

Step 1 - Understand why LVGL is a better UI toolkit

Goal: Pick the right graphics approach for a touchscreen smart switch UI.

What to do: If you are coming from direct-draw libraries like Adafruit_GFX (or raw TFT_eSPI drawing calls), note that those are great for simple primitives. LVGL is a retained-mode UI toolkit where widgets keep state, redraws are partial and smooth, and you can design layouts visually with SquareLine Studio and export C code.

Expected result: You understand the main trade-off: LVGL uses more RAM (around 30 KB minimum), but the ESP32's SRAM is typically sufficient for this class of UI.

LVGL user interface running on an ESP32 240x320 touchscreen display
LVGL widgets and styling enable a more polished touchscreen UI than simple direct-draw graphics.

Step 2 - Set up the ESP32 LVGL display hardware

Goal: Confirm what is already integrated on the display board and what you need to wire.

What to do: The ShillehTek ESP32 LVGL display is a single PCB with the ESP32 module, ILI9341 240x320 TFT, XPT2046 resistive touch, and USB-C. Plug in USB-C to power and program the board. Use the board's product page for the correct library and pin configuration.

Expected result: Your board powers up over USB-C and you are ready to compile and upload an Arduino sketch.

Step 3 - Upload a quick "Hello LVGL" sketch

Goal: Initialize LVGL and draw a basic button on the display.

What to do: Install the required libraries (LVGL and TFT_eSPI) in Arduino IDE, then upload a minimal LVGL example that initializes the display driver, sets up a draw buffer, and creates a centered button with a label.

Code:

#include <lvgl.h>
#include <TFT_eSPI.h>
#include "touch.h"   // XPT2046 helper

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[240 * 10];

void my_disp_flush(lv_disp_drv_t *d, const lv_area_t *a, lv_color_t *p) {
  tft.startWrite();
  tft.setAddrWindow(a->x1, a->y1, a->x2-a->x1+1, a->y2-a->y1+1);
  tft.pushColors((uint16_t*)&p->full, (a->x2-a->x1+1)*(a->y2-a->y1+1), true);
  tft.endWrite();
  lv_disp_flush_ready(d);
}

void setup() {
  tft.begin(); tft.setRotation(1);
  lv_init();
  lv_disp_draw_buf_init(&draw_buf, buf1, NULL, 240*10);
  static lv_disp_drv_t drv;
  lv_disp_drv_init(&drv);
  drv.flush_cb = my_disp_flush;
  drv.hor_res = 320; drv.ver_res = 240;
  drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&drv);

  lv_obj_t* btn = lv_btn_create(lv_scr_act());
  lv_obj_center(btn);
  lv_obj_t* lbl = lv_label_create(btn);
  lv_label_set_text(lbl, "Hello LVGL!");
}
void loop() { lv_timer_handler(); delay(5); }

Expected result: The screen shows a centered LVGL button with the text "Hello LVGL!".

Step 4 - Add a relay-toggle button to the UI

Goal: Toggle a GPIO that controls a relay module from the touchscreen button.

What to do: Choose the relay GPIO (example below uses GPIO 32). Create an LVGL button, attach an event callback, and update both the relay output level and the on-screen label when the user taps.

LVGL touchscreen relay toggle button UI on an ESP32 smart display
A simple LVGL button can act as a smart switch for a relay output.

Code:

const int RELAY = 32;
bool relayOn = false;

static void toggle_cb(lv_event_t* e) {
  relayOn = !relayOn;
  digitalWrite(RELAY, relayOn ? HIGH : LOW);
  lv_obj_t* btn = lv_event_get_target(e);
  lv_label_set_text(lv_obj_get_child(btn, 0),
                     relayOn ? "Light ON" : "Light OFF");
}

void setup() {
  pinMode(RELAY, OUTPUT);
  // ... LVGL init from step 3 ...
  lv_obj_t* btn = lv_btn_create(lv_scr_act());
  lv_obj_set_size(btn, 200, 80);
  lv_obj_center(btn);
  lv_obj_add_event_cb(btn, toggle_cb, LV_EVENT_CLICKED, NULL);
  lv_obj_t* lbl = lv_label_create(btn);
  lv_label_set_text(lbl, "Light OFF");
}

Expected result: Tapping the on-screen button flips the relay GPIO and updates the label between "Light OFF" and "Light ON".

Step 5 - Display live data with an animated gauge

Goal: Show a live temperature reading on the UI.

What to do: Read the DHT22 periodically (for example, every 2 seconds) and feed the value into an lv_meter widget. This gives you a swept-needle style gauge that updates smoothly.

Expected result: The screen shows a temperature gauge that updates on a timed interval as new DHT22 readings arrive.

Step 6 - Publish state to Home Assistant over MQTT

Goal: Send button/relay state changes to your MQTT broker so Home Assistant can track and control the entity.

What to do: Add the PubSubClient library, connect the ESP32 to WiFi, and publish a message (example topic: home/livingroom/light) whenever the LVGL button is pressed. You can also subscribe to the same topic (or a command topic) to reflect state changes initiated in Home Assistant back on the display.

ESP32 LVGL display integrated with Home Assistant using MQTT topics
MQTT is a straightforward bridge between the touchscreen UI and Home Assistant entities.

Expected result: Home Assistant detects the MQTT messages and you can control or monitor the smart switch state from other devices.

Step 7 - Use SquareLine Studio for more complex UIs

Goal: Speed up multi-screen UI creation without manually calculating layout positions.

What to do: For multi-page interfaces (settings, dashboards, animated transitions), use SquareLine Studio to design the UI visually, then export the generated C code and integrate it into your Arduino project.

Expected result: You can iterate on a polished UI faster, while still running everything locally on the ESP32.

Conclusion

You built an ESP32 LVGL touchscreen smart switch UI that can toggle a relay, display live DHT22 temperature data, and publish state changes over MQTT for Home Assistant integration. This workflow gives you a modern, smooth UI on inexpensive hardware while keeping the firmware fully under your control.

Want the exact parts used in this build? Grab them from ShillehTek.com. If you want help customizing this project or building something for your product, check out our IoT consulting services.

Attribution: This guide was inspired by "Building an ESP32-based Smart Switch With LVGL Display" on Instructables.