This instructable will show you how to use an Arduino to send and receive a variety of MIDI messages so you can start building your own MIDI controllers and instruments. First I'll talk a little bit about MIDI protocol, if you're just looking for sample code skip ahead to steps 5-9.

If you know absolutely nothing about MIDI note, velocity, and pitchbend or are confused about what MIDI does and why you would want to use it, check out my What is MIDI? instructable.

Step 1: Bytes and Bits

To understand MIDI communication, you have to understand a little about bytes and bits. A byte is a packet of data used to store information. In MIDI protocol, each byte is made up of 8 bits; bits can only equal to 0 or 1. A sample byte is given below:


Each 1 or 0 in this byte is a bit. The leftmost bit is called the most significant bit (or MSB) and the rightmost bit is called the least significant bit (or LSB).

Bytes of the form above are binary numbers because they are expressed using only 1's and 0's. We can convert this number to base ten as well:

11010111 in binary (base 2) = 215 in decimal (base 10)

If you need help converting numbers from binary to decimal or vice versa check out Wolfram Alpha. Type in a binary number followed with "from binary to decimal" to get the decimal equivalent. Wolfram Alpha is also great for converting to and from hexadecimal.

Wikipedia is a good resource for more information about bytes and binary.

<div>when I try to use the MIDI Hairless and try to connect with the port of arduino, the error &quot;this application has Requested the Runtime to terminate it in an unusual way&quot; shows how I can fix this?</div>
<p>Hi, I realize this is an old thread, but I am having the same issue. How did you resolve it?</p>
<p>Thanks for the great 'ible.</p><p><iframe allowfullscreen="" frameborder="0" height="281" src="//www.youtube.com/embed/wUUEu4H2_tE" width="500"></iframe></p><p>Do you know how to do something like this. I basically want to be able to read midi files from the Arduino and connect it to a MIDI device. I'm planning (if this is possible!) to have LEDs which light up when a specific note is played - it could also display the MIDI velocity by changing its brightness with PWM.</p>
<p>Hi Amanda,</p><p>Great Tutorial. However when it comes to Electronics my knowledge is limited at best. I was wondering whether you would mind further explaining the use of the optocoupler for receiving data... If I could understand WHY we use it the rest will become clearer to me. Many Thanks. Chris</p>
<p>hey, sorry for the late reply. <a target="_blank" href="http://www.midi.org/techspecs/electrispec.phphttps://en.wikipedia.org/wiki/Opto-isolator">Optocouplers</a> isolate circuits from each other by using light to transmit data instead of voltage. This can be useful if two circuits need to communicate with each other and they use different voltages to transmit data signals (eg 5V vs 3.3V logic). In this case it's not a voltage difference, I think the optocoupler is there to protect from current spikes. It is required in the <a target="_blank" href="http://www.midi.org/techspecs/electrispec.phphttps://en.wikipedia.org/wiki/Opto-isolator">specs</a>.</p>
The optocoupler provides electrical insulation between equipments. This avoids several problems that plague audio devices, like ground loops and hum pickup.
<p>Hi Amanda!</p><p>I think your phrase: </p><p>&quot;The last half of the command byte sets the MIDI channel. All the bytes <br>listed above would be in channel 0, command bytes ending in 0001 would <br>be for MIDI channel 1, and so on.&quot;</p><p>is not exact, because in 4 bits values go from 0 to 15. So a byte ending 0001 means 2. </p>
<p>Hi your tutorial is very usefull :-)</p><p>I just have a probleme. I tried you receive and check midi if note = 60 and it work. So i decided to modify it to light up 8 led when i play on my midi keyboard. So i made this programme but it does'nt work. </p><p>/*<br>By Amanda Ghassaei<br>July 2012<br><a href="http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/" rel="nofollow">http://www.instructables.com/id/Send-and-Receive-M...</a><br><br><br>*/<br><br>byte commandByte;<br>byte noteByte;<br>byte velocityByte;<br><br>byte noteOn = 144;<br><br><br>void setup(){<br> <br> Serial.begin(56000);<br> pinMode(13,OUTPUT);<br> pinMode(12,OUTPUT);<br> pinMode(11,OUTPUT);<br> <br> digitalWrite(13,LOW);<br> digitalWrite(12,LOW);<br> digitalWrite(11,LOW);<br> <br>}<br><br>void directblink13(){<br> digitalWrite(13,HIGH);//turn on led<br> delay(1000);<br> digitalWrite(13,LOW);<br> }<br>void directblink12(){<br> digitalWrite(12,HIGH);//turn on led<br> delay(1000);<br> digitalWrite(12,LOW);<br> }<br>void directblink11(){ <br> digitalWrite(11,HIGH);<br> delay(1000);<br> digitalWrite(11,LOW); <br> }<br><br>void checkMIDI(){<br> do{<br> if (Serial.available()){<br> commandByte = Serial.read();//read first byte<br> noteByte = Serial.read();//read next byte<br> velocityByte = Serial.read();//read final byte<br> if (commandByte == noteOn){//if note on message<br> //check if note == 60 and velocity &gt; 0<br> if (noteByte == 60 &amp;&amp; velocityByte &gt; 0){directblink13;}<br> <br> else if(noteByte == 61 &amp;&amp; velocityByte &gt; 0){directblink12;}<br> <br> else if(noteByte == 62 &amp;&amp; velocityByte &gt; 0){ directblink12;}<br> }<br> <br> <br> <br> }<br> <br> }<br> while (Serial.available() &gt; 2);//when at least three bytes available<br>}<br> <br><br>void loop(){<br> checkMIDI();<br> delay(1);<br><br>}</p><p>Thanks :-)</p>
<p>When you're calling your directblink functions, you're forgetting to add ()</p><p>So a call should be: directblink12();</p>
<p>Hey Amanda. I've written some very simple code that receives MIDI and turns on some LEDs via the pwm. I'm receiving the messages via Hairless so no need for the external MIDI wirings.</p><p>For some reason the program will only work when there is a short delay of minimum 4ms after the checkMIDI() function is called. If there is no delay, the LEDs dont light up. The only problem is, this causes some messages to be missed. Any idea why? </p><p>Below is the code:</p><p>byte commandByte;</p><p>byte secondByte;</p><p>byte thirdByte;</p><p>byte noteOn = 144;</p><p>byte noteOff = 128;</p><p>byte pitchBend = 224;</p><p>int pwmVal;</p><p>void setup()</p><p>{</p><p> Serial.begin(9600);</p><p> pinMode(3,OUTPUT);</p><p>}</p><p>void checkMIDI()</p><p>{</p><p> do</p><p> {</p><p> if (Serial.available())</p><p> {</p><p> commandByte = Serial.read();//read command byte</p><p> secondByte = Serial.read();//read next byte (MSB, or Note)</p><p> thirdByte = Serial.read();//read final byte (LSB or velocity)</p><p> if (commandByte == noteOn)</p><p> {</p><p> if (secondByte &gt; 0 &amp;&amp; thirdByte &gt; 0)</p><p> {</p><p> pwmVal = map(thirdByte,0,127,0,255);</p><p> analogWrite(3,pwmVal);//turn on led with velocity value</p><p> }</p><p> }</p><p> else if(commandByte == noteOff)</p><p> {</p><p> analogWrite(3,0);</p><p> }</p><p> }</p><p> }</p><p> while (Serial.available() &gt; 2);//when at least three bytes available</p><p>}</p><p>void loop()</p><p>{</p><p> checkMIDI();</p><p> delay(4);</p><p>}</p>
<p>Sorry, I conducted as your instructable and I found that midiout message can be received normally by hairless software. But it seemed that the midiin.maxpat didn't work as what presented in your video.</p><p>I am trying to figure out this problem. I am assuming that the problem occurs when hairless route message to MAX, but I don't know where goes wrong.</p>
<p>maybe try selecting another midi channel in hairless midi/max. There might be something called From/To MaxMSP</p>
<p>Hi Amanda, thanks for your extensive tutorial! I'm thinking of building a touch capacitative midi keyboard and am trying to figure out how to translate the amount of touch recieved to velocity of note. So &lt; touch &lt; volume. Just wondering if you could help me out. Thanks!</p>
<p>No problem. Read in touch data from an analog pin (number between 0-1023) then scale that number down to a number between 0-127 using the <a target="_blank" href="https://www.arduino.cc/en/reference/map">map</a> function. Then send that out as the velocity. You can start with the variable velocity code I wrote and modify it to use the touch velocity from your sensor.</p>
<p>Hey There!</p><p>I am currently working on this project and everything is working fine so far. Is there a big difference between an 6N138 and an 6N137 Optocoupler? Am I able to build Step10 with an 6N137 Optocoupler too? </p><p>By the way: <strong>Awesome </strong>tutorial!!!</p><p>Greetings from Germany ;)</p>
<p>I'm not sure. If the pin outs are the same and the basic specs (input/output voltage/current, etc) look the same and are withing range for the arduino it's worth it to try. Did you try it already?</p>
<p>Thank you for this great tutorial! I've tried the midi out and works perfectly, I even managed to have arduino play poliphony in my synth. I haven't tried the midi in because I don't have the octocoupler yet but in the meanwhile I've been having a look at the schematics and the photos and there's something I don't understand (I'm a just a beginner in arduino/electronics): in the schematics, the cable with the 220ohm resistor comes out from the octocoupler's pin 2, but in the photos the resistor is soldered to the yellow cable, which in turn comes from pin 3.</p><p>Should I solder the resistor to the yellow or the green cable? To which pins in the octocoupler should the yellow and green cable ba connected?</p><p>Many thanks! :-)</p>
<p>hey, I see where the confusion is coming from, but it's been so long I'm not sure. I would probably go with the schematic, did you find out which pin was correct?</p>
<p>Hi!<br>First of all, thank you for this great instructable!<br>I'm currently using MIDI as input on my Arduino Uno and use Arduino as output translator device. So basically I'm playing notes on Synthesizer, send them to Arduino using MIDI, and then play them using notes library. I'm also displaying notes, velocity and event on LCD, just to se what is going on there. <br>The main problem is that the whole thing is too slow. I don't know if this happens to you, but Arduino sometimes skips or doesn't even receive the note or any MIDI message if it is played too fast. For example, if I play a note and release it emediately, the Arduino receives the first message with velocity&gt;0, but misses the second message with velocity=0. <br>I tried to make it faster by removing notes or LCD library, but it was the same. Maybe the Serial is to slow in Arduino because it is Arduino softare? Any ideas?</p>
<p>Thank you for the elaborate tutorial.</p><p>But you didn't mention how to interface the midi software like garageband when the midi messages were sent out.</p><p>I know that hairless can help messages route to garageband, but I wonder how garageband behave when receiving the Noteon command? </p>
<p>Our project is slightly different, since we do MIDI over USB and then use Hairless and LoopMIDI to interface with Ableton, but if people are interested, the code is available here:</p><p><a href="http://stephane.thunus.org/SAE/arduino.htm" rel="nofollow">http://stephane.thunus.org/SAE/arduino.htm</a></p><p>It is not 100% finished and clean, but it works - sorry, the code is a further version than the video explanations - will be updated when the project is finished.</p>
Now I did, sorry. I just got in the optocouplers from mouser, and was about to put this all together, and remembered by board in 3.3V. If I supply the optocouplers with 3.3 will I run into any obvious issues?
if you supply the optocouplers with 3.3V, then the max signal coming out of them will be 3.3V. Since you are trying to read with with one of the Arduino's digital pins, I'm concerned it might not be enough to switch it to a "HIGH" state. no harm in trying though.
<p>Hello amanda I was looking at this programs you put in here, very interesting, and thanks for sharing them a lot of things i&acute;ve learn. I have a small question is their for example any free software for arduino that can receive the midi file (for example a midi version of beethovens 5th symphony intro) and just read the notes as they came from the midi file and then to the arduino board keeping the same duration &quot;as the intro of the symphony is&quot;. For example if I want to export each note from the midi and let several leds to play each single note.<br>Thanks a lot again for sharing this. Hope you have a great day</p>
<p>You could use fl studio demo it will let you export into an audio file (mp3, wav, etc...) but not save.</p>
<p>This Code below here from you doesn't work to me.<br>The Serial.read() only put values in commandByte, but not noteByte and velocityByte? I can be sure that commandByte is always bigger than 127 and the other values 0-127 can be noteByte or velocityByte?</p><p>ISR(TIMER2_COMPA_vect) {//checks for incoming midi every 128us<br> do{<br> if (Serial.available()){<br> commandByte = Serial.read();//read first byte<br> noteByte = Serial.read();//read next byte<br> velocityByte = Serial.read();//read final byte<br> }<br> }<br> while (Serial.available() &gt; 2);//when at least three bytes available<br>}</p>
Yes the command byte is always >127 and the note and velocity (or whatever other parameters come after the command are <= 127. This code can be really finicky depending on your setup. Try removing the > 2 in the code able and see if it helps. You might want to add some additional logic to be sure that the command byte is set correctly (check if it is > 127)<br />
<p>First of all, many thanks for this awesome tutorial! It really helped me a lot. </p><p>Unfortunately, I'm having the same problem. Removing &gt;2 doesn't seem to help. With additional logic, I've discovered that noteByte reads 255, no matter wich note I play.The commandByte, noteOn and noteOff are working fine.</p>
<p>Very helpful! Thank you!!</p>
<p>Hi everyone just a brief question. Is their any free program like the ones describe in here that just receive the midi as it comes from the midi file and the arduino play it as the file came. So for example if one has beethoven 5th symphony, just let the arduino receive it through the imput and let it out to something else like an output for example. thanks </p>
<p>I'm unclear on some things. Well written instructable, but I'm not fully understanding MIDI yet. Will the master midi device send a constant bitstream, with every single bit being part of a command byte or data byte? If not, I'm guessing that if I wanted to read midi into my Nexys-3 board, I'd need to create a clock to check the data input pin 31250 times a second, listen for a logic high, and then proceeding to store the data bytes and the rest of the command byte. For my project, I intend to only care about the Note On and Note Off commands, but will expand in the future. </p><p>Also, would you know of any program that could either A) take guitar input to the computer (through a Scarlett 2i2) and convert to midi and then output to a usb port (that will have a usb to midi cable), or B) take a .mid file and output it to the same usb cable as in A? My project is an audio modulated Tesla coil, and the Tesla coil works. I have my bridge circuit and protection circuit hardware ready, just need to understand how to read midi input. Any help would be greatly appreciated!</p>
<p>I've been having problems reading the midi data once I start playing more than one note at a time (polyphony). Does this have to do with the note on command with 0 velocity and the note off command? Does it send both commands when a note is released?</p>
<p>yeah the code I have there isn't setup to handle polyphony. The way that works is two note on messages are sent to the arduino at approx the same time, and then two note off messages are sent when you release the note. Remember note off messages specify the pitch they are turning off, so each note off command is specific to a certain pitch. What are you planning on making?</p>
Could you give an example of how you send two messages at a time? I am hoping to use this brilliant tutorial to help me integrate my controllers and some messages it sends are two note messages.
<p>I've attached an led strip, and I'm trying to assign a note to each led on the strip. One note seems to work fine, but things just start getting wonky when I play more than one note. Did I not implement the note off message correctly, or does the circuit just not handle polyphony?</p><p><br>#include &lt;Adafruit_NeoPixel.h&gt;</p><p>Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);</p><p>byte commandByte;</p><p>byte noteByte;</p><p>byte velocityByte;</p><p>byte noteOn = 144;</p><p>byte noteOff = 128;</p><p>void setup(){</p><p>Serial.begin(31250);</p><p>strip.begin();</p><p>}</p><p>void loop(){</p><p>checkMIDI();</p><p>strip.show();</p><p>delay(10);</p><p>}</p><p>void checkMIDI(){</p><p>do {</p><p>if (Serial.available()){</p><p>commandByte = Serial.read();//read first byte</p><p>noteByte = Serial.read();//read next byte</p><p>velocityByte = Serial.read();//read final byte</p><p>if (commandByte == noteOn){//if note on message</p><p>if (velocityByte &gt; 0) {</p><p>strip.setPixelColor(noteByte-30, 0, 0, velocityByte);</p><p>} else {</p><p>strip.setPixelColor(noteByte-30, 0, 0, 0);</p><p>}</p><p>} else if (commandByte == noteOff) {</p><p>strip.setPixelColor(noteByte-30, 0, 0, 0);</p><p>}</p><p>}</p><p>}</p><p>while (Serial.available() &gt; 2);//when at least three bytes available</p><p>}</p>
<p>sorry, apparently that error appears when I connect to the MIDI output, how do I connect to the application of the piano?</p>
<p>does not matter because I decided it was custi&oacute;n create a virtual MIDI port, I installed &quot;loopMIDI&quot; and it worked. thanks for the tutorial, this rather detailed.</p>
<p>Hi Amanda,</p><p>Thanks for the excellents Midi Instructables you have shared!</p><p>I am a newbie with Midi and Arduino and no experience in programing, I am looking for a simple Arduino sketch to read the output from the Midi In board and print it in the serial console.</p><p>I am planning to build a wireless midi transmissor and that sketch will be the first step.</p><p>Thanks in advance for your help.</p><p>Edilberto</p>
have you tried Serial.println(Serial.read()) ?
<p>hello,</p><p>I've got my arduino hooked up to my PC with the MIDI-USB cable. the baudrate is set to 31250 but still my computer is not picking up any midi signals. I use the software of this tutorial. if i hit my piezo my tx light will light up so thats not the problem. what can my problem be?</p>
<p>Is there a way you could send the signal through USB directly, without having to use a separate adapter?</p>
<p>To be more clear, I want to use a digital pin to send the signal, instead of the arduino's USB interface. I'm using a barebones arduino that requires an FTDI adapter (that I only have one of).</p>
<p>if you're sending MIDI to your comp, you could run an application like <a href="">this</a> to convert serial to MIDI and pass the MIDI messages through the USB connection. You could also get your Arduino to act as a USB/MIDI device through <a href="">firmware</a>.</p>
<p>I see; are there any necessary changes (using the first method) to the code described in the instructable? How would you wire the USB connection from the Arduino pin? Thanks for the help.</p>
You can use the USB on the arduino, I added some info in step 5
<p>Ok, thanks. Would it be possible to use a digital pin on the arduino to send the serial signal, instead of the programming port? Again, I am using barebones arduinos that require a separate FTDI adapter, and I only have one of those.</p>
<p>no, I don't think so.</p>
<p>What if you used this library I found; it's called SoftwareSerial, and it says it allows you to send serial data through a digital pin. Would it be compatible with Hairless MIDI?</p><p><a href="http://arduino.cc/en/Reference/SoftwareSerial#.Uv8g-_ldWT8" rel="nofollow">http://arduino.cc/en/Reference/SoftwareSerial#.Uv8...</a></p><p><a href="http://arduino.cc/en/Tutorial/SoftwareSerial#.Uv8g9_ldWT8" rel="nofollow">http://arduino.cc/en/Tutorial/SoftwareSerial#.Uv8g...</a></p>
<p>you can use this to send serial data to electronics, but I'm not sure it will communicate with your computer.</p>
I want to making you know that I had some trouble making my arduino speaking MIDI. Finally I got it with Hairless Serial&lt;&gt;MIDI converter and a MIDIPort, but I must set the serial baudrate at a different speed (38400). In Hairless' Settings MENU I must choose at which speed is Arduino sending serial information and there isn't 31250. <br>I can't solve this issue and I need to because MIDI Library work at 31250 by default and because I imagine a physical USB converter (as yours) expect to receive data at that frecuency. <br>I tried to use a Midiman MIDISPORT 2x2 without success. I don't know how to solve this problem and also It get me a bit frustrated because all DIY projects use that MIDI default MIDI without problems. <br> <br>I haven't tried to receive, manage and process incoming MIDI data. I'm going step by step. <br> <br>Anyway I found your channel really well made with detailed informations and clear explications. I'm also having benefits from the other instructables about Timer Interrupts. It's great! <br> <br>Alberto

About This Instructable


420 favorites


Bio: I'm a grad student at the Center for Bits and Atoms at MIT Media Lab. Before that I worked at Instructables, writing code for ... More »
More by amandaghassaei: OTCA Metapixel - Conway's Game of Life "9 Degrees of Freedom" IMU Twitter Controlled Pet Feeder
Add instructable to: