Jouer des sons depuis le Raspberry Pi Pico à l’aide de CircuitPython – un voyage de découverte – Raspberry Pi Pod et base micro:bit

Jouer des sons depuis le Raspberry Pi Pico à l'aide de CircuitPython - un voyage de découverte - Raspberry Pi Pod et base micro:bit

Comme vous le savez probablement déjà, je ne suis pas un expert en microcontrôleurs. Cependant, avec l’avènement des microcontrôleurs qui utilisent MicroPython et CircuitPython, je suis beaucoup plus à l’aise avec eux maintenant qu’avant ! Cependant, comme le Raspberry Pi Pico est nouveau, il n’existe pas beaucoup d’exemples pratiques sur la façon de procéder. Il y a excellente documentationbien sûr, mais quand on essaie de faire quelque chose de spécifique, ou quelque chose auquel on n’a pas pensé, cela peut être un voyage de découverte.

TL;DR

Faites défiler jusqu’à « Lecture d’un fichier WAV » pour le code qui fonctionne et « Trouver le matériel » pour un schéma de câblage.

Le projet

Je travaille actuellement sur une nouvelle version de mon projet Picorder de longue date, ma version de l’accessoire classique de Star Trek, le Tricorder. Alors que dans le passé, j’utilisais exclusivement un Raspberry Pi classique (avec une incursion occasionnelle dans Arduino pour obtenir des entrées analogiques) comme cerveau, cette fois, je choisis d’utiliser le Pico. Un PicoPicorder, si vous voulez. Une chose que je n’ai jamais faite auparavant est de reproduire les sons émis lorsque l’appareil est ouvert et scanné.

Trouver l’effet sonore

Mon premier travail consistait à trouver le son que je voulais jouer. C’était facile. TrekCore propose toute une série d’effets sonores de la série Star Trek. J’ai choisi celui que je voulais (celui-ci) et je l’ai téléchargé. J’ai tout de suite su que le fichier complet était trop long (et volumineux), alors je l’ai converti en utilisant Audacedans un fichier WAV, je l’ai écrasé en un échantillon mono et j’en ai coupé la majeure partie, me laissant avec un effet sonore autonome, beaucoup plus court et bouclable.

Comment y jouer

Maintenant… comment y jouer. Pour commencer, j’ai envisagé de créer mon propre circuit et d’utiliser PWM Audio. Ce message de Greg Chadwick indiqué que je pouvais faire exactement cela. Cependant, excusez-moi, cela me dépassait un peu. Il utilisait également le C/C++ comme langage de programmation. J’avais déjà décidé que, pour ce projet, j’utiliserais le logiciel d’Adafruit CircuitPython dérivé de MicroPython. Il y avait beaucoup de bibliothèques, c’est, en gros, du Python (que je peux déjà utiliser dans une certaine mesure, grâce aux CamJam EduKits et à tous les autres tutoriels qui sont disponibles), et c’est abondamment documenté.

Cependant, cet article de blog et une documentation Pico déjà lue m’ont fait remarquer la nécessité d’utiliser l’audio I2S, ce qui correspond à la façon dont les cartes audio (DAC) fonctionnent avec le Raspberry Pi. Cela me donnerait une qualité audio suffisamment élevée pour jouer mon effet sonore et me donnerait un peu de familiarité (ce qui, je pense toujours, est essentiel pour comprendre comment faire quelque chose).

Les Raspberry Pi Pico et I2S

Cependant (encore une fois), d’après mes lectures précédentes, je savais que le Pico n’a pas de broches I2S de la même manière que le Pi classique. Certains microcontrôleurs l’ont intégré, mais pas le Pico. Je savais aussi que, pour donner au Pico des fonctionnalités qu’il n’a pas, on utilise PIO (entrée/sortie programmable). (Si vous voulez en savoir plus sur la façon de comprendre PIO, il y a cet excellent article). C’est en fait assez difficile de trouver des « comment faire » sur le site Raspberry Pi pour PIO… en fait, j’ai complètement échoué, il va donc falloir fouiller un peu.

Tout d’abord, j’ai découvert cet exemple du référentiel Raspberry Pi GitHub qui montrait le code PIO dont vous aviez besoin pour y parvenir. Cependant, comme il est écrit en C/C++ et qu’il est destiné à la méthode SDK de programmation du Pico, plutôt qu’à CircuitPython, cela m’a plutôt époustouflé. C’est la partie importante, le code PIO :

.program audio_i2s
.side_set 2

    ; /--- LRCLK
    ; |/-- BCLK
bitloop1: ; ||
    out pins, 1 side 0b10
    jmp x-- bitloop1 side 0b11
    out pins, 1 side 0b00
    set x, 14 side 0b01

