Clément Saillant 00596f39cd fix(box): radio sound + add SuperLoustic station
Webradio was silent: the streams are stereo 44.1 kHz MP3, and opening the
ES8311 codec in stereo failed ("i2s_std_set_slot: dma descriptor") because the
stereo I2S DMA no longer fits the tight internal RAM — the podcast path works
only because its files are mono. Downmix the decoded stereo PCM to mono and
open the codec at one channel. Also switch the stream URLs to plain HTTP: the
HTTPS handshake intermittently failed to allocate AES memory, and these mounts
serve identical audio over http with no redirect. Add SuperLoustic (3 stations).
2026-06-15 10:02:12 +02:00
2026-06-15 07:45:15 +02:00
2026-06-14 00:40:46 +02:00

Lisael Box

Firmware ESP32-S3-BOX-3 pour une "boîte" à destination d'un jeune enfant : webradios FR enfants, boîte à sons (microSD), coin calme / respiration, horloge / veilleuse, et jeux adaptés. UI tactile LVGL, sans lecture obligatoire (gros boutons + icônes), volume bridé (plafond enfant).

⚠️ Statut : point de départ soigné, NON compilé / NON flashé. Ce dépôt a été écrit sans la carte ni ESP-IDF/ESP-ADF installés. Le code suit les APIs ESP-IDF 5.x, le BSP esp-box-3 (v3.2.x, LVGL 9) et ESP-ADF de façon idiomatique, mais rien n'a pu être bâti. Voir la section À vérifier sur le matériel — elle est honnête et exhaustive.

Matériel cible

  • ESP32-S3-BOX-3 : ESP32-S3 (8 Mo PSRAM octal, 16 Mo flash), LCD 320×240 tactile capacitif, codec audio ES8311 + HP, micro ES7210, microSD, IMU (ICM-42670). Pas de capteur température/humidité externe sur la carte de base (un add-on AHT30 existe ; non supposé présent ici).

Stack logicielle

  • ESP-IDF 5.4 / 5.5 (nouvelles APIs : driver/i2c_master.h, driver/temperature_sensor.h, esp_netif_sntp.h, …).
  • BSP espressif/esp-box-3 ^3.2.0 (managed component) — écran, tactile, LVGL port, codec ES8311 (esp_codec_dev), microSD (FATFS), boutons, IMU. Tire transitivement esp_lvgl_port ^2, LVGL 9.x, esp_codec_dev ~1.5.
  • LVGL 9 pour l'UI tactile.
  • ESP-ADF pour l'audio en streaming/décodage (webradio + lecture SD). ESP-ADF n'est pas un managed component : il s'installe à part (voir ci-dessous).
  • espressif/cjson pour le manifest.json SD et les réponses open-meteo.

Arborescence

lisael-box/
├── CMakeLists.txt            # projet ; injecte ESP-ADF via ADF_PATH
├── partitions.csv            # 16 MB : factory 4 MB + storage FAT
├── sdkconfig.defaults        # défauts communs
├── sdkconfig.defaults.esp32s3# PSRAM octal, 16 MB flash, 240 MHz, LVGL/PSRAM
├── main/
│   ├── CMakeLists.txt        # sources + REQUIRES (BSP, ADF guardé)
│   ├── idf_component.yml     # managed deps (esp-box-3, cjson)
│   ├── Kconfig.projbuild     # menuconfig : WiFi, lat/lon météo, volume
│   ├── lisael_config.h       # constantes partagées (TZ, NVS keys, volume)
│   ├── app_main.c            # séquence de boot + tâches
│   ├── net/
│   │   ├── wifi.{c,h}        # STA + reconnexion + creds NVS/menuconfig
│   │   ├── sntp_time.{c,h}   # SNTP + fuseau Europe/Paris
│   │   └── weather.{c,h}     # open-meteo.com (HTTPS, sans clé) périodique
│   ├── audio/
│   │   ├── audio_player.{c,h}# façade codec ES8311 + volume bridé (NVS)
│   │   ├── radio_pipeline.{c,h} # ESP-ADF http_stream→decoder→i2s
│   │   └── sd_player.{c,h}   # ESP-ADF fatfs→mp3→i2s + parse manifest.json
│   ├── ui/
│   │   ├── ui.{c,h}          # shell LVGL + routeur de modes + styles
│   │   ├── fr_date.{c,h}     # date FR en lettres (sans setlocale)
│   │   └── icons.{c,h}       # glyphes/emoji des tuiles et boutons
│   └── modes/
│       ├── home.c            # accueil : date FR, heure, météo, capteur, tuiles
│       ├── radio.c           # écran webradios + volume/stop
│       ├── radios.h          # liste de stations (URLs à vérifier)
│       ├── soundbox.c        # grille SD depuis manifest.json
│       ├── calm.c            # bulle de respiration (anim LVGL)
│       ├── clock.c           # horloge/veilleuse + histoire du soir
│       └── games.c           # Memory + Compter + Coloriage (stub)
└── sdcard/
    ├── README.md             # disposition attendue de la carte
    └── sounds/manifest.json  # exemple de manifeste

