Simple DIY Electronic Music Projects<p><strong>CircuitPython USB to Serial MIDI Router</strong></p><p>I’ve indirectly used USB and Serial MIDI with CircuitPython a few times now, but haven’t explicitly shown how to use it as a simple USB (device) to serial MIDI converter. This project shows how to do that. Any CircuitPython device should be usable like this, but I’ve used this as an excuse to do something with the Seeedstudio Seeeduino XIAO board.</p><p><em><strong>Warning!</strong> I strongly recommend using old or second hand equipment for your experiments. I am not responsible for any damage to expensive instruments!</em></p><p>These are the key tutorials for the main concepts used in this project:</p><ul><li><a href="https://wiki.seeedstudio.com/Seeeduino-XIAO-CircuitPython/" rel="nofollow noopener" target="_blank">Seeeduino XIAO CircuitPython</a></li><li><a href="https://learn.adafruit.com/cpx-midi-controller" rel="nofollow noopener" target="_blank">Circuit Playground Express USB MIDI Controller and Synthesizer</a></li></ul><p>If you are new to microcontrollers, see the <a href="https://diyelectromusic.wordpress.com/getting-started/" rel="nofollow noopener" target="_blank">Getting Started</a> pages.</p><p><strong>Parts list</strong></p><ul><li>CircuitPython device (e.g. <a href="https://www.raspberrypi.com/products/raspberry-pi-pico/" rel="nofollow noopener" target="_blank">Raspberry Pi Pico</a>, <a href="https://www.adafruit.com/product/3500" rel="nofollow noopener" target="_blank">Adafruit Trinket M0</a>, <a href="https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html" rel="nofollow noopener" target="_blank">Seeeduino XIAO</a>, etc)</li><li>A 3.3V compatible MIDI module (e.g. one of the <a href="https://diyelectromusic.wordpress.com/2021/03/16/diy-midi-interfaces/" rel="nofollow noopener" target="_blank">DIY MIDI Interfaces</a> or a 3.3V <a href="https://diyelectromusic.wordpress.com/2020/11/30/ready-made-midi-modules/" rel="nofollow noopener" target="_blank">Ready-Made MIDI Module</a>)</li><li>Breadboard and jumper wires</li></ul><p><strong>The Circuit</strong></p><p>If you are using a Raspberry Pi then the circuit is one I’ve used <a href="https://diyelectromusic.wordpress.com/2021/02/15/midi-in-for-3-3v-microcontrollers/" rel="nofollow noopener" target="_blank">several times</a> already. Connect up your 3V3 compatible MIDI module to GND, 3V3, RX and TX.</p><p>If you are using a Trinket M0 then there is a <a href="https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/pinouts" rel="nofollow noopener" target="_blank">really good learning guide on the Adafruit site</a> that will get you going – again you’ll need the same GND, 3V3, RX and TX pins.</p><p>In my case, I wanted an excuse to do something with a <a href="https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html" rel="nofollow noopener" target="_blank">Seeedstudio Seeeduino XIAO module</a>. This is a SAMD21G based module with a USB-C connector, and would need to be connected up as follows.</p><p>The general idea is that the CircuitPython device will connect to a PC (or other USB host) as a USB MIDI device and forward any MIDI traffic between the USB MIDI link and a connected serial MIDI module.</p><p><strong>The Code</strong></p><p>The basic idea is relatively straightforward once your device is <a href="https://diyelectromusic.wordpress.com/2021/01/26/midi-circuitpython-cpx-and-pi-pico/" rel="nofollow noopener" target="_blank">up and running with Circuitpython</a> itself (see the Adafruit guides for help to get this far!):</p><pre>Set up the USB MIDI deviceSet up the serial MIDI devicewhile: IF there is a USB MIDI IN message THEN Send it out on the serial MIDI OUT port IF there is a serial MIDI IN message THEN Send it out on the USB MIDI OUT port</pre><p>The only slight quirk is that I try to filter out unrecognised MIDI messages to limit the forwarded traffic, but if you haven’t imported the adafruit_midi representation of a MIDI message, then the code will not recognise it! So I need to pull in the various MIDI message representations at the start of the file.</p><p>Not being a python person myself really, I may well be missing something and there might be a more elegant way to do this, but I have to say I’m not really a fan of how MIDI is implemented in CircuitPython as it feels too hidden away behind “clever layers” for my liking. But having said that, there really is no easier way (at present) for making a USB MIDI device than CircuitPython.</p><p>The code also supports flashing an LED on reception of a MIDI event. For the XIAO this looks like the following:</p><pre>led = digitalio.DigitalInOut(board.D13)led.direction = digitalio.Direction.OUTPUTled.value = Truedef ledOn(): led.value = Falsedef ledOff(): led.value = True</pre><p>With the XIAO the LED is on when led.value = False. For the Raspberry Pi Pico, it would be different again, something like the following (untested, but pasted in from my other code):</p><pre>led = digitalio.DigitalInOut(board.GP25)led.direction = digitalio.Direction.OUTPUTdef ledOn(): led.value = Truedef ledOff(): led.value = False</pre><p>Some boards support the Python/CircuitPython “built in LED” identifier – you might be able to get away with using board.LED above, but the True/False logic still needs setting up correctly for your board. Some boards are now using board.LED_INVERTED too, so just see what works.</p><p>One way to see what is supported is to do the following in the REPL shell when connected to the board:</p><pre>>>> import board<br>>>> dir (board)</pre><p>Also, whilst the XIAO and other boards have board.TX and board.RX defined for the default serial port, the Raspberry Pi Pico does not, so the code to initialise the serial MIDI will also have to be changed to look more like the following for the Pico (this is to use UART 0 on GP0 and GP1).</p><pre>uart = busio.UART(tx=board.GP0, rx=board.GP1, baudrate=31250, timeout=0.001)</pre><p>The original was:</p><pre>uart = busio.UART(tx=board.TX, rx=board.RX, baudrate=31250, timeout=0.001)</pre><p><a href="https://github.com/diyelectromusic/sdemp/blob/master/src/SDEMP/CircuitPython/USBUARTMidiRouter.py" rel="nofollow noopener" target="_blank">Find the XIAO version on GitHub here</a>.</p><p><strong>Closing Thoughts</strong></p><p>As always, I continue my love/hate relationship with CircuitPython (and Python more generally), but I can’t deny, this is still probably the easiest way to get a USB MIDI device to serial MIDI converter up and running!</p><p>Now USB MIDI Host… well that is another story…</p><p>Kevin</p><p><a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/circuitpython/" target="_blank">#circuitpython</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/midi/" target="_blank">#midi</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/raspberry-pi-pico/" target="_blank">#raspberryPiPico</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/trinket/" target="_blank">#trinket</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/usb-midi/" target="_blank">#usbMidi</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://diyelectromusic.com/tag/xiao/" target="_blank">#xiao</a></p>