A three-mode smartwatch UI β digital, analog, and tilt-level β backed by the PCF85063 RTC, QMI8658 IMU raise-to-wake, and tap-to-cycle touch.
The PCF85063 RTC keeps accurate time across power cycles. On first boot (or if the oscillator-stopped flag is set), the sketch seeds the RTC from the compile-time __DATE__ / __TIME__ macros.
Tap the screen to cycle through three faces: Digital (large HH:MM, seconds bar, date), Analog (swept hands with gold bezel and tick marks), and Info (time + live pitch/roll level bars). Tilting the board upward triggers raise-to-wake; the display sleeps after 10 s of inactivity.
| Face | Index | Key elements |
|---|---|---|
| Digital | 0 | HH:MM at size-6, seconds in gold at size-3, animated seconds progress bar, day + date + month string. |
| Analog | 1 | 60-tick bezel with gold double-ring, 12 hour numerals, thick hour/minute hands, red second hand with tail, date window at 6 o'clock position. |
| Info / Level | 2 | Compact time at top, two horizontal progress bars showing live roll and pitch angles. Bar turns green within Β±3Β°, orange beyond. |
| Input | Behaviour |
|---|---|
| Tap (CST816T gesture 0x01) | Cycles faceIdx 0β1β2β0, wakes display, resets 10 s sleep timer. |
| Raise-to-wake (IMU) | Detects rising-edge on Z-axis acceleration crossing 0.4β0.7 g (wrist lift). Wakes display, resets timer. |
| Inactivity timeout | After 10 000 ms with no touch or raise event, backlight is pulled LOW (display off). |
0x00 Control_1 β STOP/START bit
0x04 Seconds (7 bytes, BCD)
0x04 Seconds β OS flag (bit 7)
β non-zero means clock lost power
if (OS flag set) {
stop RTC (0x00 = 0x20)
write __DATE__ / __TIME__
start RTC (0x00 = 0x00)
}
Only runs once after a cold start or battery loss β subsequent boots preserve stored time.
The QMI8658 accelerometer is read every loop (~50 ms). A simple edge detector watches the Z-axis value (gravity component) cross from below 0.4 g to above 0.7 g β the signature of a wrist-lift. A low-pass filter (az = azΓ0.8 + prevΓ0.2) smooths the signal before the threshold check.
For the Info face, pitch and roll are derived from all three accelerometer axes:
pitch = atan2(ay, sqrt(axΒ² + azΒ²)) Γ 180/Ο roll = atan2(βax, az) Γ 180/Ο
All drawing targets an Arduino_Canvas (off-screen framebuffer in PSRAM). Each face calls canvas->flush() once at the end to push the full frame via SPI DMA β eliminating tearing artifacts.
Arduino_Canvas *canvas = new Arduino_Canvas(240, 280, gfx);
PSRAM-backed; the 240Γ280Γ2 byte buffer (~131 KB) fits comfortably in the 8 MB OPI PSRAM.
for d in [-thick/2 .. thick/2]: offset perp to line by d px drawLine(offset copy)
Renders bold clock hands without hardware stroke-width support.
Full sketch in the ESP32-S3-LCD repo β sketches/watch_face/watch_face.ino.
git clone https://github.com/binRick/ESP32-S3-LCD bash flash-sketch-003-watch-face.sh