Prérequis

  1. ESP-IDF 5.4+ installé et exporté :

    . $IDF_PATH/export.sh
    
  2. ESP-ADF installé séparément (audio streaming/décodage). ESP-ADF n'est pas distribué via le registre de composants ; on le clone et on exporte ADF_PATH :

    git clone --recursive https://github.com/espressif/esp-adf.git ~/esp/esp-adf
    export ADF_PATH=~/esp/esp-adf
    # (esp-adf fournit aussi $ADF_PATH/export.sh qui définit ADF_PATH)
    

    Le CMakeLists.txt racine ajoute $ADF_PATH/components à EXTRA_COMPONENT_DIRS. Si ADF_PATH est absent, le projet configure quand même (UI/horloge/respiration), mais les modules audio (webradio, lecture SD) ne sont pas liés et renvoient ESP_ERR_NOT_SUPPORTED à l'exécution (gardes __has_include("audio_pipeline.h")).

    ⚠️ Compatibilité de versions à vérifier. ESP-ADF s'épingle historiquement à des versions précises d'ESP-IDF, et son abstraction audio_board peut entrer en conflit avec le BSP esp-box-3 (les deux veulent gérer l'I2S/le codec). Voir À vérifier sur le matériel.

Build & flash

# 1. cibler l'ESP32-S3
idf.py set-target esp32s3

# 2. configurer le WiFi et la météo (lat/lon, ville)
idf.py menuconfig
#   -> "Lisael Box configuration" -> Wi-Fi / Weather / Audio

# 3. build (télécharge les managed components dans managed_components/)
idf.py build

# 4. flash + monitor (macOS : le port apparaît en /dev/cu.usbmodem*)
idf.py -p /dev/cu.usbmodem* flash monitor
#   (Linux : -p /dev/ttyUSB0 ou /dev/ttyACM0 ; Ctrl+] pour quitter le monitor)

Provisioning Wi-Fi

Deux voies :

  • menuconfig : Lisael Box configuration → Wi-Fi → SSID / password. Les valeurs partent dans le binaire (pratique en dev).
  • NVS à l'exécution : lisael_wifi_save_credentials() écrit les clés wifi_ssid / wifi_pass dans le namespace lisael ; elles priment sur les valeurs menuconfig au boot suivant. Brancher un petit portail captif ou une commande console reste à faire (les valeurs menuconfig suffisent pour démarrer).

Météo

api.open-meteo.com (gratuit, sans clé, HTTPS via le CA bundle mbedTLS). La latitude/longitude viennent de NVS (lat/lon) sinon des défauts menuconfig (Paris). Rafraîchissement toutes les CONFIG_LISAEL_WEATHER_REFRESH_MIN min. En cas d'échec réseau, l'accueil affiche .

Carte microSD

Voir sdcard/README.md. En bref : FAT32, dossier /sounds/ contenant des .mp3 + un manifest.json ([{file, title, emoji}]). Les clips seront générés plus tard par TTS FR.

Modes

Mode Fichier Implémenté Notes
Accueil modes/home.c date FR en lettres, heure (SNTP), météo (open-meteo), temp interne de la puce (fallback), 5 tuiles
📻 Webradios modes/radio.c + audio/radio_pipeline.c code / ⚠️ URLs pipeline ESP-ADF http_stream→decoder→i2s ; URLs de stations à confirmer (modes/radios.h)
🔊 Boîte à sons modes/soundbox.c + audio/sd_player.c grille depuis manifest.json ; pipeline fatfs→mp3→i2s
🫧 Coin calme modes/calm.c bulle qui gonfle (~4 s) / dégonfle (~6 s) en boucle, "Inspire…/Souffle…", ambiance SD optionnelle
🕐 Horloge/veilleuse modes/clock.c grande heure + date FR, fond sombre doux, backlight tamisé, bouton "Histoire du soir"
🎮 Jeux modes/games.c Memory + Compter / 🚧 Coloriage stub feedback positif uniquement, pas de défaite ; Coloriage est un stub documenté (canvas tactile = plus lourd sur 320×240)

Sécurité enfant

  • Volume bridé : plafond CONFIG_LISAEL_VOLUME_MAX_PERCENT (défaut 60 %), appliqué partout via audio_player.c (clamp_volume), persisté en NVS.
  • Pas de lecture requise : icônes/emoji + gros boutons (≥ 56 px).
  • Jeux sans échec : aucun score punitif, retour "Bravo ! ".

À vérifier sur le matériel

Liste honnête de ce qui n'a pas pu être testé et doit être validé sur une vraie carte :

  1. Compilation. Le code n'a jamais été bâti (ni ESP-IDF ni ESP-ADF installés ici). Attendez-vous à des ajustements : noms exacts de composants managés ESP-ADF dans REQUIRES (audio_pipeline, audio_stream, esp-adf-libs, audio_sal) et includes/macros décodeur exacts (DEFAULT_ESP_MP3_DECODER_CONFIG vs …_AUDIO_DECODER_CONFIG varie selon la révision ADF). cJSON = composant built-in json d'ESP-IDF.
  2. Coexistence BSP ↔ ESP-ADF sur l'I2S/codec. C'est le point chaud. Le BSP esp-box-3 initialise l'I2S et le codec ES8311 (bsp_audio_init / bsp_audio_codec_speaker_init), et ESP-ADF i2s_stream veut lui aussi posséder le port I2S. Deux approches connues, à arbitrer sur le matériel :
    • (A) ADF possède l'I2S : configurer i2s_stream avec le port/pins du BOX-3 et ne pas appeler bsp_audio_init ; n'utiliser le handle codec du BSP que pour le volume/gain. (approche codée ici)
    • (B) Le BSP possède l'I2S : écrire le PCM décodé vers le codec via esp_codec_dev_write() depuis un raw_stream au lieu de i2s_stream. Les configs i2s_std (port, broches, horloge via i2s_stream_set_clk) dans radio_pipeline.c / sd_player.c portent des TODO(hardware) — elles doivent matcher les valeurs du BSP de votre version.
  3. Version ESP-ADF compatible avec votre ESP-IDF 5.4/5.5 (ADF s'épingle souvent à une révision IDF précise). L'abstraction audio_board d'ADF peut doublonner le BSP — c'est pourquoi board.h n'est pas inclus.
  4. URLs des webradios (modes/radios.h) : ce sont des placeholders plausibles (Radio Pomme d'Api, Radio Doudou, etc.). Confirmez chaque flux (curl -Iaudio/mpeg ou audio/aac) et préférez du MP3 HTTP simple.
  5. Polices / emoji LVGL. Les fonts Montserrat par défaut ne contiennent pas les emoji ; les glyphes 📻🔊🫧… risquent d'apparaître en "tofu". Pour les rendre, embarquez une police emoji (subset Noto via lv_font_conv) ou remplacez par le set monochrome LV_SYMBOL_* (déjà utilisé pour les flèches et contrôles). Les accents FR (é, à, û, î) demandent une police Latin-1 — à vérifier aussi.
  6. Tailles de police montserrat (lv_font_montserrat_28/48) : activez-les dans menuconfig → Component config → LVGL → Font usage si elles ne sont pas dans le set par défaut.
  7. Backlight / luminosité. bsp_display_brightness_set() / bsp_display_backlight_on() supposés présents dans le BSP — à confirmer sur votre version (sinon le mode veilleuse ne tamise pas).
  8. Capteurs. Seule la température interne de la puce (driver/temperature_sensor.h) est lue, en fallback : ce n'est PAS la température de la pièce. L'IMU ICM-42670 et l'éventuel AHT30 ne sont pas exploités (le BSP expose bsp_sensor_init — à brancher si voulu).
  9. Profondeur de pile des tâches. net/weather à 8192 o (TLS+HTTP+JSON), tick à 4096 o, tâche LVGL gérée par le BSP — à surveiller au monitor (uxTaskGetStackHighWaterMark) sous charge audio + UI.
  10. Mémoire de jeu (games.c). Les états Memory/Compter sont alloués via lv_malloc et vivent le temps de l'écran (non libérés à la destruction) — OK pour une app mono-écran longue durée, à durcir si les écrans sont recréés en boucle.
  11. Politique supply-chain. Conformément au dépôt parent, les deps doivent à terme être miroitées/épinglées par hash contre la baseline auditée (idf_component.yml ne fige aujourd'hui que les versions sémantiques).

Licence

À définir (aligner sur la politique de l'org electron-rare).

S
Description
Lisael Box — firmware ESP32-S3-BOX-3 : webradios FR enfants + boite a sons SD + coin calme + horloge. ESP-IDF/ESP-ADF/LVGL.
Readme 908 KiB
Languages
C 93.8%
Python 4%
HTML 1.8%
CMake 0.3%