The Waveshare 1.69 inch display module built on the ESP32-S3 microcontroller offers a streamlined foundation for interactive hardware development.
With integrated components such as a six-axis IMU, ESP32-S3 RTC configuration, and adaptable power management, it provides the essential tools for responsive, sensor-based projects.
In this guide, I detail the ESP32-S3 Arduino setup, covering everything from efficient battery charging strategies to gyroscope integration and precise accelerometer setup.
Using the ESP32-S3 Arduino IDE configuration, I outline how to optimize functionality while maintaining performance.
This approach enables me to fully utilize the capabilities of the board for professional-grade prototyping and deployment.
Note: Multiple versions of this development board exist. This guide specifically references Version 2 (V2) of the Waveshare ESP32-S3 1.69 inch display module.

Overview of the Waveshare ESP32-S3 1.69″ Display Board
Key Specifications
The Waveshare 1.69 inch display module delivers a compact and high-performance visual interface with a native ESP32-S3 display resolution of 240×280 pixels and support for 262K colors.
This configuration ensures clarity and depth for rendering custom UI elements, whether for data visualization or real-time feedback in embedded systems.
Specification | Details |
---|---|
Screen Size | 1.69 inches |
Resolution | 240×280 pixels |
Colors | 262K colors |
Core Components
Powered by the ESP32-S3R8 dual-core processor, this module includes 8MB of PSRAM and 16MB of flash memory, resources well-suited for handling GUI development tasks, as well as advanced features like gesture recognition and motion tracking.
The board supports efficient sketch uploading and library installation workflows via the Arduino IDE.
Component | Details |
---|---|
Processor | ESP32-S3R8 dual-core |
PSRAM | 8MB |
Flash Memory | 16MB |
Onboard Features
The integrated PCF85063 module enables accurate Real Time Clock (RTC) configuration, while the QMI8658 sensor supports both gyroscope integration and accelerometer setup.
A programmable buzzer enhances interaction design through basic buzzer usage, and the USB Type-C port simplifies both power delivery and serial monitor access.
Feature | Details |
---|---|
RTC | PCF85063 |
Six-Axis IMU | QMI8658 |
Buzzer | Yes |
USB Port | Type-C |
Connectivity
With onboard support for Wi-Fi 802.11 b/g/n and Bluetooth 5 (LE), the board is optimized for I2C communication and UART interface projects, particularly those requiring wireless data exchange or remote sensor interaction.
Connectivity | Details |
---|---|
Wi-Fi | 802.11 b/g/n |
Bluetooth | 5 (LE) |
Power Management
The ETA6098 chip manages efficient battery charging, while the programmable power button can be configured for various power management routines, including low-power mode activation or conditional wake-ups via external triggers.
Power Management | Details |
---|---|
Charging Chip | ETA6098 |
Power Button | Yes, it’s programmable |
This board’s features make it a robust platform for microcontroller-based applications, especially when paired with tools like SquareLine Studio, the TFT_eSPI library, and LVGL integration.
Its compact form factor, combined with advanced capabilities, supports a wide range of creative and technical implementations.
Pin Definitions
Pin Label | GPIO | Function |
---|---|---|
GPIO18 | GPIO18 | SPI Clock (SCK) / General Purpose I/O |
GPIO17 | GPIO17 | Backlight Control (BL) / GPIO |
GPIO16 | GPIO16 | Chip Select (CS) / GPIO |
GPIO3 | GPIO3 | Reset (RST) / GPIO |
GPIO2 | GPIO2 | Data/Command (DC) / GPIO |
SDA | GPIO11 | I²C Data (SDA) |
SCL | GPIO10 | I²C Clock (SCL) |
U0TXD | GPIO43 | UART0 Transmit |
U0RXD | GPIO44 | UART0 Receive |
3.3V | — | 3.3V Power Supply |
GND | — | Ground |
5V | — | 5V Input (USB / Battery Boost) |

