mercredi 9 juillet 2025

MIDI IN avec le Raspberry Pi Pico (Micropython)

Dans cet article, nous allons recevoir, au moyen d'un Raspberry Pi Pico programmé en Micropython, les messages MIDI générés par un clavier musical.

Il s'agit de la suite logique de mon précédent article (publié il y a presque deux ans...mieux vaut tard que jamais!) qui traitait de l'émission d'un signal MIDI.

 



Le circuit

J'ai utilisé l'interface MIDI dont j'avais parlée dans cet article. Le circuit permettant la réception de messages MIDI par un microcontrôleur nécessite l'utilisation d'un optocoupleur, afin d'éviter les boucles de masse. Plusieurs options sont possibles; j'ai choisi le H11L1 après avoir vu dans un forum de discussion qu'il s'agissait d'un bon choix pour un microcontrôleur utilisant un niveau logique de 3,3 V. Le schéma du circuit recommandé par la MIDI association peut être consulté ici.

  • La broche 1 du H11L1 est branchée à une résistance de 220 Ω, qui est elle-même connectée à la broche 4 du connecteur MIDI (DIN-5).
  • La broche 2 du H11L1 est branchée à la broche 5 du connecteur MIDI (DIN-5).
  • De plus, une diode pour petits signaux 1N914 est branchée entre les broches 1 et 2 du H11L1.
  • La broche 3 du H11L1 n'est pas connectée.
  • La broche 4 du H11L1 est reliée à l'entrée RX (UART) du Raspeberry Pi Pico, ainsi qu'à une résistance pull-up de 470 Ω qui est elle-même reliée à l'alimentation 3,3 V.
  • La broche 5 du H11L1 est reliée à la masse GND.
  • La broche 6 du H11L1 est reliée à l'alimentation 3,3 V.
(Attention, si l'optocoupleur que vous utilisez n'est pas un H11L1, son brochage pourrait être différent.)

Un câble MIDI relie le connecteur femelle DIN-5 à la sortie MIDI OUT du clavier musical alors que, du côté Raspberry Pi Pico, l'information arrivera par la broche GP5 du Raspberry Pi Pico. 

Numéro des broches du connecteur DIN-5


Script #1: affichage brut des données reçues

Ce premier exemple est volontairement minimaliste: il se contente d'afficher dans la console de Thonny tous les messages MIDI reçus en provenance du clavier musical.

La communication UART est d'abord initialisée (ligne #12). Nous utilisons le bus UART 1, qui est associé aux broches GP4 (TX) et GP5 (RX). Dans ce cas, seule la broche de réception (GP5) sera utile. La vitesse de la communication est réglée à 31 250 bauds, tel que requis par le protocole MIDI.

Ensuite, si nous recevons un message UART, nous l'affichons en format hexadécimal.

Lors de la mise à l'essai d'une première version de ce script, j'ai eu la surprise de voir s'afficher à l'écran une quantité effarante de données alors que je n'avais encore appuyé sur aucune des touches du clavier musical. Les valeurs affichées étaient 0xF8 et 0xFE qui correspondent respectivement à "Timing Clock" et "Active Sensing".  Les messages de type "Timing Clock" servent à synchroniser deux instruments MIDI pour qu'ils soient au même tempo, alors que les messages "Active Sensing" permettent de vérifier constamment qu'un appareil MIDI est toujours branché et actif. La ligne #17 du script désactive donc l'affichage de tous ces messages de type "System Real Time" pour éviter que les données générées par les actions du musicien soient noyées dans un océan de données répétitives inutiles. (Certains claviers MIDI n'émettent pas ces messages)

Affichage de messages "System Real Time"

Voici donc le script en micropython:

-

-

Voyons ce qui est affiché à l'écran lorsque j'appuie sur la note "Do2" de mon clavier:

Appui sur la touche Do2 du clavier musical

 

Trois octets sont envoyées par le clavier:

Le nombre hexadécimal 0x90 représente un message "Note On" sur le canal 1. Il indique que nous avons appuyé sur une touche du clavier. Il existe 16 canaux, qui sont officiellement numérotés de 1 à 16, mais nous les numérotons de 0 à 15 dans un programme. Le nombre hexadécimal 0x91 aurait signifié un message "Note On" sur le canal 2, le nombre hexadécimal 0x92 aurait signifié un message "Note On" sur le canal 3, et ainsi de suite jusqu'à 0x9F, qui représente un "Note On" sur le canal 16.

Un message "Note On" est toujours suivi de deux octets supplémentaires: un nombre qui représente le numéro de la note jouée, et un nombre qui représente la vélocité avec laquelle la touche a été enfoncée.

Ici, nous pouvons constater que j'ai joué la note numéro 0x24 en hexadécimal (ou 36 en décimal), qui correspond à un Do du 2e octave (cette page, qui énumère la signification des différents numéros de notes, peut s'avérer bien utile). Finalement,la vélocité de cette note était de 0x4d (ce qui correspond à 77 en décimal). Ce nombre serait plus grand si j'avais appuyé plus fort sur la touche du clavier.

Voyons maintenant ce qui s'affiche lorsque je relâche la touche de clavier que j'avais enfoncée.

Relâchement de la touche Do2 du clavier musical
 

Lorsque nous relâchons une touche, un instrument MIDI doit générer un message "Note Off". Certains instruments émettent un véritable message Note Off qui correspond à 0x80. D'autres émettent plutôt un "Note On" avec une vélocité de 0. C'est ce que vous pouvez constater sur la saisie d'écran ci-dessus: en relâchant la touche Do2 que j'avais enfoncée, le clavier musical a émis le message 0x90 (Note On), suivi du numéro de la note correspondant à la touche relâchée (0x24), et d'une vélocité nulle (0x0).

La saisie d'écran ci-dessous, réalisée avec un clavier différent, montre les données reçues lorsque la touche "Do2" est d'abord appuyée, puis ensuite relâchée (ce clavier émet un véritable message "Note Off" de 0x80).

Do2 enfoncée, puis relâchée, sur un autre clavier

 

Script #2: Interprétation des messages reçus

Dans ce deuxième exemple, je fais un effort pour présenter les données d'une façon plus compréhensible pour un être humain. Pour simplifier les choses, je me limite aux messages de type Note On ou Note Off reçues sur le canal 1 (0x80 ou 0x90). Je n'afficherai donc pas de message de type "program change", "pitch bend", etc.): le script ne réagit qu'aux touches enfoncées ou relâchées.

Cette fois, le numéro de la note s'affiche en valeur décimale, et le script détermine s'il s'agit d'un do, ou d'un sol, etc. 

La vélocité s'affiche également en valeur décimale, et le script indique si la touche a été enfoncée (note On) ou relâchée.


-

-

Et ensuite?

Maintenant que vous maîtrisez les bases de la réception d'un message MIDI, vous pourriez transformer votre Raspberry Pi Pico en un mini synthétiseur; pour ce faire, vous pourriez vous référer à cet article sur la production d'un son au moyen du Raspberry Pi Pico


À lire également:


Yves Pelletier



mardi 5 septembre 2023

MIDI OUT avec le Raspberry Pi Pico (Micropython)

Ce projet consiste à utiliser un Raspberry Pi Pico programmé en Micropython, afin d'envoyer des instructions MIDI à un clavier musical. Le synthétiseur du clavier jouera la musique ayant préalablement été programmée dans le Raspberry Pi Pico.

Circuit

La norme MIDI (Musical Instrument Digital Interface) a été mise au point au début des années 1980 afin de permettre la communication entre divers instruments de musique électronique.

À l'origine, tous les appareils communiquaient en utilisant un niveau logique de 5 V mais puisque le Raspberry Pi Pico (comme la majorité des microcontrôleurs actuels) utilise plutôt un niveau logique de 3,3 V, nous utiliserons le circuit que je vous ai présenté dans le récent article intitulé Fabrication d'un module MIDI (IN et OUT) pour microcontrôleur 3,3 V.

Le circuit est très simple et peut être rapidement monté sur une breadboard. Le seul composant "spécialisé" étant un connecteur DIN-5 femelle dans lequel sera inséré le câble MIDI branché au clavier­. La numérotation des broches de ce connecteur est présenté sur la photographie ci-dessous.

  • Une résistance de 10 Ω est insérée entre la broche GP4 du Raspberry Pi Pico et la broche numéro 5 du connecteur DIN-5 femelle.
  • La broche 2 du connecteur DIN-5 femelle est branchée à une des broches GND du Raspberry Pi Pico.
  • Une résistance de 33 Ω est insérée entre la broche 4 du connecteur DIN-5 femelle et la sortie 3,3 V du Raspberry Pi Pico.  Attention: on recommande une résistance de 0,5 W.  (Pour cette raison, j'ai plutôt utilisé deux résistances de 68 Ω en parallèle)­.

Ce circuit est inspiré des recommandations de la MIDI Association.

Un câble MIDI est inséré dans le connecteur DIN5, et l'autre extrémité du câble est inséré dans le jack MIDI IN du clavier musical.

Script en Micropython #1

Commençons par présenter un script très simple, en Micropython, pour illustrer la procédure: il se contente de ne jouer qu'une seule note.

Les spécifications du protocole MIDI imposent une communication série à une vitesse de 31 250 bauds. Cette vitesse est réglée au début du programme (ligne #15) lorsque nous initialisons le bus UART #1 du Raspberry Pi, qui est lié aux broches GP4 (TX) et GP5 (RX). Dans ce projet, nous n'utilisons que la broche GP4, qui sert à la transmission des données (GP5 serait utile si nous devions recevoir des données, ce qui n'est pas le cas ici).

À la ligne #18, nous réglons le "programme" du synthétiseur, c'est à dire le timbre qui sera utilisé. La norme "General MIDI" définit 128 timbres correspondant à l'imitation d'un instrument de musique. Par exemple, le timbre numéro 57 correspond à un son de trompette. De plus, vous disposez de 16 canaux, chacun de ces canaux pouvant être réglé à son propre timbre (sauf le canal 10, qui est réservé aux percussions).

À la ligne #18, donc, nous assignons un son de trompette au canal 1.  Pour ce faire, nous envoyons un premier octet qui envoie l'instruction "program change" ainsi que le numéro du canal auquel il faut assigner ce timbre:

  • Le nombre hexadécimal C0 modifie le timbre du canal 1
  • Le nombre hexadécimal C1 modifie le timbre du canal 2
  • Le nombre hexadécimal C2 modifie le timbre du canal 3
  • ...
  • Le nombre hexadécimal CF change le timbre du canal 16

Vous l'avez peut-être remarqué: la numérotation officielle des canaux, qui s'adresse aux musiciens plutôt qu'aux programmeurs, va du canal 1 au canal 16 mais dans un programme, nous utilisons les numéros 0 à 15...

Cette instruction est suivie d'un deuxième octet (ligne #19) qui contient le numéro du timbre. Ici encore, les timbres sont officiellement numérotés de 1 à 128 mais nos programmes utilisent une numérotation de 0 à 127. Pour cette raison, nous envoyons "56" parce que la trompette est l'instrument numéro 57!

Pour jouer une note, nous envoyons un message de type "Note On":

  • Le nombre hexadécimal 90 joue une note dans le canal 1
  • Le nombre hexadécimal 91  joue une note dans le canal 2
  • Le nombre hexadécimal 92  joue une note dans le canal 3
  • ...
  • Le nombre hexadécimal 9F  joue une note dans le canal 16

À la ligne #22, nous avons donc envoyé l'instruction 90, en hexadécimal, afin de jouer une note dans le canal 1. 

Il faut aussi lui indiquer quelle note il faut jouer (ligne #23). Le Do4, par exemple, correspond au numéro 60 (voir cette page pour tous les numéros de notes).

Ensuite (ligne #24), il faut envoyer un troisième octet qui indique la vélocité de la note. Plus ce nombre est élevé, plus le volume du son est élevé. 127 représente le maximum.

Nous maintenons ensuite cette note pendant 2 secondes (ligne #26).

En MIDI, il faut envoyer une instruction qui demande explicitement de cesser de jouer la note: c'est le message "note off", qui est très similaire  au message "note on", sauf qu'on remplace le 9 par un 8:

  • Le nombre hexadécimal 80 interrompt une note dans le canal 1
  • Le nombre hexadécimal 81  interrompt une note dans le canal 2
  • Le nombre hexadécimal 82  interrompt une note dans le canal 3
  • ...
  • Le nombre hexadécimal 8F  interrompt une note dans le canal 16

La ligne #29 envoie donc un message "note off" au canal 1.

Il faut ensuite spécifier le numéro de la note qu'on désire interrompre, et il est bien sûr important d'utiliser le même numéro que celui a servi dans le message "note on"! À la ligne #30, nous interrompons la note numéro 60, qui est le do4 qui joue depuis maintenant 2 secondes.

Nous spécifions finalement la vélocité, qui est typiquement nulle pour un message de type "note off". (ligne #31).  (Notez qu'un message "note on" de vélocité nulle aurait eu le même effet qu'on message "note off".)

-

-

Script en Micropython #2

Ce deuxième script joue une mélodie à la basse dans le canal #1, tout en jouant de la batterie dans le canal #10. Ça joue en boucle jusqu'à l'interruption du programme.

-

-

Bibliothèque Micropython-midi-library

Pour des applications plus sérieuses, vous serez peut-être intéressés par la Micropython-midi-library de sensai7. 


À lire également


Yves Pelletier

lundi 4 septembre 2023

Fabrication d'un module MIDI (IN et OUT) pour microcontrôleur 3,3 V

Il y a quelques années, j'avais fabriqué un module MIDI permettant de brancher un clavier MIDI à une carte Arduino, qui m'a été bien utile dans un grand nombre de petits projets musicaux. Ce circuit, toutefois, est conçu pour une logique à 5 V alors que, de nos jours, mes intérêts s'orientent surtout vers des microcontrôleurs qui fonctionnent avec une logique à 3,3 V. J'ai donc fabriqué une nouvelle interface MIDI, qui me permettra de faire de nouvelles expérimentations musicales avec, entre autres, mon Raspberry Pi Pico!

Ce nouveau module comporte un circuit "MIDI OUT" qui permettra à un microcontrôleur d'envoyer des instructions MIDI par une sortie UART, ainsi qu'un circuit "MIDI IN" qui permettra à un microcontrôleur de recevoir des messages MIDI par une entrée UART.

Évidemment, si vous préférez, vous pouvez trouver en lignes des modules MIDI déjà prêts à être utilisés (parfois munis d'un commutateur permettant de sélectionner une logique à 5 V ou à 3,3 V).

Connecteurs MIDI

Mon module est muni de deux connecteurs DIN 5 femelles (communément appelées "connecteurs MIDI). La numérotation des broches de ces connecteurs est parfois ambigüe, d'une part parce qu'elles ne sont pas numérotées dans l'ordre, et d'autre part parce que les schémas n'indiquent pas toujours clairement s'ils montrent le connecteur mâle ou le connecteur femelle. La photo ci-dessous montre le numéro des broches d'une façon qui me semble claire.


Connections avec le microcontrôleur

Pour faire la liaison avec le microcontrôleur, notre module MIDI doit comporter quatre connecteurs:

  • Connexion avec l'alimentation 3,3 V (sortie 3,3 V du microcontrôleur)
  • Connexion avec la masse (GND) du microcontrôleur
  • Connexion avec la broche RX (UART) du microcontrôleur
  • Connexion avec la broche TX (UART) du microcontrôleur
Bien entendu, vous utilisez le type de connecteur (mâle ou femelle) qui répond le mieux à vos besoins.


Circuits

Nul besoin de réinventer la roue: la MIDI Association présente sur son site officiel les schémas des circuits recommandés.

Le circuit "MIDI OUT" est le plus simple des deux circuits, puisqu'il ne nécessite rien d'autre que deux résistances.

  • Une résistance de 10 Ω (1/4 W) est insérée entre la broche 5 du connecteur MIDI (DIN-5) et la broche TX (UART) du microcontrôleur.
  • La broche 2 du connecteur MIDI (DIN-5) est directement connectée à la masse GND.
  • Une résistance de 33 Ω (1/2 W) est insérée entre la broche 4 du connecteur MIDI (DIN-5) et la sortie 3,3 V du microcontrôleur. Puisque je n'avais pas de résistance de 1/2 W sous la main, j'ai plutôt utilisé deux résistances de 68 Ω (1/4 W) en parallèle.
  • Les broches 1 et 3 du connecteur MIDI (DIN-5) ne sont pas connectées.

Circuit MIDI OUT

Le circuit "MIDI IN" n'est pas beaucoup plus complexe, mais il nécessite des composants un peu plus variés: un optocoupleur, une diode et deux résistances.

L'optocoupleur doit pouvoir réagir à une tension de 3,3 V, et avoir un temps de réaction suffisamment court. J'ai utilisé un H11L1. 


Cette fois, seules les broches 4 et 5 du connecteur MIDI (DIN-5) sont utilisées. Les broches 1, 2 et 3 ne sont pas connectées.

  • La broche 1 du H11L1 est branchée à une résistance de 220 Ω, qui est elle-même connectée à la broche 4 du connecteur MIDI (DIN-5).
  • La broche 2 du H11L1 est branchée à la broche 5 du connecteur MIDI (DIN-5).
  • De plus, une diode pour petits signaux 1N914 est branchée entre les broches 1 et 2 du H11L1.
  • La broche 3 du H11L1 n'est pas connectée.
  • La broche 4 du H11L1 est reliée à l'entrée RX (UART) du microcontrôleur, ainsi qu'à une résistance pull-up de 470 Ω qui est elle-même reliée à l'alimentation 3,3 V.
  • La broche 5 du H11L1 est reliée à la masse GND.
  • La broche 6 du H11L1 est reliée à l'alimentation 3,3 V.
(Attention, si l'optocoupleur que vous utilisez n'est pas un H11L1, son brochage pourrait être différent.)

Circuit MIDI IN

À lire aussi:

Yves Pelletier