Did you know you can use a QT Py RP2040 as a USB to Serial MIDI converter? The QT Py RP2040, running CircuitPython code, receives MIDI messages over USB and then sends the messages out over serial UART. You can build small add-on boards, or friends, for TRS-A, TRS-B and DIN-5 MIDI out circuits that plug directly into the QT Py RP2040.

This concept was inspired by Sandy Macdonald on Twitter. It makes for a compact and simple solution for interfacing hardware MIDI devices with USB.

The MIDI friend breakouts plug directly into a QT Py RP2040 with socket headers.

Versions for TRS-A, TRS-B and DIN-5 MIDI connections are shown in this guide. You can choose which one to build depending on your hardware MIDI device.

TRS-A or TRS-B?

If you aren't sure which type of TRS connection your TRS MIDI device uses, you can search for it on minimidi.world to see if it uses TRS-A or TRS-B. TRS-A is currently the MIDI standard, but many devices out there have TRS-B sockets. The difference is that the 3V and TX serial connections are swapped on the audio jack.

Prerequisite Guides and Resources

Parts

Video of hand holding a QT Py PCB in their hand. An LED glows rainbow colors.
What a cutie pie! Or is it... a QT Py? This diminutive dev board comes with one of our new favorite chip, the RP2040. It's been made famous in the new
Out of Stock
Breadboard-Friendly 3.5mm Stereo Headphone Jack
Pipe audio in or out of your project with this very handy breadboard-friendly audio jack. It's a stereo jack with disconnect-switches on Left and Right channels as well as a center...
$0.95
In Stock
Breadboard-friendly MIDI Jack
To celebrate the 30th Anniversary of the invention of MIDI we're carrying these handy 5-pin MIDI jacks. They're what you see on the back of nearly every synthesizer and drum...
$1.75
In Stock
Angled shot of single Bakelite Universal Perfboard Plate.
Make your next project as you imagine it with prototyping perfboards that can easily be cut with scissors like these Bakelite Universal Perfboard Plates!We...
$4.95
In Stock
Very strong looking scissors with comfy grip
Save your scissors! Instead of using your nice shears (and dulling them) or wire cutters (not right for the job) - use these super scissors. They're meant for engineering/maker...
$14.95
In Stock
Angled shot of coiled pink and purple USB cable with USB A and USB C connectors.
This cable is not only super-fashionable, with a woven pink and purple Blinka-like pattern, it's also made for USB C for our modernized breakout boards, Feathers, and...
$2.95
In Stock
1 x 10Ω Resistor
10Ω resistor for TX connection
1 x 30Ω Resistor
30Ω resistor for 3.3V connection

DIN-5

Data

  • Board TX to 10Ω resistor
  • 10Ω resistor to DIN-5 pin 5 (current sink)

Ground

  • Board GND to DIN-5 pin 2 (shield)

Power

  • Board 3V to 30Ω resistor
  • 30Ω resistor to DIN-5 pin 4 (current source)

TRS-A

Data

  • Board TX to 10Ω resistor
  • 10Ω resistor to TRS pin 5 (ring)

Ground

  • Board GND to TRS pin 1 (sleeve)

Power

  • Board 3V to 30Ω resistor
  • 30Ω resistor to TRS pin 2 (tip)

TRS-B

Data

  • Board TX to 10Ω resistor
  • 10Ω resistor to TRS pin 2 (tip)

Ground

  • Board GND to TRS pin 1 (sleeve)

Power

  • Board 3V to 30Ω resistor
  • 30Ω resistor to TRS pin 5 (ring)

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

CircuitPython Quickstart

Follow this step-by-step to quickly get CircuitPython running on your board.

Click the link above to download the latest CircuitPython UF2 file.

Save it wherever is convenient for you.

To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in blue above). Continue to hold the BOOT/BOOTSEL button until the RPI-RP2 drive appears!

If the drive does not appear, release all the buttons, and then repeat the process above.

You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.

A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.

You will see a new disk drive appear called RPI-RP2.

 

Drag the adafruit_circuitpython_etc.uf2 file to RPI-RP2.

The RPI-RP2 drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

Safe Mode

You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.

Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.

Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.

Entering Safe Mode in CircuitPython 6.x

This section explains entering safe mode on CircuitPython 6.x.

To enter safe mode when using CircuitPython 6.x, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 700ms. On some boards, the onboard status LED (highlighted in green above) will turn solid yellow during this time. If you press reset during that 700ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)