Setting Up the Arduino IDE for Your ESP32-S3
Working with the Waveshare 1.69 inch display powered by the ESP32-S3 opens up an environment for interactive and visual experimentation.
To begin, you need to configure the Arduino IDE in order to ensure compatibility and stability throughout development.
Installing Arduino IDE
First, download and install the latest version of the Arduino IDE from the official Arduino website.
This environment serves as the foundation for sketch uploading, firmware flashing, and efficient management of connected modules.

Adding ESP32 Support
To enable ESP32 development, navigate to File > Preferences, then add the following URL to the “Additional Boards Manager URLs” field:
https://dl.espressif.com/dl/package_esp32_index.json
Or if you’re like me and you work with multiple development boards:
http://arduino.esp8266.com/stable/package_esp8266com_index.json,https://dl.espressif.com/dl/package_esp32_index.json,https://espressif.github.io/arduino-esp32/package_esp32_index.json
After confirming, open Tools > Board > Boards Manager, search for “ESP32”, and install the package by Espressif Systems.
This step prepares the environment for ESP32-S3 library installation and board integration.

Selecting the Correct Board
From the Tools > Board menu, select ESP32S3 Dev Module.
This step is essential for accurate ESP32-S3 bootloader mode, ESP32-S3 reset procedure, and hardware-level operations.
Specifically you need to following settings:
Setting | Value |
---|---|
Board | ESP32S3 Dev Module |
Port | Select your connected port |
USB CDC On Boot | Enable |
CPU Frequency | 240MHz (Wi-Fi) |
Core Debug Level | None |
USB DFU On Boot | Disable |
Erase All Flash Before Sketch Upload | Disable |
Events Run On | Core1 |
Flash Mode | QIO 80MHz |
Flash Size | 16MB (128Mb) |
Arduino Runs On | Core1 |
USB Firmware MSC On Boot | Disable |
Partition Scheme | 16M Flash (3M APP/9.9MB FATFS) |
PSRAM | OPI PSRAM |
Upload Mode | UART0/Hardware CDC |
Upload Speed | 921600 |
USB Mode | CDC and JTAG |
Installing Key Libraries
To activate display and communication functions, I open Sketch > Include Library > Manage Libraries and install:
- TFT_eSPI: for advanced TFT_eSPI library support and control of the ST7789V2 driver.
- Wire: to enable reliable I2C communication.

Downloading and Installing the Official Waveshare Demo Code
To ensure complete functionality with the Waveshare 1.69 inch display, begin by downloading the official demo code provided by Waveshare.
This resource is available on their wiki and is essential for referencing validated examples that align with the board’s hardware specifications.
After downloading the ESP32-S3-LCD-1.69 Demo
, navigate to the Arduino-v3.0.5
directory and locate the libraries
folder.
These files contain important configurations and drivers.
- Copy all contents from the
libraries
folder. - paste them into my standard Arduino libraries path:
Documents > Arduino > libraries
Alternatively, for project-specific organization, I prefer using a dedicated development directory.
In this case, I adjust the Arduino IDE configuration by opening File > Settings and changing the Sketchbook Location to point to my custom directory.
This approach enables better modularity when managing different library installations or hardware profiles.
This setup forms the technical backbone of my work across both visual and responsive media.

Wiring and Powering the ESP32-S3 Display Board
When configuring the Waveshare 1.69 inch display with the ESP32-S3, ensuring correct power and connection setup is critical for reliable performance.
Below is my workflow for establishing power and preparing the board for development.
USB Type-C Connection for Programming and Power
The ESP32-S3 is powered and programmed via its USB Type-C interface.
This single connection provides both data and power transfer, streamlining the setup process for ESP32-S3 sketch uploading and serial communication through the ESP32-S3 serial monitor.
Portable Power via the MX1.25 Lithium Battery Interface
For portable or embedded projects, the onboard MX1.25 connector supports lithium battery input, enabling mobile use without sacrificing performance.
This option integrates directly into power management workflows, particularly for battery-based installations.
- Use a lithium battery compatible with the MX1.25 connector.
- Securely attach it to the battery port on the board.
- Ensure all contacts are stable to avoid intermittent power loss.
This feature pairs well with battery charging capabilities for autonomous, field-deployable projects.

