Skip to content

ViiFii/M5Paper-Color-Reloj-Clima

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

M5Paper Color — Estación multimodo

Plataforma Framework Pantalla Estado

Firmware para el M5Paper Color (ESP32-S3, tinta electrónica a color) que reúne varias utilidades en un dispositivo de bajo consumo: estación meteorológica con predicción de AEMET, marco de fotos, reproductor de música y lector de libros de texto. Incluye un modo oculto TV-B-Gone por infrarrojos. Todo se configura desde la microSD.


✨ Características

  • 🌦️ Clima — temperatura/humedad interior (SHT40) + predicción AEMET de varias localidades (hoy destacado: icono a color, máx/mín, viento + racha, índice UV, previsión por horas, lluvia y humedad + 3 días) + observación en tiempo real de una estación AEMET. La última predicción se guarda en la SD y se ve al instante al encender, aunque no haya WiFi. Vista LOCAL con fecha, reloj grande y batería.
  • 🖼️ Carrusel de fotos — imágenes de la microSD a pantalla completa, con auto-rotación del panel según la orientación de cada foto.
  • 🎵 Música — reproductor desde la SD (MP3 / M4A / FLAC / WAV / AAC) con el códec ES8311. Títulos con acentos correctos (fuente propia).
  • 📖 Libro — lector de TXT desde /Libros con selector de archivos y memoria de página por libro (otros formatos: mejor descargarlos desde el gestor web).
  • 📶 WiFigestor web de la microSD con login: se une a tu red (muestra la IP) o crea su AP propio con QR. Navegar (lista/detalles/miniaturas), subir, editar, borrar, descargar carpeta en ZIP, ver fotos (proporción real, swipe), vídeo ligero, mini‑reproductor de música, abrir PDF (visor del navegador) y EPUB (lector integrado), y abrir en el navegador cualquier formato que sepa mostrar (SVG, HTML…). Tema claro/oscuro y editor de config.json por formulario.
  • ⚙️ Modos configurables — activa/desactiva cualquier modo desde config.json; los desactivados se saltan.
  • 📺 TV-B-Gone (modo oculto) — apaga televisores por IR (108 códigos europeos).
  • 🕒 Hora por NTP mantenida en el RTC, con horario de verano automático.

🎛️ Controles

Tres botones de usuario (el cuarto es el de encendido):

Botón Gesto Acción
G1 (GPIO1) 1 click Cambiar de modo (Clima → Carrusel → Música → Libro → WiFi; salta los desactivados)
G1 Doble click 📺 TV-B-Gone (modo oculto: apaga la TV)
G1 Mantener (~0,8 s) Acción del modo · Clima: actualizar por WiFi (NTP + AEMET)
UP (GPIO9) / DOWN (GPIO10) Navegación del modo (ver abajo)

Navegación UP/DOWN por modo:

Modo UP / DOWN Doble click UP/DOWN Mantener UP/DOWN
Clima Vista anterior/siguiente
Carrusel Foto anterior/siguiente
Música Volumen −/+ Canción ant/sig Play / Pausa
Libro (lista) Mover selección Abrir libro
Libro (leyendo) Página ant/sig Volver a la lista (mantener G1)
WiFi Encender / apagar el AP — (gestión desde el navegador)

El modo activo se guarda en NVS y se restaura al reiniciar. En Libro, cada archivo recuerda su última página.


💾 La microSD

Formatea en FAT32 y crea esta estructura en la raíz:

/config.json        ← configuración
/Fotos/             ← imágenes del carrusel  (.jpg .jpeg .png .bmp)
/Musica/            ← canciones  (.mp3 .m4a .flac .wav .aac)
/Libros/            ← libros (.txt en UTF-8; PDF/EPUB se leen desde el gestor web)
/fonts/title.vlw    ← fuente con acentos para los títulos
/fonts/body.vlw     ← fuente con acentos para el lector de libros
/lib/               ← (opcional) lector EPUB para la web: jszip.min.js + epub.min.js

📖 Para leer EPUB en el gestor web, copia la carpeta tools/sdcard/lib (trae jszip.min.js y epub.min.js) a la raíz de la SD como /lib/. Así el lector funciona también en modo AP, sin internet. Los PDF no necesitan nada (los abre el propio navegador).

config.json