Entering Safe Mode in CircuitPython 7.x

This section explains entering safe mode on CircuitPython 7.x.

To enter safe mode when using CircuitPython 7.x, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)

In Safe Mode

Once you've entered safe mode successfully in CircuitPython 6.x, the LED will pulse yellow.

If you successfully enter safe mode on CircuitPython 7.x, the LED will intermittently blink yellow three times.

If you connect to the serial console, you'll find the following message.

Auto-reload is off.
Running in safe mode! Not running saved code.

CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.

You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.

Flash Resetting UF2

If your board ever gets into a really weird state and doesn't even show up as a disk drive when installing CircuitPython, try loading this 'nuke' UF2 which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.

Once you've finished setting up your QT Py RP2040 with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
# SPDX-License-Identifier: MIT

import board
import busio
import usb_midi
import adafruit_midi
# pylint: disable=unused-import
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.program_change import ProgramChange

#  uart setup
uart = busio.UART(board.TX, board.RX, baudrate=31250)
#  midi channel setup
midi_in_channel = 1
midi_out_channel = 1
#  midi setup
#  UART is setup as the input
#  USB is setup as the output
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0],
    midi_out=uart,
    in_channel=(midi_in_channel - 1),
    out_channel=(midi_out_channel - 1),
    debug=False,
)

while True:
    #  receive MIDI message over USB
    msg = midi.receive()
    #  if a message is received...
    if msg is not None:
        #  send that message over UART
        midi.send(msg)
        #  print message to REPL for debugging
        print(msg)

Upload the Code and Libraries to the QT Py RP2040

After downloading the Project Bundle, plug your QT Py RP2040 into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the QT Py RP2040's CIRCUITPY drive. 

  • lib folder
  • code.py

Your QT Py RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

circuitpy

How the CircuitPython Code Works

The code begins by importing the libraries. All of the MIDI message libraries are imported so that any incoming MIDI message type will be recognized.

import usb_midi
import adafruit_midi
import board
import busio
import time
from adafruit_midi.control_change import ControlChange
from adafruit_midi.pitch_bend import PitchBend
from adafruit_midi.note_off import NoteOff
from adafruit_midi.note_on import NoteOn
from adafruit_midi.program_change import ProgramChange

This is followed by the MIDI setup. The QT Py RP2040's USB port is setup as the MIDI input and the UART pin is setup as the MIDI output. This means that MIDI messages are received over USB and sent out over UART.

#  uart setup
uart = busio.UART(board.TX, board.RX, baudrate=31250)
#  midi channel setup
midi_in_channel = 1
midi_out_channel = 1
#  midi setup
#  USB is setup as the input
#  UART is setup as the output
midi = adafruit_midi.MIDI(
    midi_in=usb_midi.ports[0],
    midi_out=uart,
    in_channel=(midi_in_channel - 1),
    out_channel=(midi_out_channel - 1),
    debug=False,
)

In the loop, if a MIDI message is received it is stored as msg. That msg is then sent out over UART exactly as it is received. This allows for direct USB to UART MIDI communication. 

while True:
    msg = midi.receive()
    if msg is not None:
        midi.send(msg)
        print(msg)

Cut the Bakelite Perfboard

You will need a piece of Bakelite perfboard that is 10 holes long by 10 holes wide. Use the white divider squares as a guide and mark your cut with a marker.

Use a pair of Super Scissors to cut the perfboard on the lines that you marked.

Proper eye protection must be worn when cutting perfboard to avoid injury. Also cut perfboard can have sharp edges. Please be careful.

You'll need one 10 hole by 10 hole piece of perfboard for every MIDI friend. The piece will be slightly larger than the QT Py RP2040 to allow for enough room for the headers and TRS or DIN-5 jack.

Solder the QT Py RP2040's Headers

Cut two strips of socket headers that are each seven pins long.

Proper eye protection must be worn when cutting header pieces to avoid injury. Also cut headers might have sharp edges. Please be careful.

Solder the socket headers to the QT Py RP2040 so that the sockets are on the USB side. You may want to use a QT Py board with plug headers as a soldering jig.

Solder the MIDI Friend's Headers

Cut two strips of plug headers that are seven pins long. Plug them into the QT Py RP2040's socket headers as a soldering jig.

Place the piece of perfboard with its solder pads facing up. Insert the plug headers into the perfboard so that their tips are visible, as shown in the picture.

Since the Bakelite perfboard only has solder pads on one side, you will need to solder the headers at an angle from the side. Solder the headers in place.

Once your headers are soldered you can solder a TRS-A, TRS-B or DIN-5 connector to the board.

These breakouts are assembled using point to point soldering, which involves bridging solder connections to complete signal paths. Make sure that no pins become bridged accidentally.

DIN-5 Jack

Insert the DIN-5 jack into the breakout board. Place the five connection pins in the center of the board. Solder the DIN-5 jack in place.

Data Signal

Insert a 10Ω resistor between the TX header pin and the DIN-5 jack's pin 5.

Solder the resistor in place. Connect the resistor to the pins by bridging the solder connections.

GND Signal

Cut and strip a piece of wire for the ground connection.

Insert the wire between the DIN-5's pin 2 and the GND header.

Solder the wire in place. Connect the wire to the pins by bridging the solder connections.

3V Signal

Insert a 30Ω resistor between the 3V header pin and the DIN-5 jack's pin 4.

Solder the resistor in place. Connect the resistor to the DIN-5 jack's pin 4 by bridging the solder connections.

Bend the remaining resistor leg so that it is next to the 3V header pin. Connect the resistor to 3V by bridging the solder connections.

And that completes your DIN-5 MIDI friend!

These breakouts are assembled using point to point soldering, which involves bridging solder connections to complete signal paths. Make sure that no pins become bridged accidentally.

TRS Jack

Insert the TRS jack into the breakout board. Solder the TRS jack in place.

Data Signal

Insert a 10Ω resistor next to the TRS jack's pin 5 (tip).

Solder the resistor in place. Connect the resistor to the TRS jack's pin 5 by bridging the solder connections.

Cut and splice a piece of wire to connect the resistor to the TX header pin. Insert the wire onto the breakout board and solder it in place. 

Complete the signal connection by bridging the wire's solder points to the TX pin and resistor.

GND Signal

Cut and strip a piece of wire for the ground connection.

Insert the wire between the TRS jack's pin 1 (sleeve) and the GND header.

Solder the wire in place. Connect the wire to the pins by bridging the solder connections.

3V Signal

Insert a 30Ω resistor next to the TRS jack's pin 2 (ring).

Solder the resistor in place. Connect the resistor to the TRS jack's pin 2 by bridging the solder connections.

Cut and splice a piece of wire to connect the resistor to the 3V header pin. Insert the wire onto the breakout board and solder it in place. 

Complete the signal connection by bridging the wire's solder points to the 3V pin and resistor.

And that completes your TRS-A MIDI friend!

These breakouts are assembled using point to point soldering, which involves bridging solder connections to complete signal paths. Make sure that no pins become bridged accidentally.

TRS Jack

Insert the TRS jack into the breakout board. Solder the TRS jack in place.

Data Signal

Insert a 10Ω resistor between the TX header pin and the TRS jack's pin 2 (ring).

Solder the resistor in place. Connect the resistor to the pins by bridging the solder connections.

GND Signal

Cut and strip a piece of wire for the ground connection.

Insert the wire between the TRS jack's pin 1 (sleeve) and the GND header.

Solder the wire in place. Connect the wire to the pins by bridging the solder connections.

3V Signal

Insert a 30Ω resistor between the 3V header pin and the TRS jack's pin 5 (tip).

Solder the resistor in place. Connect the resistor to the pins by bridging the solder connections.

And that completes your TRS-B MIDI friend!

You can use the QT Py RP2040 with any application that supports USB MIDI, such as a USB MIDI host or a software DAW (digital audio workstation).

Plug your selected MIDI friend breakout into the QT Py RP2040 before plugging in any cables. Then, connect the QT Py RP2040 using a USB-C cable. 

If you're using the QT Py RP2040 with a DAW, you'll want to setup a MIDI track and set the CircuitPython Audio device as a MIDI output. This will send the MIDI track out to the QT Py RP2040 so that your TRS or DIN-5 MIDI device can receive the data.

Connect your MIDI friend breakout to the MIDI input jack on your hardware device.

If you're using a TRS MIDI device, be sure to connect your device to the MIDI friend breakout with a stereo audio cable. If you aren't sure whether your hardware uses TRS-A or TRS-B, you can search for it on minimidi.world.

This guide was first published on Apr 26, 2022. It was last updated on 2022-04-26 14:57:46 -0400.