XIAO SAMD21, Arduino and MIDI – Part 4

One of the nice things about the SAMD21 based microcontrollers like the XIAO is the embedded USB support.  Whilst it can make the uploading a little, er, interesting, it also allows for the building of USB devices.  This post looks at how to turn the XIAO into a USB MIDI device for more MIDI routing.

Previous parts in this series:

  • Part 1 – Introduction to the XIAO SAMD21 and some projects to get started.
  • Part 2 – Looking at accessing additional serial ports and using them for MIDI.
  • Part 3 – Mozzi FM synthesis using the DAC on the XIAO.
  • Part 4 – USB MIDI on the XIAO.
  • Part 5 – XIAO as a USB MIDI Host.
  • Part 6 – MIDI control using the expansion board.
  • Part 7 – XIAO Expansion I2C MIDI control.
  • Part 8 – XIAO MIDI PCBs.

Note: Although I’ve had vouchers from Seeed Studio for their Fusion service to support the manufacturing of some of my PCBs, there is no support for my use of the XIAO boards for this post.  I bought these a while ago, bought my own expansion board more recently, and just wanted a bit of a play to see what I could come up with.

IMG_7059

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

  • Seeed Studio XIAO SAMD21.
  • Up to three 3V3 compatible MIDI module, for example one of the Ready-Made MIDI Modules or DIY MIDI Interfaces.
  • MDI devices as required to source or sink MIDI.
  • Breadboard and jumper wires.

See the notes in part 1 about uploading to the XIAO and what to do if there are issues!

The Circuit

XIAO-MIDI-Tri-USB

This is effectively the same circuit from part 2, but now the USB link is also an active MIDI link.  As mentioned previously, the three MIDI modules are connected as shown below.

XIAO-MIDI-SERCOM

With the MIDI modules connected as follows:

  • MIDI IN/OUT 1 to SERCOM 4 (A6/A7)
  • MIDI IN/OUT 2 to SERCOM 2 (A4/A5)
  • MIDI IN/OUT 3 to SERCOM 0 (A10/A9)

The Code

There are two ways to get USB working on the XIAO. It can support the Arduino “built in” USB stack or TinyUSB.  Both can be used with the MIDI Library, so I’ll go through both here.

TinyUSB Stack

There are instructions for using the TinyUSB stack here: https://wiki.seeedstudio.com/Seeeduino-XIAO-TinyUSB/

The Seeed SAMD core includes a version of the Adafruit TinyUSB stack but it also relies on the actual Adafruit TinyUSB Library too.  But there-in lies a problem!  The Seeed SAMD core has been regularly updated, but the last release at the time of writing is v1.8.3 which was released back in May 2022.  This is unfortunately incompatible with any version of the Adafruit TinyUSB library > 1.0.  This means that to use TinyUSB mode requires the following:

  • Install (or roll-back) the Adafruit TinyUSB Library using the Arduino Library manager, but make sure to install version 0.10.5.  Note that this library is now up pas v2.0, so this is many, many versions out of date!
  • Select USB Stack -> “TinyUSB” in the board menu for the XIAO.

Then to use MIDI USB requires the following:

#include <Adafruit_TinyUSB.h>
#include <MIDI.h>

Adafruit_USBD_MIDI usb_midi;

MIDI_CREATE_INSTANCE(Adafruit_USBD_MIDI, usb_midi, UMIDI);

At this point the UMIDI object can be used as any other MIDI instance.

Arduino USB Stack

My preferred option is to use the Arduino USB stack and the USB-MIDI Library that I’ve used several times in the past now.  Select USB Stack -> “Arduino” from the board menu and be sure to have the following libraries installed:

Both of which should be available from the Library Manager.

To use, do the following:

#include <MIDI.h>
#include <USB-MIDI.h>

USBMIDI_CREATE_INSTANCE(0, UMIDI);

The MIDI routing code has been updated now to take the following logic:

IF MIDI data from USB:
  Forward onto all three serial MIDI ports

IF MIDI data from any serial MIDI port:
  Forward onto USB MIDI

Find it on GitHub here.

Closing Thoughts

I had a fun bug in my routing code.  I had the following for loop to send MIDI to the serial ports:

if (UMIDI.read()) {
  for (int i=1; 1<=3; i++) {
    midiThru(0, i, UMIDI.getType(),
                   UMIDI.getData1(),
                   UMIDI.getData2(),
                   UMIDI.getChannel());
  }
}

Can you spot the problem?  The test “1<=3” is naturally always true (at least in this universe) so as soon as I sent a single message over USB MIDI, everything got stuck in an infinite loop! I thought there was weirdness going on with the USB stacks in use so ended up down a rabbit hole trying to work out how to “properly” drive USB on the XIAO.

Having started with the Arduino stack and getting the “hanging” problem, I switched to TinyUSB. But then had loads of compilation errors!  It took quite a bit of working through verbose compilation warnings before I finally noticed the statement on the XIAO TinyUSB guide about using the old Adafruit TinyUSB library…

Of course once that was all working I still had the problem with hanging code and it wasn’t until I started commenting out bits to get back to the most basic of examples (and having already seen the Adafruit TinyUSB “test_midi” application working fine) that I finally notice the typo, fixed it, and then switched USB stacks back again.

At this point I whole-hearted recommend using the Arduino stack for USB MIDI on the XIAO.  Just don’t get your code stuck in an (effectively) infinite loop – it really doesn’t help 🙂

Kevin

Leave a comment