Raspberry PI Actualité

Jouer les sons du Raspberry Pi Pico à l’aide de CircuitPython – un voyage de découverte

Par Thomas, le 21 mars 2021 — 11 minutes de lecture
Jouer les sons du Raspberry Pi Pico à l'aide de CircuitPython - un voyage de découverte

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 de les utiliser maintenant qu’auparavant! Cependant, comme le Raspberry Pi Pico est nouveau, il n’y a pas de parcelle d’exemples pratiques de la façon de faire les choses là-bas. Il y a excellente documentation, bien sûr, mais lorsque vous essayez de faire quelque chose de spécifique, ou quelque chose auquel vous n’avez 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 «Recherche du 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’ai utilisé exclusivement le Raspberry Pi ordinaire (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 numérisé.

Trouver l’effet sonore

Mon premier travail a été de trouver le son que je voulais jouer. C’était facile. TrekCore a toute une série d’effets sonores de la série Star Trek. J’ai choisi celui que je voulais (celui-ci) et l’a 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 Audace, dans un fichier WAV, l’a écrasé en un échantillon mono et en a 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 cherché à créer mon propre circuit et à utiliser PWM Audio. Ce message de Greg Chadwick a indiqué que je pouvais faire exactement cela. Cependant, c’était, excusez-moi, un peu au-delà de moi. Il a également utilisé C / C ++ comme langage de programmation. J’avais déjà décidé que, pour ce projet, j’utiliserais Adafruit CircuitPython dérivé de MicroPython. Il y avait beaucoup de bibliothèques, il s’agit, en gros, de Python (que je peux déjà utiliser dans une certaine mesure, grâce aux CamJam EduKits et à tous les autres tutoriels disponibles), et il est largement documenté.

Cependant, cet article de blog et une documentation Pico précédemment lue m’ont fait remarquer que je devais utiliser l’audio I2S, c’est ainsi que 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).

Le Raspberry Pi Pico et I2S

Cependant (encore une fois), d’après mes lectures passées, je savais que le Pico n’a pas de broches I2S de la même manière que le Pi régulier. 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, vous utilisez PIO (entrée / sortie programmable). (Si vous voulez savoir comment comprendre encore plus PIO, il y a cet excellent article). Il est en fait assez difficile de trouver des «comment faire» sur le site Web de Raspberry Pi pour PIO… en fait, j’ai complètement échoué, vous devrez donc 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 cible la méthode SDK de programmation du Pico, plutôt que 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

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

Je pensais prendre du recul et aborder les choses d’une manière différente.

Trouver le matériel

J’ai pesé la quantité de compétences en résolution de problèmes que j’avais et, plutôt stupidement, j’ai supposé que je aurait être en mesure de faire fonctionner I2S, d’une manière ou d’une autre.

Si je pouvais faire fonctionner I2S, alors je savais que j’aurais besoin d’un DAC et d’un amplificateur pour sortir le son du Pico. Je suis tombé sur ce tutoriel sur le site Adafruit pour l’utilisation l’ampli mono MAX98357 I2S qui combinait un ampli I2S et un DAC sur la même carte. Idéal. Il ne sort que vers un seul haut-parleur mais, pour ce projet, un petit haut-parleur est tout ce dont j’ai besoin. j’ai trouvé l’évasion sur le site de Raspberryme.com et ils ont eu la gentillesse de me l’envoyer avec quelques autres morceaux à des fins d’examen.

En regardant plus 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. À ma grande consternation, l’exemple de code ne couvrait pas la partie PIO. D’accord, j’ai pensé, nous pouvons briser ce morceau et l’autre morceau ensemble d’une manière ou d’une autre.

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

Maintenant que c’était fait, PIO était la prochaine étape. Ou c’est ce que j’ai pensé.

Utilisation de 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éé un canal Discord pour une discussion de leurs produits et, Hallelujah, CircuitPython. Il y avait même un canal spécial pour PIO. J’ai rejoint et j’ai réalisé à quel point les canaux étaient tous actifs – génial, tellement d’expertise et vivre.

À partir des suggestions reçues là-bas, je suis tombé sur ce tutoriel sur le site Adafruit pour l’utilisation de PIO dans CircuitPython, alors j’ai finalement su que ce que j’essayais de faire était possible. Quelqu’un a alors pointé cet exemple à moi qui utilise PIOASM (assembleur PIO) pour créer de l’audio sur le Pico à l’aide de 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.

Retournant à l’exemple de plus tôt qui montre l’exemple PIOASM pour créer de l’audio dans CircuitPython. L’exemple ne fait que créer le code PIO nécessaire, l’assembler, puis l’utiliser pour jouer une onde sinusoïdale.

À ma grande surprise, une fois que les épingles ont été triées, elles sont tombées en panne. J’ai eu l’erreur suivante que d’autres pourraient obtenir, alors la voici:

Traceback (most recent call last):
File "code.py", line 40, in <module> 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:

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 du CircuitPython UF2 à partir de cette page qui était à l’époque 6.2.0-beta.4. 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 repris et… ça a marché! Ça a marché! Impressionnant! Mais ce n’était pas la fin de l’aventure… Je voulais lire un fichier WAV.

Lecture d’un fichier WAV

Je suis retourné à 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 changé les références D1, D0 et D9 à mes propres broches et ajouté les noms d’argument 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 gaffais dans le noir et je savais que cela ne fonctionnerait pas. Aucun élément PIO évident là-bas, après tout. Le Pico ne saurait pas quoi faire de lui-même. Droit?

Mal.

L’échantillon, que j’avais copié à la racine du lecteur CIRCUITPY du Pico, est sorti des haut-parleurs. Il était déformé et répété au-dessus de lui-même, mais il jouait! Que diable?

Rouler avec

J’ai décidé de rouler avec. J’ai changé le code pour simplement lire le fichier WAV une fois, puis dormir. Cela a abouti à ce qui suit (vous devrez peut-être augmenter le volume):

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-hoppy. Mais pourquoi cela a-t-il fonctionné?

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 n’ai pas. J’ai reçu un pointeur vers le code audiobusio / I2SOut sur la chaîne Discord et a jeté un coup d’œil. À ma grande surprise, il contenait tout le code PIO! Cela signifie … Cela signifie que quelqu’un d’autre a fait tout le travail dur avec les trucs PIOASM … C’est incroyable!

Effacer le son

J’ai parlé à David Glaude sur le canal Discord à propos du problème que je rencontrais avec le son glitchy (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). J’ai essayé. Il boucle la musique de StreetChicken 10 fois. Il a montré que le problème de pépin était toujours là et a également souligné un problème avec le tandis que i2s.jouer un rôle – il peut y avoir un bug (que David a rapporté). David a également suggéré qu’il y avait un problème avec le Pico connecté à 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 un bloc d’alimentation mural et, en effet, cela a résolu le problème.

J’ai ensuite modifié le code pour le lire ma échantillon sonore du tricordeur en boucle, basé sur le code de David. Pour mon plus grand plaisir, cela 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!

En conclusion

Tu peut obtenir le son, assez facilement, 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 accédez à la chaîne Adafruit Discord – il y a beaucoup d’aide disponible! 🙂

Thomas

Thomas

Fan de Raspberry Pi de la première heure, je suis l'évolution de ces micro-pc depuis maintenant 5 ans. En plus de l'actualité je propose de nombreux tutoriels pour vous aider à exploiter pleinement votre nano-ordinateur côté domotique ou retro-gaming.