fbpx
Skip to main content

Arduino MIDI Output Basics


Introduction

The Arduino UNO is a popular open-source microcontroller that, in many respects, is a perfect complement to the extensible nature of the Music Instrument Digital Interface (MIDI) protocol. Microcontroller platforms such as Arduino, Teensy, and others, make it relatively easy to develop custom MIDI controllers that respond to light, pressure, sound, and many other forms of input. In this way, microcontrollers provide a unique way to expand the possibilities of MIDI into the physical realm. MIDI musicians can now envision and create an astounding array of custom hardware devices from custom controllers to algorithmic composers and beyond.

Note that this article focuses on the basics of MIDI output on an Arduino UNO. Future articles will cover MIDI input on the Arduino and Teensy platforms as well as the use of potentiometers, switches, and other components for real-time MIDI control.

Transmitter Circuit

It is necessary to utilize a MIDI interface in order to send MIDI messages from an Arduino to a synthesizer, Digital Audio Workstation, or other MIDI device. Fortunately, it is easy (and inexpensive) to create a simple circuit that can handle MIDI output. The circuit can be mocked up on a solderless breadboard for experimentation or a permanent version can be soldered to solderboard. Users who are new to electronics might want to consider a commercial version such as the SparkFun MIDI Shield, offered at a nominal cost by SparkFun Electronics and other vendors.

As is evident in Figure 1, a circuit that was documented in David Miles Huber’s The MIDI Manual, the circuit for MIDI output is relatively simple and consists of:

  • a connection from the 5V pin of an Arduino through a 220-ohm resistor to pin 4 of a standard MIDI DIN jack,
  • a connection from the GND pin of an Arduino to pin 2 of a MIDI DIN jack,
  • a connection from the TX pin of an Arduino through a 220-ohm resister and 7404 Hex inverter to pin 5 of a MIDI DIN jack. 

Figure 2 demonstrates one way that the transmitter circuit could be configured on a solderless breadboard. Note that the top rail of the solderless breadboard is connected to the 5V pin on the Arduino and the bottom rail is connected to the Arduino GND pin.

MIDI Output Sketch: “Old School” Approach

While it is generally more convenient to use a MIDI library to program MIDI sketches on an Arduino, we will start with a low-level “pure” sketch in order to demonstrate how MIDI bytes are handled. If you have ever programmed MIDI applications for Windows, OS X, or Linux you are in for a pleasant surprise because MIDI output can be achieved with just a few lines of code on an Arduino. If you haven’t done so already, be sure to download the Arduino Software (Integrated Development Environment) from https://www.arduino.cc/en/Main/Software. Next, run the Arduino software and select File…New and enter the code that is described in the following paragraphs.

Boilerplate Code

While the basics of C and C++ programming are beyond the scope of this article (and covered in detail in my own Arduino for Musicians as well as numerous other books and online resources), rest assured that the basics of coding a simple MIDI sketch are not unduly difficult. Start by typing the functions shown in Listing 1 which form the basis for all Arduino sketches. Note that the term function is used to describe a block of “functional” code denoted by the function name and opening and closing braces:

Listing 1 Boilerplate functions


void setup()
{

}

void loop()
{

}

The setup() function is called once when your sketch is first run on an Arduino. You will use that block of code (between the opening and closing braces) to establish the serial transmission rate and any other initialization required by the sketch. The loop() function is where the action happens. As the name of the function implies, the loop() function continues to loop throughout the duration of your sketch unless you pause it with a delay() function or some other blocking activity.

Establishing a serial connection

To establish a serial MIDI connection between the Arduino and a MIDI receiver, add the code shown in Listing 2 to the setup() function. The Serial object represents a class (an object or pre-programmed chunk of code) that handles all of the low-level details of establishing and maintaining a serial connection. Note that the Serial class provides a function (typically called a method in the context of a class) titled begin() that takes the baud rate as a parameter. In this example, serial transmission is set to 31250 baud, the expected MIDI transmission rate as per The Complete MIDI 1.0 Detailed Specification (available from the MIDI Association at midi.org).

Listing 2 Setting up a serial connection