{
  "wifi": [
    { "ssid": "TU_RED_WIFI", "pass": "TU_CONTRASENA" },
    { "ssid": "OTRA_RED",    "pass": "OTRA_CONTRASENA" }
  ],

  "aemet_api_key": "PEGA_AQUI_TU_TOKEN_AEMET",
  "timezone": "CET-1CEST,M3.5.0,M10.5.0/3",

  "carousel_seconds": 300,
  "photo_auto_rotate": true,
  "deep_sleep_minutes": 60,
  "modos": { "clima": true, "carrusel": true, "musica": true, "libro": true, "wifi": true },
  "wifi_modo": { "ap_ssid": "PaperColor", "ap_pass": "papercolor1234", "user": "admin", "pass": "admin" },

  "fotos_dir": "/Fotos",
  "musica_dir": "/Musica",
  "libros_dir": "/Libros",
  "font_title": "/fonts/title.vlw",
  "font_body": "/fonts/body.vlw",

  "locations": [
    { "name": "Madrid",           "municipio": "28079", "estacion": "3126Y" },
    { "name": "San Ildefonso",    "municipio": "40181", "estacion": "" },
    { "name": "Posada de Llanes", "municipio": "33036", "estacion": "" }
  ]
}
Campo Descripción
wifi Lista de redes; se prueban en orden hasta conectar.
aemet_api_key Token gratuito de AEMET OpenData.
timezone POSIX TZ. Peninsular: CET-1CEST,M3.5.0,M10.5.0/3 · Canarias: WET0WEST,M3.5.0/1,M10.5.0.
carousel_seconds Segundos entre fotos.
photo_auto_rotate true = gira el panel según la orientación de cada foto.
deep_sleep_minutes Minutos de inactividad antes de apagarse (deep sleep por PMIC). Se enciende con el botón de encendido.
modos Activa/desactiva cada modo (clima/carrusel/musica/libro/wifi). Un modo en false no se ejecuta y G1 lo salta. Si los pones todos en false, se reactivan todos (a prueba de bloqueos).
wifi_modo Modo WiFi (gestor de la SD): ap_ssid/ap_pass del punto de acceso propio (ap_pass mín. 8 caracteres) y user/pass del login web.
fotos_dir/musica_dir/libros_dir Carpetas en la SD.
font_title Fuente VLW (con acentos) para los títulos.
font_body Fuente VLW (con acentos) para el lector de libros.
locations Localidades del clima: municipio = código INE (predicción); estacion = idema de observación AEMET (opcional, "" = solo predicción).

🔒 Las credenciales reales viven solo en la microSD, nunca en el repositorio.


🌦️ Clima y AEMET

Usa la API gratuita de AEMET OpenData:

  1. Solicita tu clave en el alta de usuario (llega por email) y ponla en aemet_api_key.
  2. Añade tus localidades por código de municipio INE (la predicción es por municipio).
  3. Opcionalmente, una estación de observación (estacion) para ver el dato actual real.

Mantén G1 pulsado en el modo Clima para actualizar por WiFi (resincroniza la hora + descarga AEMET).

📡 Estaciones AEMET (cómo encontrar tu estacion / idema)

El idema es el código de la estación de observación. Para encontrar el tuyo:

  • Método web (el más rápido): entra en aemet.es → El tiempo → Observación → Últimos datos, elige tu estación y mira la URL: contiene ?l=XXXXX. Eso es el idema. Ej.: Madrid, El Goloso...ultimosdatos?l=3126Y → idema 3126Y.
  • Lista completa (todas las estaciones): ejecuta el script incluido con tu clave:
    python tools/aemet_estaciones.py TU_API_KEY estaciones.csv
    
    Genera un CSV con idema, nombre, provincia, altitud de todas las estaciones.

Ejemplos habituales (verifica el tuyo con el método de arriba — los sufijos pueden variar):

Lugar idema Lugar idema
Madrid, El Goloso 3126Y Bilbao Aeropuerto 1082
Madrid, Retiro 3195 Zaragoza Aeropuerto 9434
Madrid-Barajas Aerop. 3129 Málaga Aeropuerto 6155A
Barcelona Aeropuerto 0076 Murcia 7178I
Valencia (Viveros) 8416 Alicante (Ciudad Jardín) 8025
Sevilla Aeropuerto 5783 Santander Aeropuerto 1109
A Coruña 1387E Palma Aeropuerto B954
Granada Aeropuerto 5530E Gran Canaria Aeropuerto C649I

⚠️ AEMET puede cambiar/retirar estaciones. Si una no devuelve datos, confirma el idema con el método web o el script.


🎵 Música y acentos (fuente VLW)

Las fuentes integradas de M5GFX son solo ASCII (los acentos salen mal) y M5GFX no rasteriza TTF. La solución es una fuente VLW (bitmap, generada de un TTF) que se carga desde la SD:

python tools/make_vlw.py "C:\Windows\Fonts\verdanab.ttf" 44 fonts/title.vlw
python tools/make_vlw.py "C:\Windows\Fonts\verdana.ttf"  18 fonts/body.vlw

Copia los .vlw resultantes a la microSD (/fonts/). Si no existen, se usa una fuente integrada (sin acentos). El .vlw no se versiona (puede derivar de una fuente propietaria).

📖 Lector de libros: el alto de línea se ajusta automáticamente al tamaño de body.vlw. Generándolo a 18 px (en vez de 22) entran más líneas por página sin tocar el código.


📺 Modo oculto TV-B-Gone

Doble click en G1 emite una tanda de 108 códigos de apagado de TVs europeas (NEC, Samsung, Sony, RC5/RC6, Panasonic, JVC…) por el emisor IR (GPIO48). No usa la pantalla: el LED RGB parpadea verde al empezar y rojo al terminar (3 veces si se cancela con G1). Apunta a la TV.

Los códigos están en M5PaperColor_Reloj/tvbgone_codes.h (portados de m5stick-weather-tvbgone).


🔋 Arranque y ahorro de energía

Arranque rápido. Al encender, el reloj se muestra enseguida (hora del RTC + sensor, sin esperar a la red). La descarga de WiFi + NTP + AEMET se hace en segundo plano tras pintar la pantalla: no bloquea el arranque ni muestra mensajes de "Sin WiFi". La hora local se corrige sola en el siguiente refresco (1/5 min) y las predicciones AEMET aparecen al navegar a una localidad.

Reposo (light sleep). En inactividad el equipo entra en light sleep y despierta solo con un botón o cuando toca el siguiente refresco. Transparente para el usuario.

Apagado por inactividad (deep sleep). Tras deep_sleep_minutes sin tocar ningún botón, el equipo se apaga de verdad mediante el PMIC (M5.Power.powerOff()): consumo mínimo y sin despertares fantasma. La tinta electrónica conserva la última imagen aunque esté apagado. Para volver a encenderlo, pulsa el botón de ENCENDIDO (arranca de cero). Mientras se reproduce música, no se duerme.

💡 Los tres botones de usuario (G1/UP/DOWN) son GPIO del ESP32 y su alimentación de pull-up se corta al dormir, así que no pueden despertar de un apagado real; por eso el despertar fiable es el botón de encendido, que cuelga directamente del PMIC.


📶 Modo WiFi (gestor de la microSD)

