# Firmware del ESP32 Firmware para el bot físico DummyBot. ESP32 + OLED SSD1306 128x64 + WiFi + polling backend. ## Hardware - **ESP32-D0WD-V3** (DevKitC / WROOM-32, 4 MB flash) - **Pantalla OLED SSD1306 0.96"** (128x64, I2C) - **3 botones** (NEXT / DONE / SNOOZE) - **1 motor vibrador 1027** (3V DC, MOSFET en GPIO 25) ### Pinout | Función | GPIO | Notas | |------------------|-------|--------------------------------------| | OLED SDA | 21 | I2C data | | OLED SCL | 22 | I2C clock | | OLED addr | 0x3C | I2C address | | Botón NEXT | 26 | INPUT_PULLDOWN, flanco ascendente | | Botón DONE | 27 | INPUT_PULLDOWN, flanco ascendente | | Botón SNOOZE | 14 | INPUT_PULLDOWN, flanco ascendente | | Vibrador | 25 | OUTPUT, MOSFET gate | | BOOT (reset cfg) | 0 | INPUT_PULLUP, mantener 5s al arrancar | ### Cableado OLED ``` ESP32 (WROOM-32) OLED SSD1306 0.96" ───────────────────── ───────────────────── 3V3 ───────▶ VDD GND ───────▶ GND GPIO 22 ───────▶ SCK (I2C SCL) GPIO 21 ───────▶ SDA (I2C SDA) ``` ### Cableado botones Los botones se conectan entre GND y el GPIO correspondiente. Con `INPUT_PULLDOWN` interno del ESP32, el GPIO lee LOW en reposo y HIGH al pulsar. El firmware detecta el flanco ascendente con debounce de 200 ms. ``` ESP32 Botón (entre pin y GND) ───── ───── GPIO 26 ──────▶ Siguiente GPIO 27 ──────▶ Hecha GPIO 14 ──────▶ Snooze 5 min GND ──────▶ Común ``` ### Cableado vibrador ``` ESP32 MOSFET (AO3400 / 2N7000) Vibrador 1027 ───── ────── ───── GPIO 25 ──[100Ω]──▶ Gate │ ├──▶ Source ──▶ GND │ └──▶ Drain ──▶ Vibrador ──▶ 3V3 ``` Si solo se dispone de NPN (BC547 / 2N2222 / S8050), esquema alternativo: motor entre 3V3 y colector, resistencia 1kΩ en base. ## Build flags (platformio.ini) ```ini build_flags = -DCORE_DEBUG_LEVEL=3 -DUSER_SETUP_LOADED=1 -DDEFAULT_WIFI_SSID=\"PHARMACO\" -DDEFAULT_WIFI_PASS=\"arnoldgym2010\" -DBACKEND_URL=\"http://157.180.77.232:18080\" -DDEFAULT_DEVICE_TOKEN=\"\" ``` ## Build y flasheo ```bash # Compilar pio run # Flashear pio run -t upload --upload-port /dev/ttyUSB0 # Monitor serie pio device monitor --port /dev/ttyUSB0 --baud 115200 ``` ## Configuración en runtime (captive portal) Si no hay config WiFi válida en NVS, el bot abre un AP `DummyBot-Setup` (pass `dummybot`) en `192.168.4.1`. Desde el móvil, configurar WiFi y token del dispositivo. El bot se reinicia automáticamente y conecta. Para resetear la config: mantener pulsado el botón **BOOT (GPIO 0)** durante 5 segundos al arrancar. ## Comandos serie (debug) Conectar a `115200 baud`: | Comando | Acción | |---------|-------------------------------------------------| | `S` | Imprime estado (WiFi, IP, tarea actual) | | `B0` | Simula pulsación botón NEXT (GPIO 26) | | `B1` | Simula pulsación botón DONE (GPIO 27) | | `B2` | Simula pulsación botón SNOOZE (GPIO 14) | | `P` | Lee estado actual de los 3 pines de botón | | `A` | Lectura continua del ADC en GPIO 34 (60s) | | `C` | Calibración guiada de umbrales ADC (3 botones) | | `W` | Watch: monitor rápido de cambios en pines | ## Arquitectura del firmware ```cpp // Namespace principales namespace Config { void load(); void save(); void clear(); } namespace UI { showBoot, showConnecting, showIdle, showTask, showPortal } namespace Vib { buzz(), tick() — patrón 2-buzz al recibir tarea nueva } namespace Api { pollPending(), markDone(), snooze() } namespace Input { tick() — polling 3 botones con debounce por flanco } namespace Portal { start(), stop(), tick() — AP + DNS + WebServer } namespace Wifi { wifiStartSTA(), wifiTick() — máquina de estados } ``` ### Máquina de estados WiFi ``` BOOT → CONNECTING (timeout 20s) ├─ OK → CONNECTED (poll cada 30s) └─ FAIL → PORTAL (AP DummyBot-Setup) CONNECTED └─ WiFi perdido → CONNECTING PORTAL └─ ESP.restart() al guardar config ``` ### Flujo de polling ``` CONNECTED → Api::pollPending() cada 30s → GET /api/device/tasks/pending → Si tiene tareas: muestra primera en OLED → Si cambia id: buzz (vibrador) ``` ## Troubleshooting ### WiFi no conecta - Verificar SSID y password (son case-sensitive). - Si el router está en 5 GHz, el ESP32 solo soporta 2.4 GHz. - Si la red bloquea nuevos dispositivos (MAC filtering), añadir la MAC del ESP32 (visible en el log de `WiFi.status()`). ### Botones no responden - Verificar que el botón hace contacto entre el GPIO y GND. - Comandos serie `P` muestra el estado actual de los pines. Pulsar y ver si cambia de 0 a 1. - Si el botón usa active-low (HIGH en reposo, LOW al pulsar), cambiar a `INPUT_PULLUP` y la lógica de flanco a descendente. ### OLED no enciende - Verificar 3V3 en VDD del OLED. - Verificar SDA (GPIO 21) y SCL (GPIO 22) — pines fijos I2C del ESP32. - I2C addr por defecto 0x3C. Si la OLED es 0x3D, cambiar `OLED_ADDR`. ### API no responde - Verificar que el bot tiene acceso a internet (ping al backend desde el ESP32 con el comando serie `S`). - Si el backend usa HTTPS con cert auto-firmado, hay que añadir el cert al firmware (más complejo) o usar HTTP plano. ## Versiones - **v6.1** (actual): producción, sin botones (pendiente nueva placa). Funcionalidad core: WiFi, OLED, polling, portal cautivo. - **v6.0** (legacy): intentona con ADC para matriz de botones, no funcionó en hardware del usuario. - **v5** (legacy): SPIFFS en lugar de NVS, varios bugs en defaults WiFi.