ESP32-S3 smartwatch
Firmware and an Android companion for the Waveshare ESP32-S3 Touch AMOLED 2.06.
The current executable is a C++ foreground-app runtime with live motion/power data,
full-screen touch-symbol collection, and eight-channel ADS1256 EMG collection. The
Android companion contains the phone-side BLE media bridge; its matching firmware
GATT service remains roadmap work.
Read [the audit](docs/AUDIT.md) before reviving any unbuilt legacy source. The
[architecture](docs/ARCHITECTURE.md), [dataset contracts](docs/DATASETS.md), and
[roadmap](ROADMAP.md) describe the end-to-end design.
Build
The helper discovers an ESP-IDF 5.5.3 installation managed by Espressif EIM. An
explicit `SMARTWATCH_IDF_PATH` environment variable can override discovery.
.\scripts\build.ps1
The verified local environment uses:
- ESP-IDF 5.5.3
- LVGL 9.3.0 and Waveshare BSP 2.0.0 through the component lock
- Microsoft OpenJDK 21
- Android SDK platform/build tools 35 and platform-tools
- Gitleaks 8.30.1 for redacted working-tree and history scans
Build the Android companion with:
cd companion-android
.\gradlew.bat assembleDebug
Do not flash until a board is detected and its existing flash is backed up. The
scripts support explicit ports:
.\scripts\backup-flash.ps1 -Port COM7
.\scripts\flash.ps1 -Port COM7 -Monitor
Data collection
Copy the protocol examples under `sdcard_staging/datasets` to the SD card if custom
labels or EMG phase durations are wanted. Missing files use built-in defaults.
Touch samples are full-resolution 410×502 grayscale BMPs with stroke time encoded as
intensity. EMG sessions are labeled CSV plus JSON metadata at 500 eight-channel
frames per second. Dataset files are written atomically where possible and incomplete
EMG sessions retain a `.part` suffix.
EMG acquisition is disabled by default. It can be enabled in `idf.py menuconfig`
only after the conditioned patient-isolated analog front end and removal/isolation of
the GPIO18 motor circuit are physically verified.
Relevant pins
- Shared SPI3: `MOSI=GPIO1`, `SCLK=GPIO2`, `MISO=GPIO3`
- microSD: `CS=GPIO17`
- ADS1256: `CS=GPIO18`, `DRDY=GPIO44`
- BOOT: `GPIO0`
- Board I2C: `SDA=GPIO15`, `SCL=GPIO14`
- Native USB: `D-=GPIO19`, `D+=GPIO20`
GPIO18 is tied to the board motor circuit and GPIO44 is commonly UART0 RX in vendor
examples. Those electrical conflicts must be resolved on the actual hardware before
ADS1256 testing.
Secrets
Local overrides, build output, APKs, device backups, and credentials are ignored.
A previously present OpenRouter key value was removed from the workspace, but it
must be revoked at the provider because deleting it locally does not invalidate it.
Current validation status
- Firmware clean build: passing
- Safety-gated EMG compile build: passing (`scripts/build-emg-compile.ps1`)
- Dataset validator unit tests: 4 passing
- Android debug APK build: passing
- Physical watch/SD/ADS1256 tests: pending; no board is connected
- Git history reconciliation: complete; obsolete parallel runtime files were removed