Arduino I2C MIDI Interface – Part 4

This project takes the I2C MIDI relay from part 3 a little further and uses a serial to I2C MIDI relay to drive two different I2C MIDI peripherals.

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 Arduino, see the Getting Started pages.

Parts list

  • 3x Arduino Uno, Nano, or similar
  • 2x Arduino MIDI Interfaces
  • old 8Ω loudspeaker
  • 220Ω resistor (for the loudspeaker)
  • MIDI source (e.g. MIDI controller, computer or keyboard)
  • MIDI sound module (e.g. synth module or computer)

The Circuit

ArduinoI2CMIDIDualRelay_bb

Now the three Arduinos all need their I2C bus linked up.

  • A4 to A4 or alternatively SDA to SDA
  • A5 to A5 or alternatively SCL to SCL
  • GND to GND

The first Arduino needs a MIDI interface for the serial MIDI IN and the last one needs a MIDI interface for the serial MIDI OUT.  For demonstration purposes the middle Arduino has a loudspeaker connected to D8.

All Arduino’s need power, e.g. over their USB connection.

IMG_5692

The Code

First, remember- this is (still) very experimental!  But I’m gaining confidence in it all the time 🙂

The loudspeaker Arduino is running the I2CMIDIReceive example from part 2 and left listening on the default I2C address 0x40.

The MIDI OUT Arduino is running the I2CMIDIRelay example from part 3, but it is configured in I2C2SERIAL mode and set to I2C address 0x50.

The MIDI IN Arduino is running some new code I’ve written (and added to the examples directory in the GitHub repository) that processes all the MIDI IN data and then decides what to do with it.

It is implementing the following rules:

  • Ignore anything that isn’t NoteOn or NoteOff.
  • Any NoteOn or NoteOff messages in the range of the I2CMIDIReceive demo code – i.e. notes 60 to72 (C4 to C5) are sent to I2C address 0x40 (the loudspeaker Arduino).
  • All other NoteOn and NoteOff messages are sent to I2C address 0x50 (the MIDI OUT Arduino).

This means that as you play notes up the keyboard, there is one full octave in the middle that plays tones but all other notes are sent out over the MIDI OUT. In the video, I’ve connected MIDI OUT to my MT-32 as usual.

How has this been achieved?  Simply by instantiating two instances of the I2CMIDI interface in CONTROLLER mode as follows:

#define I2CMIDIADDR1 0x40 // Relay to the I2CMIDIReceive Demo
#define I2CMIDIADDR2 0x50 // Relay to an I2CMIDI to Serial Relay Demo (with address changed)

I2CMIDI_CREATE_INSTANCE(I2CMIDICONTROLLER, I2CMIDIADDR1, I2CMIDI1);
I2CMIDI_CREATE_INSTANCE(I2CMIDICONTROLLER, I2CMIDIADDR2, I2CMIDI2);

// Serial MIDI
MIDI_CREATE_DEFAULT_INSTANCE();

Once all three MIDI interfaces have been initialised in the usual way (calling their begin() functions) the loop can listen for messages via MIDI.read() and send them out to either I2CMIDI1.send() or I2CMIDI2.send() as appropriate.

Find it on GitHub here.

Closing Thoughts

I have to be honest – I was really surprised this “just worked”. I really thought there would be some weird interactions between the two instances of the I2C MIDI interface.  I don’t know what would happen if (for example) the reads managed to get overlapped somehow, but I guess as long as both interfaces are configured as CONTROLLERS it should be fine.  Which is fine for me, as I’m thinking of having some kind of MIDI distribution node sending out over I2C to a number of receivers.

I really don’t see how it could work as two PERIPHERALS, so should probably build in some checks to prevent that happening!

I haven’t pushed it to see what the performance is like either, but the video does show how notes seem to successfully get interleaved ok.

So still very early days and this really needs some hammering now, but this is a very encouraging result!

Kevin

Leave a comment