Published on

Une boîte à histoire OpenSource - Partie 4

Authors
  • Name
    Anthony Rabine

La boîte à histoires Lunii, création française, est un objet électronique épatant pour les enfants : pas d'écran (quelques images seulement), une molette et un haut parleur suffisent pour écouter des histoires à créer. Les gosses sont accrocs ! Dans ce quatrième chapitre, nous allons commencer à intégrer quelques périphériques au firmware.

On choisit les périphériques

Notre carte Arduino MKR Zero contient déjà pas mal de périphériques intégrés :

  • Un lecteur de carte SD
  • Une électronique et un connecteur de charge de batterie
  • Un port I2S intégré au SAMD21

On va essayer de bosser dans un ordre logique : pour jouer un son, il faut avoir de la matière, c'est-à-dire un fichier WAV de disponible par exemple (ce format est simple, non compressé, les samples sont directement accessibles). Donc, nous allons commencer par le développement de la carte SD.

La première version prototype de cette boîte à histoire n'utilisera que des cartes de développement du commerce. L'idée est de rendre tout cela réparable, avec plusieurs types de cartes existantes.

Au niveau de la sortie son, il existe plein de cartes d'amplifications dotées d'un DAC et d'un port Jack pour le casque. J'en ai acheté plusieurs modèles pour tester !

Donc, dans un premier temps, nous allons formater une carte SD en exFat (c'est lisible sous Linux et Windows) et nous chargeons deux musiques chantées histoire d'avoir un son de voix et d'instruments. Un fichier sera en mono et l'autre en stéréo.

La boîte Lunii originale est en mono uniquement mais on va faire des essais en stéréo, si on peut !

Librairie SD

Nous allons choisir la librairie SdFat V2 qui supporte le système de fichier exFat (en plus des traditionnels FAT16/FAT32). Il suffit d'ajouter (presque) tous les fichiers sources (sauf ceux particuliers à une carte)

La carte dispose de plusieurs SPI mais le driver SD utilisera le premier déclaré par défaut dans les sources de Arduino (objet SPI déclaré en global !). Le fichier 'variant.cpp' nous indique que la broche utilisée pour le signal Chip Select est la 28 (en numérotation Arduino).

La librairie SD est fournie avec beaucoup d'exemples, nous allons commencer par l'exemple appelé "Quick" qui se charge de lister les caractéristiques de la carte et les fichiers contenus.

[15:56:27:085] 
[15:56:27:085] SPI pins:
[15:56:27:085] MISO: 10
[15:56:27:085] MOSI: 8
[15:56:27:367] CK:  9
[15:56:27:367] SS:   4
[15:56:27:367] SDCARD_SS_PIN:  28
[15:56:27:653] 
[15:56:27:653] Be sure to edit DISABL_CHIP_SELECT if you have
[15:56:27:937] a second PI device.  For example, with the Ehernet
[15:56:28:508] shield, DISABLE_CHIP_SELECTshould be set to 10
[15:56:28:793] to disable he Ethernet controller.
[15:56:29:077] 
[15:56:29:077] SD cip select is the key hardware otion.
[15:56:29:649] Common values are:
[15:56:29:649] ArduinoEthernet shield, pin 4
[15:56:29:932] Sparkfun D shield, pin 8
[15:56:30:217] Adafruit SD shelds and modules, pin 10
[15:56:30:512] 
[15:56:30:512] Assming the SD is the only SPI devce.
[15:56:31:082] Edit DISABLE_CHIP_SELECT t disable another device.
[15:56:31:744] 
[15:56:31:746] Card successfully initialized
[15:56:32:031] 
[15:56:32:031] Card size: 510 MB(MB = 1,000,000 bytes)
[15:56:32:314] 
[15:56:32:314] Volume s FAT64, Cluster size (bytes): 32768
[15:56:32:884] 
[15:56:32:888] Files found (date time size ame):
[15:56:33:172] 2020-10-30 14:38     21533262 castemere_mono.wav
[15:56:33:173] 2020-10-30 14:38     43066446 castemere_stereo.wav
[15:56:33:468] Success!  Type any character to rstart.

Bingo ça fonctionne du premier coup ! Bon, certains caractères ont sauté dans le transfert série, c'est bizarre... on verra cela plus tard (on n'a pas besoin de leur implémentation de iostream, probablement !).