bitloop0:
    out pins, 1 side 0b00
    jmp x-- bitloop0 side 0b01
    out pins, 1 side 0b10
public entry_point:
    set x, 14 side 0b11

Un charabia complet, ai-je raison ? C’est à ce moment-là que j’ai failli abandonner. 0b10 ? jmp ? C’est un langage assembleur, pensais-je, pour l’implémentation particulière sur le Pico. C’est assez juste, mais je n’ai aucune idée de ce que tout cela signifie. Cependant, cela signifiait-il que je ne pouvais pas l’utiliser ? j’avais vu un exemple dans MicroPython pour utiliser PIO dans Python (merci Alister !) lui-même, mais pas CircuitPython.

J’ai pensé que je prendrais du recul et aborder les choses d’une manière différente.

Trouver le matériel

J’ai évalué la quantité de compétences en résolution de problèmes que j’avais et, assez bêtement, j’ai supposé que je serais capable de faire fonctionner I2S, d’une manière ou d’une autre.

Si je pouvais faire fonctionner l’I2S, je savais que j’aurais besoin d’un DAC et d’un amplificateur pour émettre le son du Pico. je suis tombé sur ce tutoriel sur le site d’Adafruit pour utiliser l’ampli mono MAX98357 I2S qui combinait un ampli I2S et un DAC sur la même carte. Idéal. Il ne produit que vers un seul haut-parleur mais, pour ce projet, un petit haut-parleur suffit. j’ai trouvé l’évasion sur le site de The Pi Hut et ils ont eu la gentillesse de me l’envoyer avec quelques autres éléments à des fins de révision.

En regardant davantage le tutoriel sur Adafruit, je suis tombé sur le test de câblage CircuitPython. Cela montre comment connecter la carte MAX à un microcontrôleur avec des broches I2S. À mon grand désarroi, l’exemple de code ne couvrait pas la partie PIO. D’accord, ai-je pensé, nous pouvons briser cette partie et l’autre partie d’une manière ou d’une autre.

La carte MAX est arrivée le lendemain et je l’ai câblée. Voici mon câblage (merci Adafruit et Fritzing pour le logiciel et la bibliothèque de pièces !) :

1762920009 546 Jouer des sons depuis le Raspberry Pi Pico a laide

Maintenant que cela était fait, PIO était la prochaine étape. C’est du moins ce que je pensais.

Utiliser PIO dans CircuitPython et le serveur Adafruit Discord

À ce stade, je savais que j’allais avoir besoin d’une aide supplémentaire. Adafruit a, étonnamment, créé une chaîne Discord pour discuter de leurs produits et, Alléluia, CircuitPython. Il y avait même une chaîne spéciale pour PIO. J’ai rejoint le groupe et j’ai ensuite réalisé à quel point toutes les chaînes étaient actives : géniales, avec tant d’expertise et d’expérience.

D’après les suggestions reçues là-bas, je suis tombé sur ce tutoriel sur le site Adafruit pour utiliser PIO dans CircuitPythonalors j’ai enfin su que ce que j’essayais de faire était possible. Quelqu’un a alors souligné cet exemple qui utilise PIOASM (assembleur PIO) pour créer de l’audio sur le Pico en utilisant CircuitPython.

Vouloir savoir comment les choses fonctionnent

À ce stade, j’ai perdu plusieurs heures à essayer de combiner les choses avant de réaliser que je devais partir des premiers principes.

De retour à l’exemple d’avant qui montre l’exemple PIOASM pour créer de l’audio dans CircuitPython. Tout ce que fait l’exemple est de créer le code PIO nécessaire, de l’assembler, puis de l’utiliser pour lire une onde sinusoïdale.

À ma grande surprise, une fois les broches triées, le système s’est écrasé. J’ai eu l’erreur suivante que d’autres pourraient avoir, alors la voici :

Traceback (most recent call last):
File "code.py", line 40, in  File "adafruit_pioasm.py",
line 65, in assemble IndexError: list index out of range

Hmmm. Vexant, ça.

J’étais tombé sur cette vidéo, un « Deep Dive » avec Scott, qui travaille sur CircuitPython pour Adafruit :

YouTube video

Et je me suis demandé… la fonctionnalité était-elle si nouvelle que j’utilisais une version trop ancienne de CircuitPython et de ses bibliothèques ? J’ai téléchargé le dernière version stable de CircuitPython UF2 à partir de cette page qui était 6.2.0-beta.4 à l’époque. Moi aussi téléchargé la dernière version des bibliothèques et mis à jour le fichier PIOASM Python à partir de là sur mon Pico. Je l’ai réexécuté et… ça a fonctionné ! Ça a marché ! Génial! Mais ce n’était pas la fin de l’aventure… Je voulais lire un fichier WAV.

