# Sylvia Touch Relay BLE-gestuurde relais-switch voor de M5Stack Atom VoiceS3R (ESP32-S3) met een bijbehorende Android-app. Het relais kan worden bediend via een capacitieve touch-sensor (open-drain) óf via Bluetooth Low Energy vanaf een Android-telefoon. ## Hardware | Component | Details | |---|---| | Board | M5Stack Atom VoiceS3R (SKU: C126-ECHO) | | SoC | ESP32-S3-PICO-1-N8R8 (8MB Flash, 8MB PSRAM) | | Touch sensor | Open-drain sensor op **G38** (3.3V, interne pullup) | | Relais / LED | Op **G1** (3.3V GPIO output) | | Status LED | Op **G46** (knippert 3x bij opstarten) | ### Pinout (Atom VoiceS3R onderste header) ``` G38 G39 3.3V GND 5V G5 G6 G7 G8 ``` - **G38** — Touch sensor input (active LOW, interne pullup ingeschakeld) - **G1** — Relais output (HIGH = aan, LOW = uit) - **G46** — Status LED (3x knipperen bij opstarten, daarna uit) ### Aansluiting ``` Sensor GND → GND Sensor OUT → G38 Sensor VCC → 3.3V Relais + → G1 Relais - → GND ``` > **Let op:** De ESP32-S3 interne pullup is ~45kΩ. Bij lange draden of elektrische ruis een externe 4.7kΩ–10kΩ pullup naar 3.3V plaatsen. ## Firmware De firmware is geschreven in C++ met behulp van PlatformIO en de Arduino-framework. BLE wordt verzorgd door de ESP32 BLE library. ### Logica Het relais gaat aan als **één van beide** bronnen actief is: | Bron | Voorwaarde | Resultaat | |---|---|---| | Touch sensor | G38 = LOW (aanraken) | Relais aan | | BLE command | App stuurt `0x01` | Relais aan | | Geen van beide | G38 = HIGH + geen BLE command | Relais uit | De touch sensor en BLE werken onafhankelijk. Als de sensor losgelaten wordt én de BLE-knop niet ingedrukt is, gaat het relais uit. ### BLE GATT | Eigenschap | UUID | |---|---| | Service | `4fafc201-1fb5-459e-8fcc-c5c9c331914b` | | Characteristic | `beb5483e-36e1-4688-b7f5-ea07361f26d8` | De characteristic ondersteunt `WRITE` en `NOTIFY`. Schrijf `0x01` om het relais aan te zetten, `0x00` om uit te zetten. ### Serial monitor Baudrate: **115200** (USB CDC). De firmware stuurt heartbeat-statussen elke 5 seconden en logt statuswijzigingen: ``` === Atom VoiceS3R BLE Relay === LED blink done, starting BLE... BLE: advertising started as 'AtomS3R-Relay' Setup done. [heartbeat] relay=OFF touch=no ble=disconnected BLE: device connected Relay ON (touch=YES, ble=connected) Relay OFF (touch=no, ble=connected) ``` ### Uploaden > **Download-mode:** Houd de reset-knop ~2 seconden ingedrukt tot de groene LED aangaat, laat dan los. Het board is nu in download-mode. ```bash pio run --target upload ``` Na het uploaden treedt er een harde reset op. Als het board in download-mode blijft, USB eruit/erin of kort op reset tikken om in run-mode te komen. ## Android App ### Features - **Auto-connect:** De app scant automatisch bij opstarten naar het BLE-apparaat "AtomS3R-Relay" - **Auto-reconnect:** Bij wegvallen van de verbinding wordt na 2 seconden opnieuw gescant - **Hold-to-activate:** Houd de knop ingedrukt voor relais aan, loslaten voor relais uit (zelfde gedrag als de sensor) - **Permissies:** Vraagt BLUETOOTH_SCAN, BLUETOOTH_CONNECT en ACCESS_FINE_LOCATION aan (Android 12+) ### Bouwen Vereisten: - Android SDK (API 34+) - Java 21 - Gradle 8.5 ```bash cd android JAVA_HOME=/pad/naar/jdk21 ./gradlew assembleDebug ``` De APK staat na build in `android/app/build/outputs/apk/debug/app-debug.apk`. ### Installeren ```bash adb install -r android/app/build/outputs/apk/debug/app-debug.apk ``` Of via draadloze foutopsporing: ```bash adb connect : adb install -r android/app/build/outputs/apk/debug/app-debug.apk ``` ### UUID's De app gebruikt dezelfde UUID's als de firmware: ```kotlin private val SERVICE_UUID: UUID = UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b") private val CHARACTERISTIC_UUID: UUID = UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361f26d8") ``` ## Projectstructuur ``` sylvia-touch-relay/ ├── platformio.ini # PlatformIO configuratie (ESP32-S3) ├── src/ │ └── main.cpp # Firmware (BLE + sensor + relais) ├── android/ │ ├── build.gradle # Root Gradle config │ ├── settings.gradle │ ├── gradle.properties │ ├── gradlew # Gradle wrapper │ ├── gradle/wrapper/ │ │ └── gradle-wrapper.properties │ └── app/ │ ├── build.gradle # App module config │ └── src/main/ │ ├── AndroidManifest.xml │ ├── java/com/eddy/atomrelay/ │ │ └── MainActivity.kt │ └── res/ │ ├── layout/activity_main.xml │ └── values/strings.xml ├── .gitignore └── README.md ``` ## Technische notities - De Atom VoiceS3R gebruikt de ES8311 audio codec op G45/G0/G48/G4/G3/G17/G11, IR TX op G47, en de knop op G41. Deze pinnen zijn niet beschikbaar voor eigen gebruik. - G1 en G2 zitten op de HY2.0-4P Grove poort. G5-G8, G38, G39 zitten op de onderste expantie-header. - De firmware gebruikt geen M5Unified library — alleen Arduino core + ESP32 BLE. Dit maakt de serial output betrouwbaarder via USB CDC. - `ARDUINO_USB_CDC_ON_BOOT=1` is ingeschakeld voor virtuele serial via USB.