I’m building an analog clock on an ESP32 Wrover Kit with a TFT LCD using the TFT_eSPI library. The clock displays the correct time using NTP, but I have a problem with the hands:
When the hands move, the old position remains visible (trails).
If I clear the whole screen and redraw the background and text every update, it works, but causes flicker and my static text disappears briefly.
Since my background is a colorful image, I cannot just erase the hands with a solid color.
Here is a simplified version of my code that reproduces the issue:
#include <TFT_eSPI.h>
#include <time.h>
#include <WiFi.h>
TFT_eSPI tft = TFT_eSPI();
#define CENTER_X 50
#define CENTER_Y 60
#define RADIUS 50
#define HOUR_LENGTH 10
#define MINUTE_LENGTH 20
const char* ssid = "Dina";
const char* password = "Dd78134003Segco";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 12600; // ایران +3:30
const int daylightOffset_sec = 0;
int lastMinute = -1;
// draw clock hand as triangle
void drawHandTriangle(int length, float angleRad, uint16_t color, int width) {
float cosA = cos(angleRad);
float sinA = sin(angleRad);
int xTip = CENTER_X + cosA * length;
int yTip = CENTER_Y + sinA * length;
int xLeft = CENTER_X + cos(angleRad + 1.57) * width;
int yLeft = CENTER_Y + sin(angleRad + 1.57) * width;
int xRight = CENTER_X + cos(angleRad - 1.57) * width;
int yRight = CENTER_Y + sin(angleRad - 1.57) * width;
tft.fillTriangle(xTip, yTip, xLeft, yLeft, xRight, yRight, color);
}
void drawClockFace() {
tft.fillScreen(TFT_BLACK);
for (int h = 0; h < 12; h++) {
float angle = (h * 30 - 90) * 0.0174533;
int x0 = CENTER_X + cos(angle) * (RADIUS - 3);
int y0 = CENTER_Y + sin(angle) * (RADIUS - 3);
int x1 = CENTER_X + cos(angle) * RADIUS;
int y1 = CENTER_Y + sin(angle) * RADIUS;
tft.drawLine(x0, y0, x1, y1, TFT_WHITE);
}
for (int h = 1; h <= 12; h++) {
float angle = (h * 30 - 90) * 0.0174533;
int x = CENTER_X + cos(angle) * (RADIUS - 15);
int y = CENTER_Y + sin(angle) * (RADIUS - 15);
tft.setTextColor(TFT_WHITE);
tft.setCursor(x - 5, y - 7);
tft.print(h);
}
}
void setup() {
Serial.begin(115200);
tft.init();
tft.setRotation(0);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
drawClockFace();
}
void loop() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
delay(1000);
return;
}
if (timeinfo.tm_min != lastMinute) {
drawClockFace(); // clears and redraws everything → causes flicker
lastMinute = timeinfo.tm_min;
float hourAngle = ((timeinfo.tm_hour % 12) + timeinfo.tm_min / 60.0) * 30 - 90;
float minuteAngle = timeinfo.tm_min * 6 - 90;
drawHandTriangle(HOUR_LENGTH, hourAngle * 0.0174533, TFT_WHITE, 2);
drawHandTriangle(MINUTE_LENGTH, minuteAngle * 0.0174533, TFT_WHITE, 1);
}
delay(1000);
}
Question: How can I update only the hands on top of a static background image and text, without leaving trails or causing flicker?