El modo entra apagado. Pulsa ARRIBA para activarlo; ABAJO lo apaga; G1 sale del modo. Al activarlo decide solo cómo conectarse:

  • Se une a tu WiFi si alguna de las redes de wifi[] está disponible → la pantalla muestra la red, la IP asignada (http://<IP>) y un QR con esa URL. Tu móvil/PC, en la misma red, abre esa dirección. Además, al estar conectado a internet, aprovecha para refrescar la hora (NTP) y toda la predicción AEMET.
  • Si no hay/conecta ninguna, crea su propio punto de acceso (estilo nomad, sin router) → muestra SSID, contraseña, http://192.168.4.1 y un QR para unirse a la red directamente.

En ambos casos abres la web, introduces usuario/clave del login y puedes navegar, descargar, subir, editar (texto) o borrar. Cada elemento tiene un menú (Ver/Editar/Reproducir, Descargar, Borrar) y hay un botón ⬅ .. atrás. La carpeta se puede ver en lista / detalles / miniaturas (☰ ≣ ▦, se recuerda).

Fotos, vídeo y música.

  • Fotos: en miniaturas o al abrir una, se ven con su proporción real; pasas a la anterior/siguiente con swipe (móvil), flechas ‹ › o teclado (←/→, Esc). La vista de miniaturas usa las miniaturas de .thumbnails/ si las generas con tools/make_thumbs.py (carga mucho más rápida; los vídeos muestran un fotograma). Si no hay, cae a la imagen original.
  • Vídeo: reproducción en el navegador con Range (HTTP 206) → permite avanzar (necesario en iOS).
  • Música: mini‑reproductor en una barra inferior que sigue sonando mientras navegas.
  • Documentos: los PDF se abren en pestaña con el visor nativo del navegador; los EPUB con un lector integrado a pantalla completa (pasa página con flechas, botones o swipe; necesita /lib/ en la SD, ver arriba). Otros formatos que el navegador sepa dibujar (SVG, HTML…) también se abren en el navegador; el resto se descargan.

Miniaturas y carga. Las miniaturas e imágenes se sirven con caché del navegador (7 días): al reentrar a una carpeta (aunque tenga cientos/miles de fotos) ya no se piden al equipo, así que es instantáneo. La primera vez, las miniaturas se cargan bajo demanda según haces scroll. Como el servidor web es de un solo hilo, si cortas una descarga grande a la mitad puede tardar un par de segundos en quedar libre. (Si regeneras las miniaturas, fuerza recarga con Ctrl/⌘+F5.)

Descargar carpeta. El botón ⬇ Carpeta (ZIP) (o el menú ⋯ de una carpeta) descarga toda la carpeta en un ZIP (sin compresión, en streaming; incluye subcarpetas).

Hay un selector de tema claro/oscuro (🌙/☀️) que recuerda tu preferencia.

🎬 Vídeo: lo decodifica el navegador del móvil; el equipo solo sirve los bytes. Como la microSD va por SPI (no SDIO), el caudal es limitado: va bien con clips ligeros (MP4 H.264/AAC, ~480p), no con HD.

El botón Configuración abre un formulario gráfico (redes WiFi, AEMET y localidades, modos activos, carpetas/fuentes, ajustes del propio modo WiFi…) que lee y reescribe config.json; también hay un botón { } JSON para el crudo. Reinicia el equipo para aplicar los cambios.

Con la conexión activa no entra en reposo. El AP/STA y la web se configuran en wifi_modo del config.json (la contraseña del AP debe tener ≥ 8 caracteres).

🔒 Todo el gestor —incluida la configuración— está detrás del login, así que las credenciales del config.json (WiFi de casa, clave AEMET) no quedan expuestas a quien solo esté en la red.


🧩 Hardware (verificado contra el esquemático C151 V0.5)

Componente Detalle
SoC ESP32-S3R8 · 16 MB flash · 8 MB PSRAM
Pantalla e-paper Spectra 6 color, 400 × 600
Sensor T/H SHT40 (I²C 0x44)
RTC RX8130CE (0x32)
PMIC M5PM1 (0x6E)
Audio códec ES8311 (0x18) + ADC ES7210 + ampli AW8737A
Otros microSD, IR (GPIO48), 2× LED RGB (GPIO21), batería 1250 mAh

Mapa de pines

Función GPIO
I²C interno (SHT40/RTC/PMIC/ES8311) SDA = 3, SCL = 2
SPI (e-paper + microSD) MOSI=13, MISO=14, SCK=15
e-paper CS=44, DC=43 · microSD CS=47
Botones G1=1, UP=9, DOWN=10
Audio I²S (ES8311) BCLK=40, LRCK=41, DATA=38 · codec_en=45, spk_en=46
IR / LED RGB IR=48 · LED=21

La microSD, el e-paper y el códec se alimentan del rail L3B del PMIC; el firmware habilita el LDO al arrancar.

⚙️ Velocidad de la microSD (SPI a 40 MHz)

La microSD va por SPI (no SDIO) compartiendo bus con el e-paper. El firmware la monta a 40 MHz (≈2× de caudal frente a 20 MHz: ayuda a la música, al vídeo y al gestor web) y, si fallara el montaje, repliega solo a 20 MHz. Si usaras una tarjeta o un cableado que a 40 MHz dé lecturas corruptas o errores intermitentes, baja la constante:

// M5PaperColor_Reloj.ino, función initSD()
const uint32_t SD_FREQ_HZ = 40000000;   // ← ponlo en 20000000 si tu tarjeta no es estable a 40 MHz

El caudal real sigue limitado por SPI: aun a 40 MHz, el vídeo va bien con clips ligeros (no HD).


🛠️ Compilación (Arduino IDE)

Placa: ESP32S3 Dev Module · Flash 16 MB · PSRAM OPI PSRAM · USB CDC On Boot Enabled

Abre M5PaperColor_Reloj/M5PaperColor_Reloj.ino, selecciona la placa y sube.

Versiones probadas (junio 2026)

⚠️ La placa es muy nueva y las librerías se actualizan a menudo estos primeros meses. Estas son las versiones con las que compila y funciona. Si una actualización rompe algo, vuelve a estas (o usa PlatformIO, que las fija automáticamente — ver abajo).

Componente Versión
Core M5Stack/ESP32 (Arduino) 3.3.7
M5Unified 0.2.17
M5GFX 0.2.22
M5Unit-ENV 1.4.0
M5PM1 1.0.7
ArduinoJson 7.4.3
ESP32-audioI2S (schreibfaul1) 3.4.6
IRremoteESP8266 2.9.0

Enlaces: M5Unified · M5GFX · M5Unit-ENV · M5PM1 · ArduinoJson · ESP32-audioI2S · IRremoteESP8266

Compilar con PlatformIO (versiones fijadas)

Para una compilación reproducible (sin pelear con el gestor de librerías) hay un platformio.ini con la plataforma y todas las librerías fijadas a las versiones de arriba. Usa el fork pioarduino (la plataforma oficial de PlatformIO aún no soporta arduino-esp32 3.x):

pio run             # compilar
pio run -t upload   # subir
pio device monitor  # monitor serie

🧰 Herramientas (tools/)

Script Para qué
make_vlw.py Genera la fuente .vlw con acentos desde un TTF (necesita pip install freetype-py).
aemet_estaciones.py Descarga el listado completo de estaciones AEMET a CSV (solo librería estándar).
make_thumbs.py Genera las miniaturas (.thumbnails/) de fotos y vídeos para que la vista de miniaturas del gestor web cargue rápido. pip install pillow (y ffmpeg para vídeos). Ej.: python make_thumbs.py E:\. Truco: cópialo a la raíz de la microSD y ejecútalo sin argumentos → escanea toda la tarjeta.

🗺️ Estado y hoja de ruta

  • Framework de modos (cambio con G1, persistencia en NVS)
  • Clima (sensor + AEMET predicción + observación, multi-localidad, iconos)
  • Carrusel (auto-rotación)
  • Música (ES8311, MP3/M4A/FLAC, controles iPod Shuffle, acentos VLW)
  • Modo oculto TV-B-Gone (IR + feedback LED)
  • Modo libro TXT (selector + paginado + memoria por libro)
  • Refresco LOCAL con cadencia inteligente (1 min; 5 min en reposo)
  • Arranque rápido (pantalla local inmediata; WiFi/NTP/AEMET en segundo plano)
  • Bajo consumo: light sleep en reposo + apagado por PMIC tras inactividad
  • HOY ampliado: viento + racha, índice UV, previsión por horas
  • Lector: alto de línea automático según el tamaño de body.vlw
  • Modos activables/desactivables desde config.json
  • Modo WiFi: se une a tu red (muestra IP) o crea AP propio; gestor web con login
  • Web: fotos (proporción real + swipe), vídeo (Range/206), tema claro-oscuro, config por formulario
  • Web: vista lista / detalles / miniaturas, mini-reproductor de música y descarga de carpeta en ZIP
  • Web: PDF (visor del navegador) y EPUB (lector integrado, libs en /lib de la SD)
  • Web: caché de miniaturas/imágenes (reentrar a carpetas grandes es instantáneo)
  • microSD a 40 MHz (con repliegue a 20 MHz) para más caudal de música/vídeo/web
  • Alarma RTC para encender a una hora programada
  • Servidor web asíncrono (cancelar descargas grandes sin esperas; solo si hace falta)

📖 EPUB: el lector en pantalla se queda en TXT (el refresco a color es lento para pasar páginas). El EPUB se lee desde el gestor web (lector integrado), que es más cómodo; en la pantalla del equipo, mejor TXT.

ℹ️ Sobre los refrescos: el e-paper a color (Spectra 6) solo hace refrescos completos (no admite refresco parcial de una región como los e-paper monocromos). Por eso la estrategia es minimizar la frecuencia: la vista LOCAL del clima se refresca una vez por minuto, y pasa a una vez cada 5 minutos si no se toca ningún botón. Las vistas de AEMET solo refrescan al navegar o al actualizar (mantener G1).


📜 Licencia y créditos

Proyecto personal de uso libre con fines educativos. Esquemático y librerías son de M5Stack. Datos meteorológicos cortesía de AEMET. Códigos IR portados de m5stick-weather-tvbgone.

Desarrollado para el M5Paper Color con ayuda de Claude (Anthropic).

About

Multimode station for M5Paper Color (ESP32-S3): weather with AEMET forecast, photo carousel, RTC+NTP. Configuration on microSD.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C++ 88.5%
  • Python 6.6%
  • C 4.9%