Understanding the function of the BOOT and RST buttons is key for flashing and resetting the board.
These manual controls are essential for entering bootloader mode and executing the reset procedure during development.
- BOOT Button: Hold down BOOT and tap RST to enter flash mode. Release RST first, then BOOT.
- RST Button: Press to perform a system reset without disconnecting power.
These controls ensure smooth transitions when updating code or troubleshooting unstable behavior.
The board includes a programmable power button, which can be configured for user-defined behavior.
I use it to optimize low-power mode activation, idle handling, or triggering UI states in response to physical input.
Steps:
- Write logic in the
setup()
andloop()
functions to define press events (single, double, long press). - Assign actions such as sleep, wake, or mode switching.
- Upload to the board and test your defined routines.
This feature gives flexible control over how power is managed in various interaction scenarios, making it invaluable for energy-efficient and responsive systems.
This foundation allows to focus on designing dynamic, sensor-aware experiences using the full capabilities of the ESP32-S3 architecture.
Running Your First Sketch
To validate that the Waveshare 1.69 inch display and graphics interface are functioning correctly, you can start with the official 01_HelloWorld.ino
sketch provided in the demo files.
This example demonstrates essential initialization steps for ESP32-S3 GUI development using the Arduino_GFX_Library.
Preparing the Environment
The sketch requires the Arduino GFX Library and associated pin configuration headers included in the Waveshare demo package.
This setup ensures compatibility with the ESP32-S3 display and correct handling of the display resolution.
Code Overview
Below is a simplified breakdown of the Hello World
example, which uses SPI communication and hardware USB CDC for serial output:
#include <Arduino.h>
#include "Arduino_GFX_Library.h"
#include "pin_config.h"
#include <Wire.h>
#include "HWCDC.h"
HWCDC USBSerial;
Arduino_DataBus *bus = new Arduino_ESP32SPI(LCD_DC, LCD_CS, LCD_SCK, LCD_MOSI);
Arduino_GFX *gfx = new Arduino_ST7789(bus, LCD_RST, 0, true, LCD_WIDTH, LCD_HEIGHT, 0, 20, 0, 0);
This initializes the ESP32-S3 I2C communication (via Wire
) and sets up the ST7789 driver using SPI, laying the foundation for advanced ESP32-S3 TFT_eSPI library or ESP32-S3 LVGL integration down the line.
In the setup()
function:
USBSerial.begin(115200);
gfx->begin();
gfx->fillScreen(BLACK);
pinMode(LCD_BL, OUTPUT);
digitalWrite(LCD_BL, HIGH);
gfx->setCursor(10, 10);
gfx->setTextColor(RED);
gfx->println("Hello World!");
delay(5000);
This initializes the display and serial output, sets the screen background, turns on the backlight using GPIO usage, and renders the initial message.
The loop()
continuously updates the display:
gfx->setCursor(random(gfx->width()), random(gfx->height()));
gfx->setTextColor(random(0xffff), random(0xffff));
gfx->setTextSize(random(6), random(6), random(2));
gfx->println("Hello World!");
delay(1000);
Here, random positions, colors, and sizes introduce dynamic visual behavior, useful when exploring animation or custom UI experiments.
Uploading the Sketch
Once the code is ready:
- Open Arduino IDE and ensure correct Arduino IDE configuration.
- Select ESP32S3 Dev Module under Tools > Board.
- Connect the board via USB Type-C for sketch uploading and serial monitor output.
- Confirm that necessary libraries (
Arduino_GFX_Library
,HWCDC
) are installed via Sketch > Include Library > Manage Libraries. - Compile and upload the sketch.
After upload and a proper reset procedure, the display shows a static red “Hello World!” followed by randomized, animated text.
This confirms successful firmware flashing, display setup, and interaction with the GPU layer through the GFX library.
With a validated display pipeline in place, you’re ready to expand into full-featured visual projects driven by the board’s powerful features.

Exploring the Built-in Gyroscope and Accelerometer
Working with the QMI8658 Six-Axis IMU
The Waveshare 1.69 inch display development board includes an onboard QMI8658 six-axis IMU, combining both a gyroscope and accelerometer into one integrated module.
This sensor is essential for real-time motion tracking, gyroscope integration, and accelerometer setup, especially when working with motion-responsive or interactive artworks.
Visualizing Sensor Data with LVGL
Rather than printing raw sensor data to the console, you can use the LVGL integration to visualize accelerometer readings as dynamic line charts directly on the display.
This approach helps with prototyping interactive visuals while validating data output from the IMU.
The official 08_LVGL_QMI8658_ui.ino
sketch provides a complete pipeline using I2C communication to read the sensor data, and ESP32-S3 GUI development tools to graph the output in real-time.
Here’s an overview of what this demo does:
- Initializes the display wiring using the
Arduino_GFX_Library
- Sets up LVGL with the display buffer and flush function
- Configures the QMI8658 sensor for high-speed data output
- Continuously updates a full-screen line chart with live accelerometer values
Setting Up the Sensor and Display
In the setup()
function, I configured the sensor with appropriate output data rates and range:
qmi.configAccelerometer(
SensorQMI8658::ACC_RANGE_4G,
SensorQMI8658::ACC_ODR_1000Hz,
SensorQMI8658::LPF_MODE_0,
true);
qmi.configGyroscope(
SensorQMI8658::GYR_RANGE_64DPS,
SensorQMI8658::GYR_ODR_896_8Hz,
SensorQMI8658::LPF_MODE_3,
true);
Both accelerometer and gyroscope are enabled via:
qmi.enableGyroscope();
qmi.enableAccelerometer();
Display and chart objects are initialized with custom UI elements using LVGL’s charting API:
chart = lv_chart_create(lv_scr_act());
lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, -3, 3);
Setting Up the Sensor and Display
In the loop()
function, I poll the IMU using:
if (qmi.getDataReady()) {
qmi.getAccelerometer(acc.x, acc.y, acc.z);
qmi.getGyroscope(gyr.x, gyr.y, gyr.z);
}
New accelerometer values are then fed directly into the chart using:
lv_chart_set_next_value(chart, acc_series_x, acc.x);
lv_chart_set_next_value(chart, acc_series_y, acc.y);
lv_chart_set_next_value(chart, acc_series_z, acc.z);
This real-time visual feedback on the display resolution is extremely helpful for debugging orientation-sensitive behaviors in my projects.
Applications in Interactive Media
By integrating the accelerometer setup and gyroscope integration with responsive UI design, you can explore applications such as:
- Gesture Recognition: Detect motion gestures to control installations or trigger events.
- Live Performance Feedback: Capture body movements and display them visually in exhibitions.
- Spatial Interaction: Use motion data to create context-aware art responsive to audience movement.
With the QMI8658 sensor operational and visual feedback running on LVGL integration, you can have a powerful toolset for designing immersive, movement-aware works.
Advanced Power Management Techniques
Effective energy optimization is essential for any mobile or embedded system.
With the Waveshare ESP32-S3 1.69 inch display board, you can take advantage of integrated power features to extend battery life and maintain responsive performance across projects.
Below are key strategies I’ve implemented using the board’s built-in capabilities.
Understanding the ETA6098 Battery Charging Chip
At the heart of the board’s battery charging system is the ETA6098, a dedicated single-cell lithium charging IC.
It enables safe, reliable charging for lithium-ion or lithium-polymer batteries, directly supporting portable workflows and remote deployment.
Key features include:
- Intelligent charge control with dynamic current management
- Overcharge, overdischarge, and short-circuit protection
- eamless USB and lithium power source switching
To create low-power applications, you can leveraged the programmable power button on the Waveshare 1.69 inch display board.
Using the official 09_LVGL_Keys_bee.ino
example, implemented real-time visual feedback for various button press actions, single, double, and long press, on the display, while managing power logic and buzzer control through ESP32-S3 GPIO usage.
Defining Pins and Modes
The sketch supports two pin configurations (legacy and updated), depending on your hardware version.
These are set using:
#define USE_NEW_PIN_CONFIG 0 // Set to 1 to enable new GPIO mapping
Depending on the setting, the board maps button input, output control, and buzzer usage as follows:
Function | Legacy GPIO | New GPIO |
---|---|---|
Button Input | 36 | 40 |
Output Control | 35 | 41 |
Buzzer (Tone) | 33 | 42 |
These GPIO assignments enable reliable digital input processing and precise tone control.
LVGL Initialization
Display rendering is managed using the Arduino_GFX_Library
and LVGL, with a draw buffer configured for a 240×280 display.
The label object is used to provide visual feedback for each button action.
label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Initializing...");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
This label updates in response to button events detected in the main loop.
Detecting Button Press Events
The button handling logic in the loop detects debounced input states and distinguishes between:
- Single Click: Quick tap within the debounce delay
- Double Click: Two clicks within
clickInterval
(500 ms) - Long Press: Press sustained for more than
longPressDuration
(1000 ms)
Each action triggers corresponding GUI updates and optionally drives the buzzer:
tone(beePin, 2000); // Buzzer on during long press
noTone(beePin); // Stop buzzer on release
This configuration is especially useful for touch functionality replacements in hardware-limited scenarios or where physical feedback is needed.
Monitoring Battery Levels
For portable or battery-powered systems, voltage monitoring is an essential part of responsible power management.
On the Waveshare 1.69 inch display development board, I used a simple voltage divider in combination with ESP32-S3 sensor data reading to track battery levels in real time.
Voltage Measurement with ADC and Voltage Divider
const int voltageDividerPin = 1; // GPIO1 used for ADC input
float vRef = 3.3; // Reference voltage of ESP32-S3
float R1 = 200000.0; // Upper resistor in ohms
float R2 = 100000.0; // Lower resistor in ohms
The voltage conversion logic is as follows:
int adcValue = analogRead(voltageDividerPin);
float voltage = (float)adcValue * (vRef / 4095.0); // Convert ADC to voltage
float actualVoltage = voltage * ((R1 + R2) / R2); // Calculate real battery voltage
Displaying Battery Voltage with LVGL
To enhance user feedback, you can use the GUI development tools via LVGL to display the current battery voltage directly on the screen:
String voltageStr = "Actual Voltage: " + String(actualVoltage) + " V";
lv_label_set_text(label, voltageStr.c_str());
This label is updated continuously within the loop()
using LVGL’s display buffer, offering real-time voltage monitoring on the display resolution.

Exploring Additional Board Features
These components offer expanded interactivity, timekeeping, and hardware integration, crucial for dynamic, sensor-based installations.
Here’s how you can implement buzzer usage with simple GPIO control:
#define BUZZER_PIN 42
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
tone(BUZZER_PIN, 2000);
}
This function can be extended using tone()
for frequency-specific audio cues or layered into a broader ESP32-S3 GUI development context.
Real-Time Clock with PCF85063
Accurate timekeeping is essential for data logging, timed triggers, and synchronizing media. The onboard PCF85063 RTC connects via I2C and supports full calendar and time functions.
Here’s the setup using RTClib
for RTC configuration:
#include <Wire.h>
#include "RTClib.h"
RTC_PCF85063 rtc;
void setup () {
Wire.begin(); // Enables **ESP32-S3 I2C communication**
rtc.begin();
if (!rtc.begin()) {
while (1); // Halt on failure
}
rtc.start();
}
void loop () {
DateTime now = rtc.now();
Serial.printf("%04d/%02d/%02d %02d:%02d:%02d\n",
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second());
delay(1000);
}
General Purpose IO, I2C, and UART Interfaces
The board supports flexible ESP32-S3 GPIO usage with up to 34 input/output pins, ideal for connecting external components:
- GPIO: Control LEDs, read buttons, or trigger relays
- I2C communication: Interface with digital sensors like IMUs, RTCs, or displays
- UART interface: Communicate with external microcontrollers, GPS modules, or serial devices