void setup()
{
Serial.begin(31250);
}

Writing a MIDI output function

Although there is nothing wrong with writing code for sending MIDI data in the loop() function, custom functions can help to produce code that is extensible and easier to read and maintain. Listing 3 demonstrates one approach to sending Note-On messages. Notice how the function takes three bytes that correspond to the MIDI channel, note, and velocity. The only tricky part of the code is the first line which translates the expected MIDI channel range of 1-16 to the range of Note-On status bytes starting at 0x90 (hexadecimal). The Serial.write() method is used to transmit the status byte and data bytes that form a Note-On message:

Listing 3 Custom function for outputting MIDI Note-On messages


void playMIDINote(byte channel, byte note, byte velocity)
{
//MIDI channels 1-16 are really 0-15
byte noteOnStatus = 0x90 + (channel-1);

//Transmit a Note-On message
Serial.write(noteOnStatus);
Serial.write(note);
Serial.write(velocity);
}

Outputting Notes

Now that a convenience function is available to handle the transmission of Note-On messages, it is easy to fill in some simple code in the loop() function to output a series of notes. Note that this example uses a blocking delay—generally a bad idea for more robust applications—but the use of timers is beyond the scope of this article and would only serve to obfuscate the underlying concept of sending MIDI data via a serial connection. In Listing 4, a “for loop” is used to output MIDI Note-On messages in the range of 60 to 72. The function delays and then the transmits the same note with a velocity of zero—which is functionally equivalent to sending a corresponding Note-Off message.

Listing 4 Outputting a chromatic scale


void loop()
{
//Play a chromatic scale starting on middle C (60)
for(int note = 60; note < 72; note++)
{
//Play a note
playMIDINote(1, note, 100);
//Hold the note for 60 ms (delay() used for simplicity)
delay(60);

//Turn note off (velocity = 0)
playMIDINote(1, note, 0);
//Pause for 60 ms
delay(60);
}
}

Uploading a Sketch to the Arduino

The complete sketch is shown in Listing 5. Once you have typed or copied the code into the Arduino Integrated Development Environment (IDE), click the leftmost check button to ensure that the sketch is free from errors. If you are relatively new to programming it might be helpful to remember that C code is case sensitive. It is also easy to omit an opening or closing brace or semicolon which can create any number of error messages. A final step is to connect the Arduino to your computer via a USB cable and select the upload button to upload the code to the Arduino. Assuming you have connected a valid MIDI output circuit, the chromatic scale should be received by any MIDI receiver device that is connected to the circuit via a MIDI cable.

Listing 5 Complete listing


void setup()
{
//Set up serial output with standard MIDI baud rate
Serial.begin(31250);

}

void loop()
{
//Play a chromatic scale starting on middle C (60)
for(int note = 60; note < 72; note++)
{
//Play a note
playMIDINote(1, note, 100);
//Hold note for 60 ms (delay() used for simplicity)
delay(60);

//Turn note off (velocity = 0)
playMIDINote(1, note, 0);
//Pause for 60 ms
delay(60);
}
}

void playMIDINote(byte channel, byte note, byte velocity)
{
//MIDI channels 1-16 are really 0-15
byte noteOnStatus=0x90 + (channel-1);

//Send notes to MIDI output:
Serial.write(noteOnStatus);
Serial.write(note);
Serial.write(velocity);
}

Coding Challenge

That’s it—Arduino MIDI output can be achieved with just a few lines of code! Consider how you might use the boilerplate code in this example to develop a simple algorithmic generator (perhaps using the Arduino random() function) or a sketch that outputs chords, exotic scales, or drum beats.

Next Steps

Although this introduction is necessarily limited, it forms the basis for many exciting possibilities including algorithmic composition, automation, and real-time control. As you will see in future articles, a basic MIDI output circuit can also be used for useful applications such as using a potentiometer to send continuous controller messages to a DAW or a two-axis joystick as an expressive real-time controller. As noted in the introduction, detailed coverage of Arduino MIDI and audio concepts are provided in Arduino for Musicians: A Complete Guide to Arduino and Teensy Microcontrollers as well as other books online resources.

Happy coding!