Arduino Multi MIDI Merge

I’ve already had a basic MIDI merge project, combining USB MIDI and serial MIDI into a single serial MIDI out (see Arduino USB MIDI Merge).  This project takes that forward to provide the options for a whole range of MIDI IN interfaces merging to a single MIDI OUT.

  • In Part 2 I develop the code to handle NoteOn/NoteOff messages in a slightly more intelligent way.
  • In this project, I build a dual MIDI IN shield for an Arduino Uno.

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 Arduino tutorials for the main concepts used in this project:

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

Parts list

  • Arduino Uno, Nano, Micro, Pro Mega or other depending on requirements.
  • USB Host 2.0 Shield (optional)
  • Several MIDI Shields or alternative MIDI interface (DIY or ready-made)
  • MIDI note sources and MIDI sound source.

The Circuit

There are many ways of talking MIDI with an Arduino.  The Arduino MIDI Library itself supports the following directly:

  • Hardware serial MIDI
  • Software serial MIDI
  • USB device MIDI
  • Apple MIDI (rtpMIDI)
  • ipMIDI
  • Bluetooth MIDI

And with a bit of fiddling around, adding a USB Host Shield 2.0 gives us USB Host MIDI too.  The idea here is to support whatever MIDI transport is possible on the hardware in use.  Here are some common Arduino boards and the MIDI options I’m looking at in this project.

Arduino Uno/Nano: Hardware serial MIDI, software serial MIDI, USB host MIDI (with an additional shield).

Pro Micro/Arduino Leonardo: Hardware serial MIDI, software serial MIDI, USB device MIDI, USB host MIDI (with an additional shield).

Pro Mega/Arduino Mega: Hardware serial MIDI (x4), software serial MIDI, USB host MIDI (with additional shield).

Recall that the main principle is that “something” is listening on any available MIDI IN ports and is intelligently reading MIDI messages and sending them back out on the designation MIDI OUT port.  This means that the MIDI OUT is the bottleneck here.  It is running at the standard 31250 bits per second MIDI protocol, so it is entirely possible for it to be swamped by several MIDI IN streams running at full capacity.

Once again, we are relying on the Arduino to keep up processing all the required MIDI interfaces, which may include USB support too, at the same time.  If you start experiencing limitations there are other (faster, more powerful) microcontrollers to be considered too (such as SAMD based ones, or possibly the Raspberry Pi Pico).

With all that in mind, here are some example configurations.

Arduino Uno: COTS Shields for USB and Serial MIDI

Arduino MIDI Merge 2

In this setup, an Arduino Uno is used with an off-the-shelf MIDI shield, a USB Host Shield 2.0, additional capability for another COTS (serial) MIDI device if required.

This is set up as follows:

  • USB MIDI Host Shield – provides MIDI IN USB host capability.
  • COTS MIDI Shield – provides MIDI IN and the merged MIDI OUT.
  • A software serial implementation for receive on D2 for an additional MIDI IN device.

This could possibly be expanded with additional software serial MIDI ports.

Pro Mega/Arduino Mega: Four Hardware Serial MIDI ports

Arduino MIDI Merge 4

All four hardware serial ports on an ATmega2560 based board can be used for MIDI routing. In this configuration there are four serial MIDI IN ports all merged into a single serial MIDI OUT:

  • UART 1 TX – D1 – MIDI OUT
  • UART 1 RX – D0 – MIDI 1  IN
  • UART 2 RX – D15 – MIDI 2 IN
  • UART 3 RX – D17 – MIDI 3 IN
  • UART 4 RS – D19 – MIDI 4 IN

This could be expanded with software serial MIDI ports and maybe the use of a USB Host Shield.

Pro Micro/Arduino Leonardo: USB MIDI Device and Serial MIDI

Arduino MIDI Merge 3

Here I’m using the USB-MIDI device support possible with an ATmega32U4 based device alongside hardware serial MIDI and the option of additional software serial MIDI.

  • USB port: MIDI IN and OUT as a USB MIDI device.
  • Hardware UART RX – D0 MIDI IN.
  • Software Serial RX – D10 MIDI IN.

The Leonardo and similar boards have some limitations on which pins can be used for Software Serial. It requires pins that support the “pin change interrupt”, so it can only be used with D8, D9, D10, D11, D14, D15, and D16 (more details here).

The Code

This code requires the potential use of a number of libraries:

Where not already available as part of the Arduino environment, these are available via the Arduino’s library manager.

The MIDI library includes a built-in “THRU” capability that will automatically send anything it receives over a MIDI IN port to the corresponding MIDI OUT port.  This could be enabled for the OUT port, but I’m disabling it for all ports and doing all the routing in my own code.

There are many options, not all of which are available on all boards:

