En réfléchissant comment relancer un peu ce projet de boite à histoires je suis parvenu à la conclusion qu’il fallait le documenter sur une base régulière. Pour ce faire je vais donc m’astreindre à écrire des billets de blog sur une base la plus régulière possible (mais je ne me mouille pas sur la fréquence encore ;).
Quoi de mieux pour maîtriser un sujet que d’en parler !
Alors, qu’est-ce que le raconteur ?
C’est une boite à histoire «faites maison» qui utilise deux modules électroniques autonome :
Un lecteur MP3 pilotable par port série : DFPlayer mini
Le module MP3 est conçu pour fonctionner de manière parfaitement autonome si on lui branche un haut parleur, une alimentation et des boutons poussoir. Les musiques à jouer se trouvent elles sur la carte microSD. Pour le raconteur nous utiliserons le port série RX/TX pour le piloter au moyen de la Longan Nano.
La carte de pilotage Longan Nano
La carte Longan Nano est programmable par le ports usb-c, elle est elle aussi munie d’un lecteur de microSD. Cette microSD va nous servir à stocker la description des histoires que le lecteur de MP3 va jouer. Comme le kit proposé sur Aliexpress est munie d’un écran amoled nous nous en servirons pour afficher des images représentant l’histoire à jouer et/ou une étape du menu.
Les deux cartes microSD
Je n’ai pas encore donné les détail de la programmation de la longan nano qui pilote l’ensemble mais un problème saute déjà au yeux : Il y a besoin de deux cartes microSD.
Une carte contenant les histoires (ensemble de fichier MP3 lisibles par le DFPLayer mini)
Une carte contenant la description des histoires, les images des menus ainsi que l’arborescence de navigation
Le programme est quand à lui téléchargé dans la mémoire flash du microcontrôleur.
Ça fait beaucoup de données à compiler et formater pour chaque histoire. D’où l’idée de créer un logiciel pour télécharger, cuisiner et servir les histoires pour le raconteur.
Ce logiciel est en cours de développement également et se nomme Recette d’Histoire. Il est codé en Rust (parce que j’ai envie d’apprendre le Rust) et se base sur des «recettes» présentées sous forme de fichier Yaml.
Mais sa description fera l’objet d’un futur billet de blog.
L’utilitaire permettant de générer les histoires à télécharger dans le Raconteur se nomme RecetteDHistoire. Il est développé en Rust. C’est une bonne excuse pour apprendre ce nouveau langage.
Un des reproche actuel fait à ce langage de programmation système est qu’il n’est pas encore très mature, ses interfaces ne sont pas encore très stable.
Pour le moment, le développement de RecetteDHistoire n’est pas ralenti par des problèmes de stabilitées de ses interfaces. L’apprentissage du langage lui même est déjà suffisamment chronophage 😉
On peut noter cependant que les versions des bibliothèques utilisées (on parle de crate dans le langage du crabe) sont majoritairement en dessous de leurs version 1.0.0 lorsque l’on compile le logiciel:
Ça fait un beau paquet de dépendances ! Mais ça se compile sans problème, et c’est même une des grandes qualité du langage : son outil de compilation et de gestion des bibliothèque.
Sur les 191 paquets utilisés nous avons :
131 en version 0.x.x
47 en version 1.x.x
7 en version 2.x.x
2 en version 3.x.x
2 en version 4.x.x
1 en version 6.x.x
1 en version 9.x.x
Je ne sais pas si la version des dépendances est un bon indicateur de stabilité d’un langage. Mais il est indubitablement un indicateur de sa jeunesse à mon avis.
Le module ESP32-WROVER-E est un module Wifi de chez Espressif à base de microcontrôleur Xtensa ® 32-bit LX6. On le trouve au tarif très compétitif d’environ 3.5€ chez les distributeurs habituels.
On trouve un kit de développement pour une grosse dizaine d’euros sur aliexpress: Le ESP32_DevKitc_V4. Et c’est le module que je viens de recevoir ce matin dans ma boite aux lettres.
La commande de ce kit n’est pas due au hasard, l’ESP32-WROVER-E est le module utilisé au cœur de la boite à histoires de France-inter/Bayard-Press : Merlin.
Branchement
Espressif fourni un tutoriel sur son wiki pour la prise en main du ESP32-DevKitC V4.
Au branchement de l’USB, un convertisseur USB-UART (cp210x) est détecté :
$ dmesg
[1174313.734558] usb 1-1.1.2: new full-speed USB device number 118 using xhci_hcd
[1174313.836871] usb 1-1.1.2: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
[1174313.836876] usb 1-1.1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1174313.836878] usb 1-1.1.2: Product: CP2102N USB to UART Bridge Controller
[1174313.836880] usb 1-1.1.2: Manufacturer: Silicon Labs
[1174313.836882] usb 1-1.1.2: SerialNumber: 0ae36f4e9dfbeb11b9dfaef7c6d924ec
[1174313.843495] cp210x 1-1.1.2:1.0: cp210x converter detected
[1174313.846185] usb 1-1.1.2: cp210x converter now attached to ttyUSB0
Si on connecte un terminal au port série ttyUSB0 en 115200 bauds on obtient une suite de message qui se déroule indéfiniment :
Une fois le programme «hello world» d’exemple compilé, il suffit de lancer le flashage avec :
$ idf.py -p /dev/ttyUSB0 flash
Executing action: flash
Running ninja in directory /opt/esp/hello_world/build
Executing "ninja flash"...
[1/5] cd /opt/esp/hello_world/build/esp-idf/esptool_py && /home/fabien/.espressif/python_env/idf5.0_py3....opt/esp/hello_world/build/partition_table/partition-table.bin /opt/esp/hello_world/build/hello_world.bin
hello_world.bin binary size 0x298e0 bytes. Smallest app partition is 0x100000 bytes. 0xd6720 bytes (84%) free.
[2/5] Performing build step for 'bootloader'
[1/1] cd /opt/esp/hello_world/build/bootloader/esp-idf/esptool_py && /home/fabien/.espressif/python_env/idf5.0_py3.7_env/bin/python /opt/esp/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x1000 /opt/esp/hello_world/build/bootloader/bootloader.bin
Bootloader binary size 0x6350 bytes. 0xcb0 bytes (11%) free.
[2/3] cd /opt/esp/esp-idf/components/esptool_py && /usr/local/bin/cmake -D IDF_PATH=/opt/esp/esp-idf -D ...ING_DIRECTORY=/opt/esp/hello_world/build -P /opt/esp/esp-idf/components/esptool_py/run_serial_tool.cmake
esptool.py esp32 -p /dev/ttyUSB0 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x1000 bootloader/bootloader.bin 0x10000 hello_world.bin 0x8000 partition_table/partition-table.bin
esptool.py v3.3-dev
Serial port /dev/ttyUSB0
Connecting.....
Chip is ESP32-D0WD-V3 (revision 3)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 34:94:54:b7:31:e0
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x00007fff...
Flash will be erased from 0x00010000 to 0x00039fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Compressed 25424 bytes to 15896...
Writing at 0x00001000... (100 %)
Wrote 25424 bytes (15896 compressed) at 0x00001000 in 0.7 seconds (effective 282.8 kbit/s)...
Hash of data verified.
Compressed 170208 bytes to 89791...
Writing at 0x00010000... (16 %)
Writing at 0x0001b0a3... (33 %)
Writing at 0x00020836... (50 %)
Writing at 0x00026023... (66 %)
Writing at 0x0002e652... (83 %)
Writing at 0x00036a08... (100 %)
Wrote 170208 bytes (89791 compressed) at 0x00010000 in 2.3 seconds (effective 581.7 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 103...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 479.6 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
Done
Puis de se connecter au terminal uart avec screen pour obtenir la sortie fonctionnelle du programme :
$ screen /dev/ttyUSB0 115200
...
Restarting now.
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6736
load:0x40078000,len:14808
load:0x40080400,len:3792
entry 0x40080694
I (27) boot: ESP-IDF v5.0-dev-810-gb886dc6998 2nd stage bootloader
I (27) boot: compile time 21:20:00
I (27) boot: chip revision: 3
I (32) boot_comm: chip revision: 3, min. bootloader chip revision: 0
I (39) boot.esp32: SPI Speed : 40MHz
I (43) boot.esp32: SPI Mode : DIO
I (48) boot.esp32: SPI Flash Size : 2MB
I (52) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (61) boot: ## Label Usage Type ST Offset Length
I (69) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (76) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (84) boot: 2 factory factory app 00 00 00010000 00100000
I (91) boot: End of partition table
I (95) boot_comm: chip revision: 3, min. application chip revision: 0
I (102) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=07824h ( 30756) map
I (122) esp_image: segment 1: paddr=0001784c vaddr=3ffb0000 size=023b0h ( 9136) load
I (126) esp_image: segment 2: paddr=00019c04 vaddr=40080000 size=06414h ( 25620) load
I (141) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=14a4ch ( 84556) map
I (171) esp_image: segment 4: paddr=00034a74 vaddr=40086414 size=04e2ch ( 20012) load
I (180) esp_image: segment 5: paddr=000398a8 vaddr=50000000 size=00010h ( 16) load
I (186) boot: Loaded app from partition at offset 0x10000
I (186) boot: Disabling RNG early entropy source...
I (200) cpu_start: Pro cpu up.
I (200) cpu_start: Starting app cpu, entry point is 0x40081004
I (187) cpu_start: App cpu up.
I (214) cpu_start: Pro cpu start user code
I (215) cpu_start: cpu freq: 160000000 Hz
I (215) cpu_start: Application information:
I (219) cpu_start: Project name: hello_world
I (225) cpu_start: App version: 1
I (229) cpu_start: Compile time: Dec 21 2021 21:19:52
I (235) cpu_start: ELF file SHA256: 81272dfce4dde882...
I (241) cpu_start: ESP-IDF: v5.0-dev-810-gb886dc6998
I (248) heap_init: Initializing. RAM available for dynamic allocation:
I (255) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (261) heap_init: At 3FFB2CA0 len 0002D360 (180 KiB): DRAM
I (267) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (273) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (280) heap_init: At 4008B240 len 00014DC0 (83 KiB): IRAM
I (287) spi_flash: detected chip: generic
I (291) spi_flash: flash io: dio
W (295) spi_flash: Detected size(8192k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (309) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
Hello world!
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision 3, 2MB external flash
Minimum free heap size: 294172 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
L’installation des outils et le flashage d’une première application «hello world» est incroyablement facile à mettre en œuvre. Il faudra voir à l’usage comment on peut décoder des MP3 et afficher des images provenant d’une carte SD.