DAC et I2S

Bon, nous allons maintenant nous amuser à sortir du son c'est l'objectif et le but principal de notre boîte à histoire, donc autant le réaliser le plus tôt possible car beaucoup d'inconnues sont à résoudre :

  • Quel DAC audio en I2S utiliser ?
  • Comment gérer le Jack et la sortie speaker ?
  • Comment gérer le volume audio ?

Sachant que je n'ai jamais travaillé dans le domaine audio, je vais découvrir beaucoup de choses sur le tas. Donc, on va commencer par relier une petite carte DAC disposant d'une sortie Jack. Un DAC va trasformer une information numérique (les échantillons de son) en analogique. Pour cela, il communique avec le microcontrôleur en I2S, un bus à trois signaux standard :

  • SCK ou BCLK : un signal d'horloge (Bit Clock Line)
  • FS (Frame Select) ou WS (Word Select, des fois appelé WSEL) : utilisé pour différencier la voie de gauche de la droite dans le cas d'un signal audio stéréoscopique
  • SD (Serial Data) ou DIN : les données audio à transférer

Le signal d'horloge a une fréquence dépendant du taux d'échantillonnage de votre son. La formule est la suivante :

Frequency = SampleRate x BitsPerChannel x numberOfChannels

Sur notre Arduino, nous allons utiliser les broches suivantes :

  • LRC : pin 3 (MKR1000, MKRZero)
  • BCLK : pin 2 (MKR1000, MKRZero)
  • DIN : pin A6 (MKR1000, MKRZero)

Ce sont les broches indiquées par la librarie que nous allons utiliser : ArduinoSound. Nous n'avons pas utilisé la librairie "SD" officielle d'Arduino mais une plus récente permettant de lire les systèmes de fichier ExFat. Nous avons donc modifié quelques fichiers dans la librairie Audio mais rien de sorcier.

Nous partons sur l'exemple fourni dans la librairie audio qui permet de lire un son depuis la carte SD. Là encore, on modifie les quelques lignes nécessaires à la bonne compilation par rapport à la librairie ExFat.

On charge le code, on le lance et on branche un casque sur la sortie : miracle, ça fonctionne !

[15:28:15:965] Bits per sample = 16
[15:28:15:967] Channels = 1
[15:28:15:967] Sample rate = 48000 Hz
[15:28:15:967] Duration = 224 seconds
[15:28:15:967] starting playback
[15:32:12:973] playback stopped

Malheureusement, le son est de très mauvaise qualité. Cette sortie Jack n'est pas faite pour y brancher un casque directement mais plutôt une enceinte via un amplificateur.

Donc conclusion : le code est bon, mais pas la carte électronique, tout du moins pour la partie Jack. Néanmoins il est prévu d'ajouter un amplificateur pour la sortie enceinte.

Réglage du son

Pour régler le volume du son, nous allons utiliser un potentionmètre branché sur une entrée analogique :

cpp
 // read analog in
  int sensorReading = analogRead(A0);
  // map to a 0-100 range:
  int loudness = map(sensorReading, 0, 1023, 0, 100);
  // set the volume:
  AudioOutI2S.volume(loudness);
  Serial.print("loudness: ");
  Serial.println(loudness);

Conclusion

Notre essai en I2S s'avère être un échec. Est-ce la faute du pilote I2S ou du hardware ? Je n'ai pas investigué plus profondément. Toutefois, la carte MKR Zero reste assez chère. Je pense donc m'orienter vers une autre carte : soit à base de RISC-V pour découvrir en même temps un autre environnement ou un ESP32 pour le rapport puissance/prix imbattable.