#define MIDI_HW_SERIAL  1
#define MIDI_HW_SERIAL2 2
#define MIDI_HW_SERIAL3 3
#define MIDI_HW_SERIAL4 4
#define MIDI_SW_SERIAL  5
#define MIDI_SW_SERIAL2 6
#define MIDI_USB_HOST   7
#define MIDI_USB_DEVICE 8

Any options not compatible or required for a particular build should be commented out.  The MIDI OUT device also has to be set to one of these too:

#define MIDI_OUT MIDI_HW_SERIAL

Here are some sample configurations for the hardware options described previously:

Arduino Uno with USB Host shield

#define MIDI_HW_SERIAL 1
//#define MIDI_HW_SERIAL2 2
//#define MIDI_HW_SERIAL3 3
//#define MIDI_HW_SERIAL4 4
#define MIDI_SW_SERIAL 5
//#define MIDI_SW_SERIAL2 6
#define MIDI_USB_HOST 7
//#define MIDI_USB_DEVICE 8

#define MIDI_OUT MIDI_HW_SERIAL

Notes:

  • Assumes use of the USB Host Shield 2.0.
  • MIDI OUT over the hardware serial port.
  • Software Serial on D2.

IMG_5604

Pro Mega

#define MIDI_HW_SERIAL 1
#define MIDI_HW_SERIAL2 2
#define MIDI_HW_SERIAL3 3
#define MIDI_HW_SERIAL4 4
//#define MIDI_SW_SERIAL 5
//#define MIDI_SW_SERIAL2 6
//#define MIDI_USB_HOST 7
//#define MIDI_USB_DEVICE 8

#define MIDI_OUT MIDI_HW_SERIAL

Notes:

  • All four hardware serial ports support MIDI IN.
  • MIDI OUT on the first hardware serial port.

IMG_5605

Pro Micro

//#define MIDI_HW_SERIAL 1
#define MIDI_HW_SERIAL2 2
//#define MIDI_HW_SERIAL3 3
//#define MIDI_HW_SERIAL4 4
//#define MIDI_SW_SERIAL 5
#define MIDI_SW_SERIAL2 6
//#define MIDI_USB_HOST 7
#define MIDI_USB_DEVICE 8

#define MIDI_OUT MIDI_USB_DEVICE

Notes:

  • USB Device support enabled via the built-in USB port.
  • MIDI IN and OUT via USB.
  • Hardware serial port MIDI IN.
  • Software serial port MIDI IN, using an alternative configuration (as software serial doesn’t work on pin 2).

IMG_5602

Optional MIDI Receive Indicator

There is the option to specify a MIDI RX LED for each enabled MIDI IN port.  This is configured in the ledPins[] array.  If no LED is required or the MIDI hardware option is not being used, these can be set to NOPIN.

From a hardware point of view, each LED should be connected to each pin via a suitable resistor to GND.

int ledPins[MIDI_LEDS] = { 2, 3, 4, 5, 6, 7, 8, 9 };

If your pin arrangement supports it, this is a great use of one of those “8-bit LED bars” I’ve used in the past.

2020-07-20 17.08.48

Find it on GitHub here.

Closing Thoughts

The video shows me using three MIDI keyboard controllers via an Arduino Uno using USB MIDI, hardware serial MIDI and software serial to control my MT-32.

I’ve not tested all combinations, but hopefully the code is a good jumping off point for a whole range of experiments. It will be interesting to see how far an Arduino can go as a merge unit!

As I mentioned before, if you really want to explore the universe of MIDI routing, merging and THRU options, you should take a look at the Teensy-based boards available from Tindie seller deftaudio (again please note I still don’t have any of them myself – they just look like a really neat idea – do let me know if you have some direct experience of these yourself).

Kevin

