Skip to content

About

Self-contained Arduino library for LVGL on 4" 480x480 ESP32-S3 display

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chipguy_4848S040_display

A self-contained display + touch + relay driver for the ESP32-S3 4848S040 development board — the 4.0" board with a 480×480 ST7701 RGB LCD, a GT911 capacitive touch panel, and up to 3 onboard relays. It drives all of these so you don't have to think about any of them: the hardware is fixed and fully handled, leaving you to write an LVGL 9 app and nothing else.

The two bundled examples are the heart of the library. Each is a complete, working starting point — the display, touch, and LVGL are already wired up and running before your code gets control. You pick the one that matches how you want to build your UI, copy it, and start replacing its placeholder UI with your own.

This is for the ST7701 480×480 RGB-interface variant of the 4848S040 (ESP32-S3, OPI PSRAM). Other 4848-style boards with different panels need a different library.


Installation

This library is distributed by downloading the code as a ZIP from GitHub — there is no Arduino Library Manager entry. To install:

  1. On the GitHub project page, click Code ▸ Download ZIP.
  2. Unzip it, and move the resulting folder into your Arduino libraries directory:
    • macOS / Linux: ~/Documents/Arduino/libraries/
    • Windows: Documents\Arduino\libraries\
  3. Restart Arduino IDE so the examples will appear in the File menu.

(Alternatively, in the IDE: Sketch ▸ Include Library ▸ Add .ZIP Library… and select the downloaded ZIP.)

Dependency: LVGL 9

The examples need LVGL 9. Install it via the Arduino Library Manager (search "lvgl"). Each example sketch folder ships its own lv_conf.h; LVGL reads its configuration from that file, so keep it next to the .ino.

This library was developed against LVGL 9.3 (the current version of LVGL that is compatible with SquareLine) but is very likely compatible with later versions.

Arduino IDE board settings

This board uses a generic ESP32-S3 board definition. In Tools, set:

  • Board: ESP32S3 Dev Module
  • PSRAM: OPI PSRAM (required — the framebuffers live in PSRAM)
  • Flash Size: 16 MB (128 Mbit)
  • USB CDC On Boot: Enabled (required to see serial output)
  • Upload Speed: 460800

Serial note: USB serial on this board is Serial0, not Serial. With "USB CDC On Boot" enabled, Serial0.begin(115200) prints to the USB port.


The two examples — pick your starting point

Open them from File ▸ Examples ▸ chipguy_4848S040_display. Both come up running on the hardware immediately, so you can confirm your board works before you change a line. They differ only in how you author the UI.

To turn either one into your own project, save it under a new name (File ▸ Save As) so your work lives outside the library, then start editing. Each example folder is self-contained — it carries its own lv_setup.hpp and lv_conf.h — so a copied sketch is fully standalone.

LvglClaudeCodeStub — write the UI yourself (by hand or with an AI)

Use this when you want to build the interface in code: directly, or by handing the sketch to an AI coding assistant such as Claude Code.

The UI lives in a tiny ui.h / ui.cpp pair in the sketch folder. All the hardware/LVGL setup happens in the sketch before ui_init() is called, so ui_init() is a blank canvas: it receives a live LVGL screen and you create widgets on it. To start your app:

  1. Open ui.cpp and look at ui_init(). The demo it ships with (a label that follows your finger, plus a color-cycling rectangle) is just there to prove the display and touch work — delete it.
  2. In its place, build your own UI on lv_screen_active() using normal LVGL calls (lv_label_create, lv_button_create, event callbacks, …).
  3. As your app grows, add more screens and helper functions, and declare the ones the sketch needs in ui.h.

Because everything except the UI is already wired up, this scaffold is ideal to hand to Claude Code: point it at the sketch folder and describe the app you want — it can focus entirely on ui.cpp and the screens you add, without touching display/touch/LVGL plumbing.

Reach for this one when you want full control, a tiny footprint, or AI-assisted/hand-written UI code.

Lvgl93SquarelineLauncher — design the UI visually in SquareLine Studio

Use this when you'd rather design the interface visually in SquareLine Studio (a drag-and-drop LVGL UI editor) and just run the result on the board.