Introduction to SquareLine Studio for GUI Development
When developing responsive, touch-enabled visual interfaces on the Waveshare ESP32-S3 1.69 inch display, I use SquareLine Studio to design, prototype, and deploy custom graphical UIs with precision.
The platform integrates seamlessly into my GUI development workflow, combining ease of use with production-ready output.
Visual Interface Design with Drag-and-Drop Simplicity
SquareLine Studio provides a graphical environment tailored for embedded systems, allowing me to build intuitive interfaces through a drag-and-drop interface.
It features a robust widget system including buttons, sliders, and images, all aligned with the requirements of ESP32-S3 custom UI development.
This eliminates the need to hand-code layout logic, streamlining both design and iteration.
Widgets are positioned to match the target hardware resolution, specifically ESP32-S3 display resolution of 240×280, and adapted to the 262K-color output of the Waveshare 1.69 inch display, ensuring pixel-perfect rendering.
Designing for the 240×280 Display
Before exporting, I configure the SquareLine Studio canvas to match the display dimensions of the ESP32-S3 Display module:
Feature | Specification |
---|---|
Screen Resolution | 240×280 |
Color Display | 262K |
Exporting to Arduino-Compatible Code
Once the interface design is complete, you can export the project using SquareLine’s built-in export tool, which generates code and assets ready for integration with the Arduino IDE.
The export includes C header and source files fully compatible with ESP32-S3 Arduino IDE configuration.
To deploy:
- Add exported files to your Arduino project directory.
- Include the appropriate headers in your sketch.
- Compile and upload using sketch uploading routines.
Integrating with ESP32-S3 Hardware Features
With the exported GUI deployed, you can bind user interface elements to real-world data, such as readings from gyroscope integration or inputs via touch functionality.
The board’s dual-core processor and ample memory ensure responsive updates even when combining complex layouts with sensor-driven logic.
Further explore the LilGo T-display S3 esp32 development board or if you’re ready to start working with interactive projects, check out my microcontroller art projects to get started.

Conclusion
The Waveshare 1.69 inch display combined with ESP32-S3 support offers a robust platform for embedded system development, balancing performance, and a compact form factor.
Throughout this guide, I completed the full Arduino setup, implemented gyroscope integration, optimized ESP32-S3 power management, and initiated scalable GUI development using SquareLine Studio.
This board has proven to be a dependable solution for both rapid prototyping and production-ready applications.
With its support for sensor data reading, RTC configuration, and flexible interface options including I2C communication and touch functionality, I look forward to deepening my exploration of this platform across future interactive and media-driven projects.
Frequently Asked Questions (FAQ)
How do I set up the Waveshare ESP32-S3 1.69″ display with the Arduino IDE?
To set up the display, install the latest Arduino IDE and add the ESP32 board support via the Boards Manager using the URL:https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
Select “ESP32S3 Dev Module” as the board, and install necessary libraries like TFT_eSPI. Configure the User_Setup.h
file to match the display’s specifications.
Why isn’t the display turning on after uploading my sketch?
Ensure that the display’s backlight pin is correctly defined and set to HIGH in your code. Also, verify that the SPI pins are correctly configured and that the display driver (e.g., ST7789 or ST7789V2) is properly initialized.
How can I utilize the built-in gyroscope and accelerometer?
The board features a QMI8658 six-axis IMU. Use the appropriate library to interface with the sensor via I2C, allowing you to read accelerometer and gyroscope data for motion tracking and gesture recognition.
What is the function of the programmable power button?
The programmable power button supports single, double, and long-press actions. You can configure these presses to perform tasks like toggling the display, entering sleep mode, or resetting the device.
How do I implement low-power modes on this board?
Utilize the ESP32-S3’s deep sleep and light sleep modes to conserve power. Configure wake-up sources as needed, and manage peripheral power states to optimize energy consumption.
Can I develop a GUI for the display using SquareLine Studio?
Yes, SquareLine Studio allows you to design graphical interfaces and export them for use with the LVGL library on the ESP32-S3. This facilitates the creation of custom UIs for your projects.
How do I display images or animations on the screen?
Convert your images to a compatible format (e.g., BMP) and store them in the SPIFFS or on an SD card. Use appropriate libraries to read and render these images on the display.
What should I do if the touch functionality isn’t responding?
Ensure that the touch controller (e.g., CST816T) is correctly interfaced via I2C, and that the necessary libraries are included in your project. Verify the touch controller’s address and initialization code.
How can I monitor battery status and charging?
The board includes a battery management chip (e.g., ETA6098). Use ADC readings to monitor battery voltage and implement charging indicators in your code as needed.