7 thoughts on “Arduino Multi MIDI Merge

  1. Hi Kevin,

    I just wonder something. I’ve got a Leonardo and made myself a switchboard from it, with which I send CC commands to my PC and control the toggles of vst’s I use for guitar. Recently I got myself a Boss GT-10 processor which also has got midi in/out ports. I wonder, is it possible to send CC messages directly from this board to GT-10 without using a PC, so that I can expand my control over the GT-10.

    Like

    1. Looks like the Boss GT-10 has serial (DIN) MIDI IN/OUT so yes, you should be able to add a serial MIDI interface to your Leonardo and have it send MIDI over that route too. There are many designs for MIDI OUT, but at its simplest, it is two resistors and a DIN socket! But a commercial MIDI add-on module for Arduino, or at least a buffered output circuit, gives more protection to your microcontroller and to your equipment. Have a look at the “Arduino MIDI Interfaces” page for some ideas.

      Note my comment on every project about testing out with cheap, sacrificial equipment mind. I suggest you don’t plug straight into your new module unless you really know what you’re doing (sorry, I don’t know your level of experience, so thought I’d go for assuming least knowledge and you can work up from there! :))

      Good luck!
      Kevin

      Like

      1. Wow, such a fast response, thanks! Here’s the code I currently use, can you guide me how can I modify it to be able to use both PC and GT-10 connection? This library belongs to someone called PieterP and as I checked from here “https://tttapa.github.io/Control-Surface-doc/Doxygen/d5/da5/Dual-MIDI-Interface_8ino-example.html#_a1” it seems possible to give output to both ways (USB & Midi)

        #include // Include the Control Surface library

        // Instantiate a MIDI over USB interface

        USBMIDI_Interface midi;

        // Instantiate an array of latched push buttons that send MIDI CC messages

        // when pressed.

        CCButtonLatched buttons[] {

        { 2, 0x10 },

        // │ └──── MIDI CC controller number

        // └───────── Button pin number

        { 3, 0x11 },

        { 4, 0x12 },

        { 5, 0x13 },

        { 6, 0x14 },

        { 7, 0x15 },

        { 8, 0x16 },

        { 9, 0x19 },

        };

        // Setup for an Analog pot for an EXP pedal on cc #11

        CCPotentiometer potentiometer = {

        A0, {MIDI_CC::Expression_Controller, CHANNEL_1}

        };

        // The filtered value read when potentiometer is at the 0% position

        constexpr analog_t minimumValue = 10550;

        // The filtered value read when potentiometer is at the 100% position

        constexpr analog_t maximumValue = 14550;

        // A mapping function to eliminate the dead zones of the potentiometer:

        // Some potentiometers don’t output a perfect zero signal when you move them to

        // the zero position, they will still output a value of 1 or 2, and the same

        // goes for the maximum position.

        analog_t mappingFunction(analog_t raw) {

        // make sure that the analog value is between the minimum and maximum

        raw = constrain(raw, minimumValue, maximumValue);

        // map the value from [minimumValue, maximumValue] to [0, 16383]

        return map(raw, minimumValue, maximumValue, 0, 16383);

        // Note: 16383 = 2¹⁴ – 1 (the maximum value that can be represented by

        // a 14-bit unsigned number

        }

        void setup() {

        potentiometer.map(mappingFunction);

        Control_Surface.begin(); // Initialize the Control Surface

        Serial.begin(31250);

        }

        void loop() {

        Control_Surface.loop(); // Update the Control Surface

        //Serial.println(potentiometer.getRawValue());

        Like

      2. I’m afraid I’m not really familiar with that library (and the code hasn’t pasted into the comments very well), but I think that example on the page you’ve linked suggests you have to create a new instance of the MIDI control surface for serial MIDI using Serial1, which should apply to your Leonardo too I think… I seem to recall the UART on the ATmega32U4 comes up as Serial1 on a Leonardo.

        So that would go after your USBMIDI_Interface line in your code.

        Then it suggests you need to add those two “pipe” lines in the setup() before the Control_Surface.begin() line and it implies magic will just happen…?

        One thing to note – using serial MIDI will mess with any Serial.print type statements to the same port. You might be ok if Serial is USB and Serial1 is the UART (being used for MIDI) though with a Leonardo, but if you get weirdness then it might be worth checking that just in case…

        Let me know how you get on. If I get a chance later this evening, I might have a proper look at that library. I think I’ve seen it mentioned elsewhere, but I’ve never looked at it myself.

        Good luck!

        Kevin

        Like

  2. This is the GitHub page of that library;

    https://github.com/tttapa/Control-Surface

    I’m not that much familiar with coding actually, I just barely understand the logic behind it. I’ll be most appreciative if you can help me with this project. I can change the code if necessary (if you know something better). This was something that I was able to find and worked for me. Initially, I didn’t have such an intention of course, but now I thought “why not?” 🙂

    The switchboard I made consists of 8 momentary switches with 2 lugs, and 1 potentiometer; all of them send CC messages which you can see above. Occupied pins are 2 to 9 and A0. I’ll buy a MIDI cable and a female 5-pin DIN connector. Also if possible, I’d like to add LED indicators for each switch, but as they are momentary switches, I don’t know how they would be implemented for on-off states.

    Like

    1. Send the code you’re using to me in an email to diyelectromusic at gmail and I’ll add in the lines to make it talk two types of MIDI that I think you need (based on that link you send me) and you can give it a go. If it is that simple, then great! If not, then I’ll need to have a proper look later 🙂

      Kevin

      Like

  3. I built one on an uno and it works like a charm for mixing my DIY doepfer keybed and DIY synth programmer.

    Like

Leave a comment