The sketch's src/ folder holds a small placeholder UI in the exact file shape a SquareLine export produces (ui.c, ui_Screen1.c, …). The sketch calls the ui_init() that SquareLine generates. To start your app:

  1. In SquareLine Studio, create a project sized 480×480, 16-bit color, with no rotation or offset.
  2. Lay out your screens visually.
  3. Export ▸ UI files (the "Arduino TFT_eSPI profile" works, among others).
  4. Replace the whole src/ folder with your export. Build and upload — ui_init() now runs your design.

Treat src/ as disposable: you overwrite it wholesale each time you re-export from SquareLine, so don't keep anything there. Your own application logic lives in the sketch — after calling ui_init(), attach event handlers from the .ino to the UI objects SquareLine exposes (e.g. ui_Button1). That way re-exporting the visuals never touches your code.

Reach for this one when you want to iterate on layout visually and write little or no C for the UI itself.


What the examples give you: the lv_setup API

Both examples wire the hardware to LVGL through one small header, lv_setup.hpp (plus lv_conf.h for LVGL's build config). That header, and the global objects it defines, is the entire surface you interact with — and once begin() returns, you are just using plain LVGL.

#include "lv_conf.h"
#include "lvgl.h"
#include "lv_setup.hpp"

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

    lv_setup.begin();           // initialize display + touch + LVGL

    // ...build your UI on lv_screen_active() here (or call ui_init())...
}

void loop() {
    lv_timer_handler();         // let LVGL run
    delay(5);
}

What the header provides:

  • lv_setup.begin() — call once in setup(). Brings up the ST7701 display, the GT911 touch, and LVGL; allocates the two PSRAM framebuffers, creates the LVGL display in direct render mode plus a pointer (touch) input device, and connects them. After this returns, the active LVGL screen exists and you build your UI with ordinary LVGL calls.
  • display — a global ESP32_4848S040 display object. Handy methods: display.width(), display.height() (480×480), and display.setBacklight(0..100) to dim/brighten the backlight.

You don't render or flush anything yourself — LVGL renders straight into the panel's framebuffers and the driver flips them at vsync (tear-free, double buffered). Your job is to create LVGL widgets and call lv_timer_handler() in loop().

Portable across chipguy board libraries

Because every hardware detail lives in just two files — lv_setup.hpp and lv_conf.h — your application code (ui.cpp, or the SquareLine src/ files) is hardware-independent. It only ever talks to LVGL.

So to move an app to a different display board, drop in the lv_setup.hpp and lv_conf.h from that board's chipguy library, and the rest of your sketch is unchanged. The same UI runs on different panels with no edits to your widget code. (Different boards have different resolutions, so alignment-based layouts travel best; fixed pixel coordinates may need adjusting.)


The onboard relays

Beyond display and touch, the board has 3 relays, driven by ESP32_4848S040_Relays:

#include <chipguy_4848S040_relays.h>

ESP32_4848S040_Relays relays;

void setup() {
    relays.begin();                 // pins as outputs
    relays.setRelayEnergized(1);    // relay 1 ON
    relays.setRelayOff(1);          // relay 1 OFF
    relays.setRelay(2, HIGH);       // explicit state, relays 1..3
}

Relay states are held across a warm reset (watchdog timeout, software reset, task panic). Each relay pin uses the ESP32 GPIO hold latch, which lives in the always-on RTC power domain and is released only by a power-on reset or an explicit change — so the pad keeps physically driving its level straight through a watchdog reboot, with no drop even during the boot window before your code runs. The last commanded state is also saved in RTC memory so relays.begin() can re-establish the hold glitch-free on the way back up. A true power-on intentionally starts with all relays OFF (the latch and RTC memory are both cleared on power loss), so relays won't surprise-energize when power returns.


License

This library is mixed-license:

  • The original code (display driver, relay driver, examples) is MIT — see LICENSE.
  • The GT911 touch driver (chipguy_4848S040_touch.h / .cpp) is a derivative of TAMC_GT911 (Copyright © TAMC) and is licensed under the Apache License, Version 2.0 — see LICENSE-Apache-2.0.txt. Those files carry the upstream attribution and note the modifications made for this board.

The ST7701 initialization/gamma values are standard panel register settings. lv_conf.h is based on LVGL's template (LVGL is MIT-licensed).

About

Self-contained Arduino library for LVGL on 4" 480x480 ESP32-S3 display

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages