I selected the Adafruit ESP32-S3 w/ TFT display as part of an impact measurement test fixture. By pairing this with an accelerometer, I got a portable, compact module that shows immediate results including a mini plot of the impact profile without needing a laptop to capture and convert results.
This code shows how to properly initialize the TFT on this board and a combination of libraries to get suitable text and graphics. (This info was not easy to find.) As an aside, it also shows the method to compress RGB colors to RGB565; a format for this hardware and common to displays in embedded systems.
The Critical Power-Up Sequence
- TFT_I2C_POWER: Master gate. Drive HIGH to provide Vcc to the display.
- Delay: 10ms settling time for logic stability.
- TFT_BACKLITE: Master backlight enable. (note spelling of this lib constant.)
// -------------------------------------------------------------------------
// FILENAME: impact_logger_tft_init.ino
// VERSION: v1.0.5-FINAL
// DATE: 2025-DEC-26 06:25 AM PT
// -------------------------------------------------------------------------
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
#include "pins_arduino.h"
// Function converts 24-bit RGB values to compressed 16-bit (565) form for TFT.
// Explicit uint16_t casting prevents bit-bleeding on 32-bit processors.
constexpr uint16_t rgb565(uint8_t r, uint8_t g, uint8_t b) {
return ((uint16_t)(r & 0xF8) << 8) | ((uint16_t)(g & 0xFC) << 3) | (b >> 3);
}
// --- UI COLORS (Tuned for ST7789 Panel Saturation) ---
constexpr uint16_t CLR_BG = rgb565(0, 0, 0);
constexpr uint16_t CLR_LABEL = rgb565(120, 120, 120);
constexpr uint16_t CLR_VALUE = rgb565(255, 230, 0); // Clear Yellow
constexpr uint16_t CLR_PLOT = rgb565(255, 140, 0); // High-Vis Orange
constexpr uint16_t CLR_RISE = rgb565(0, 180, 180); // Vibrant Teal
constexpr uint16_t CLR_TAN = rgb565(210, 180, 140); // Instrumentation Tan
constexpr uint16_t CLR_FRAME = rgb565(100, 100, 100);
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
uint32_t status_counter = 0;
void initDisplay() {
pinMode(TFT_I2C_POWER, OUTPUT);
digitalWrite(TFT_I2C_POWER, HIGH);
delay(10);
pinMode(TFT_BACKLITE, OUTPUT);
digitalWrite(TFT_BACKLITE, HIGH);
tft.init(135, 240); // (width, height) ref: NATIVE portrait dimensions
tft.setRotation(3); // Landscape: USB port on the LEFT
tft.fillScreen(CLR_BG);
}
void drawStaticElements() {
tft.setTextSize(1);
tft.setTextColor(CLR_LABEL);
tft.setCursor(8, 28);
tft.print("Value 1");
tft.setCursor(8, 62);
tft.print("Value 2");
tft.setCursor(8, 96);
tft.print("Value 3");
tft.drawRect(95, 28, 138, 96, CLR_FRAME);
}
void updateStatus(uint32_t count) {
tft.setTextSize(2);
// Flicker-free refresh using overprint erasing (Text Color, Background Color)
tft.setTextColor(CLR_TAN, CLR_BG);
tft.setCursor(8, 2);
char buf[20];
sprintf(buf, "Status: %-5u", count);
tft.print(buf);
}
void drawSimpleWave() {
int x_start = 97;
int y_mid = 76;
int amp = 30; // 30px swing +/- from center
int step = 15;
for (int i = 0; i <= 110; i += (step * 4)) {
int x0 = x_start + i;
int x1 = x0 + step;
int x2 = x1 + step;
int x3 = x2 + step;
int x4 = x3 + step;
if (x1 < 232) tft.drawLine(x0, y_mid, x1, y_mid - amp, CLR_PLOT);
if (x2 < 232) tft.drawLine(x1, y_mid - amp, x2, y_mid, CLR_PLOT);
if (x3 < 232) tft.drawLine(x2, y_mid, x3, y_mid + amp, CLR_PLOT);
if (x4 < 232) tft.drawLine(x3, y_mid + amp, x4, y_mid, CLR_PLOT);
}
}
void setup() {
initDisplay();
drawStaticElements();
// Data output with 2px vertical spacing from labels
tft.setTextSize(2);
tft.setTextColor(CLR_VALUE, CLR_BG);
tft.setCursor(8, 40);
tft.print("14.8");
tft.setTextColor(CLR_PLOT, CLR_BG);
tft.setCursor(8, 74);
tft.print("18.2");
tft.setTextColor(CLR_RISE, CLR_BG);
tft.setCursor(8, 108);
tft.print("3.4");
drawSimpleWave();
}
void loop() {
updateStatus(status_counter++);
delay(800);
}
/// EOF
Note: This board is available from adafruit.com with the display on the top (PID 5483) or the bottom (PID 5493) to accommodate different packaging needs.









