Raspberry Pi Pico Multi MIDI Router – Part 3

The obviously missing part of my Raspberry Pi Pico Multi MIDI Router is the use of USB MIDI.  The Pico should support both USB host and device functionality, but I think you need to get into the C software development kit to do that properly, something I’ve not looked at yet.

One of the easiest ways right now to get USB MIDI device support on a Pico is to use CircuitPython, but I’ve not had much success so far with PIO in CircuitPython.  So I have the requirement that I want to use Micropython for PIO support, but need CircuitPython for USB MIDI device support.  Neither will support USB MIDI host functionality.

This project is one enhancement that adds both by adding two “USB MIDI co-processors” to the Pico.

IMG_6122

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

These are the key tutorials for the main concepts used in this project:

If you are new to microcontrollers, see the Getting Started pages.

Parts list

Introduction

The core principle is to use an Adafruit Trinket M0 as a “USB MIDI Host Co-processor” and a Seeeduino XIAO as a “USB MIDI Device Co-processor” and get them to communicate with the Raspberry Pi Pico using the two UART MIDI channels.

This can all be done using jumper wires and the original breadboard version of the Pico router, but I’m opting to add them to my proto-board version, as described below.

Trinket M0 USB MIDI Host Co-Processor

PiPicoMultiMIDIv3_bb

The original proto-board design has plenty of space to squeeze in an Adafruit Trinket M0 as shown above.  To function it needs just four connections:

  • USB to 5V
  • GND
  • D4 (TX) to the Pico RX
  • D3 (RX) to the Pico TX

5V is required as the Trinket will have to provide 5V power over the USB socket to any plugged in USB device, as it is acting as the USB host.  It could connect to either UART 0 or UART 1 on the Pico, but the pins align most simply on my router board if UART 1 is used, so that is how I’ve done it.

Here are some photos of how I’ve added pin header sockets to allow the Trinket to be plugged in.

Some of the unused pins from the Trinket’s two headers were removed to prevent interference with the wires that already exist on the rear of the protoboard.  The addition of the Trinket remains optional after these changes.  Simply removing it leaves UART 1 free to be used via the pin headers once again.

IMG_6110

Finally a USB “on the go” adaptor is required to present a standard USB A socket interface to USB devices.

USB MIDI Host Code

In terms of code, this is using the exact same code as described in my previous project – USB-MIDI to MIDI Revisited.  Key things to note about this code:

  • Although the Trinket M0 is very capable of running CircuitPython, this application is an Arduino C application using the USB Host library ported to the SAMD architecture.  For full details of how to install and use it, see my previous post linked above.
  • This is using the off-the-shelf “MIDIUARTUSBH.ino” application which can be found here: https://github.com/gdsports/usbhostcopro
  • Although the above provides a simple UF2 firmware file that can simply be dragged onto your Trinket’s boot drive, I’m not using that as it sets the serial MIDI baud to a non-standard rate.  I need it to be the standard MIDI 31250 (as described in my previous link).  Of course it is totally possible to update the Pico side of things to the non-standard 115200 to match if you’d rather not get the Arduino IDE involved!
  • The Pico side of things keeps the original Micropython application.  No changes are required (assuming you’re sticking with 31250 MIDI), as it just sees this as a standard MIDI link on UART1.  You just need to put in the appropriate “MIDI routing table” to match what you’d like it to do.  UART 1 is “port 1” in the routing table.

XIAO USB MIDI Device Co-Processor

The idea here is to utilise a CircuitPython board to provide a USB MIDI device to serial gateway and feed that to the other UART of the Pico.  Any CircuitPython device could be used, even another Pico, but I’m using a Seeeduino XIAO as it is pretty small.  An Adafruit QT Py or QT RP2040 would have the same pinout (I believe) and the Pimoroni Tiny RP2040 is only slightly larger.  You could even use a second Trinket M0.  There are many options!

To make mounting the XIAO on top of my Pico easier, I’ve build a simple adaptor proto-board as shown below.  There are two designs but they are both oriented to put the XIAO on TOP of the Pico as installed on my MIDI router.  If you wanted a general “CircuitPython co-processor” for use with a Pico with the headers arranged more “normally” you’d probably need to reverse the connections here somehow so it could go “back to back” with the Pico.

PicoXiaoUSBDevice_bb

This is all a bit of a temporary “fudge” to be honest – just until either Micropython gains USB MIDI device support, or I’m more comfortable with the PIO support in CircuitPython, so there are a few rough edges to this.

Power is an odd one.  The way I’ve wired it up, by connecting the 5V/USB power links, means it can only be powered by one USB link at a time.  If the XIAO’s USB MIDI device is to be used, this means powering it via the XIAO not the Pico.

Recall that the Trinket is connected to UART 1 on the Pico so I’ve connected this to UART 0.

The circuit diagram above shows two variants.  On the left is an adaptor board that allows us to plug in a XIAO using all its headers.  The USB link is left facing the top of the router board.  Here are some photos showing how that comes together.

IMG_6113IMG_6114

The nice thing about doing it this way is that the XIAO is completely removeable.  It doesn’t need to be on the Pico if you don’t want USB device functionality, and the XIAO itself isn’t fixed to the adaptor board so can be used for other projects.  The downside it that it sticks up in the air quite a long way with two sets of headers to accommodate!

On the right of the circuit is an alternative design that solders the XIAO directly to the adaptor board and has the USB link off to the side.  Here are some photos of that one.

IMG_6122

The problem here is that the XIAO is now attached to the protoboard, although only by four pins.  There are a few “gotchas” to watch out for here:

  • I’ve had to be really careful along that top edge – those castellated pads must NOT to connected to the holes on the protoboard that I’m using for the two wires on the underside!
  • Two of the two-way header sockets have had their pins removed so they don’t protrude and create a short with the XIAO.
  • That GND connection is soldered directly onto the pin of the header socket below.

In my view this is a much neater solution, even the XIAO is no longer reusable in quite the same way.

USB MIDI Device Code

In terms of running code, this can simply run the CircuitPython USB to Serial MIDI Router code unchanged.

Closing Thoughts

The way things stand with the CP/MP split and the Pico, I can actually see my way clear to make more use of a “USB MIDI CP Co-Processor” in other projects too.  But eventually hopefully this will go away, giving me back one of the UARTs for a fifth serial MIDI link.

Neither Micropython or CircuitPython supports USB Host functionality though, so the use of a Trinket M0 as a USB Host Co-processor is likely to be more enduring.

Ultimately I should go and have a proper look at the C code support for the Pico and see what options that presents.

But right now, I have a nice “universal” MIDI router that supports:

  • 4x Serial MIDI IN/OUT ports.
  • Optional USB MIDI Device functionality – you can plug it into a computer and use it as a USB MIDI controller.
  • Optional USB MIDI Host functionality – you can plug USB MIDI controllers into it.

It only took the use of three microcontrollers to do it!?  I should also really take a proper look at a Teensy which may well be able to do most of this in one!

If I wanted to extend this to all six serial MIDI ports, then another option might be to use my Raspberry Pi Pico I2C MIDI Interface as the interconnect between the Trinket, XIAO and the Pico.

Kevin

One thought on “Raspberry Pi Pico Multi MIDI Router – Part 3

Leave a comment