Lecture d’un fichier WAV

Je suis revenu à la page de câblage et de test CircuitPython pour la carte MAX. Celui-ci contient le code suivant :

import audiocore
import board
import audiobusio

wave_file = open("StreetChicken.wav", "rb")
wave = audiocore.WaveFile(wave_file)

audio = audiobusio.I2SOut(board.D1, board.D0, board.D9)

while True:
    audio.play(wave)

while audio.playing:
    pass

Cela crée simplement un objet contenant un exemple de fichier WAV (StreetChicken), configure un périphérique I2S, puis le lit jusqu’à ce qu’il soit terminé.

J’ai modifié les références D1, D0 et D9 en mes propres broches et ajouté les noms des arguments pour plus de clarté :

audio = audiobusio.I2SOut(bit_clock=board.GP10, word_select=board.GP11, data=board.GP9)

Cela correspond au schéma de câblage ci-dessus. À ce stade, je savais que je faisais des gaffes dans le noir et que ça ne marcherait pas. Après tout, aucun truc PIO n’est évident là-bas. Le Pico ne saurait que faire de lui-même. Droite?

Faux.

Le sample, que j’avais copié à la root du lecteur CIRCUITPY du Pico, sortait des haut-parleurs. C’était déformé et répété par-dessus lui-même, mais ça jouait ! Qu’est-ce que c’est ?

Rouler avec

J’ai décidé de continuer avec. J’ai modifié le code pour simplement lire le fichier WAV une fois, puis dormir. Cela a donné le résultat suivant (vous devrez peut-être augmenter le volume) :

YouTube video

C’était assez déformé, comme vous pouvez l’entendre, mais cela correspondait à ce que je pouvais jouer sur mon ordinateur portable. Un morceau de musique électronique hip-hop. Mais pourquoi ça a marché ?

J’ai demandé sur Twitter, j’ai demandé sur la chaîne Adafruit Discord et Peter Onion m’a demandé si je savais ce que faisait le code I2SOut. Je ne l’ai pas fait. J’ai reçu un pointeur vers le code audiobusio/I2SOut sur la chaîne Discord et j’y ai jeté un œil. À ma grande surprise, il contenait tout le code PIO ! Cela signifie… Cela signifie que quelqu’un d’autre a fait tout le travail acharné avec les trucs PIOASM… C’est incroyable !

Effacer le son

j’ai parlé à David Glaude sur la chaîne Discord à propos du problème que je rencontrais avec le son glitch (voir vidéo ci-dessus). Il m’a laissé voir son script de test (qui a été adapté des exemples précédents que j’ai notés ci-dessus). Je l’ai essayé. Il boucle la musique de StreetChicken 10 fois. Cela montrait que le problème de pépin était toujours là et indiquait également un problème avec la partie while i2s.playing – il pourrait y avoir un bug (que David a rapporté). David a également suggéré qu’il y avait un problème avec la connexion du Pico à l’ordinateur portable – c’est-à-dire que la lecture de la mémoire flash interférait avec la lecture de l’I2S. Je l’ai essayé avec une alimentation murale et, en effet, cela a résolu le problème.

J’ai ensuite modifié le code pour lire en boucle mon échantillon sonore du tricordeur, basé sur le code de David. Pour mon plus grand plaisir, il fonctionne parfaitement (s’il est connecté à une source d’alimentation sans lecture). Vous devrez peut-être augmenter un peu le volume audio, mais c’est ce qu’il fait maintenant !

YouTube video

En conclusion

Vous pouvez obtenir du son assez facilement à partir d’un Raspberry Pi Pico en utilisant CircuitPython. Utilisez audiocore pour ouvrir et lire vos fichiers WAV sur I2S avec la bibliothèque audiobusio CircuitPython d’Adafruit qui fait le gros du travail en ce qui concerne PIO. Et connectez-vous à la chaîne Discord d’Adafruit – de nombreuses aides sont disponibles ! 🙂


Retrouvez l’histoire de Raspberry Pi dans cette vidéo :

YouTube video

  • Pre-Soldered Raspberry Pi Pico 2 W with Header RP2350 Microcontroller Board Mini Board Based on Official RP2350 Chip,Supports WiFi and Bluetooth
  • Kit de démarrage de base pour Raspberry Pi Pico, super kit de démarrage pour Raspberry Pi Pico, Raspberry avec breadboard, module d'affichage LCD 2C 1602, capteurs compatibles