Instructables
loading
loading
Picture of Send and Receive MIDI with Arduino
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.
 
Remove these adsRemove these ads by Signing Up

Step 1: Bytes and Bits

Picture of 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:

11010111

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.
1-40 of 163Next »
ikožar7 days ago

Hi!
First of all, thank you for this great instructable!
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.
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>0, but misses the second message with velocity=0.
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?

solohust29 days ago

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.

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.

Screen Shot 2015-06-03 at 2.43.06 PM.png
solohust1 month ago

Thank you for the elaborate tutorial.

But you didn't mention how to interface the midi software like garageband when the midi messages were sent out.

I know that hairless can help messages route to garageband, but I wonder how garageband behave when receiving the Noteon command?

Spock4442 months ago

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:

http://stephane.thunus.org/SAE/arduino.htm

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.

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?
amandaghassaei (author)  canada13records2 years ago
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.

Hello amanda I was looking at this programs you put in here, very interesting, and thanks for sharing them a lot of things i´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 "as the intro of the symphony is". For example if I want to export each note from the midi and let several leds to play each single note.
Thanks a lot again for sharing this. Hope you have a great day

You could use fl studio demo it will let you export into an audio file (mp3, wav, etc...) but not save.

schobz1233 months ago

Hey There!

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?

By the way: Awesome tutorial!!!

Greetings from Germany ;)

forgoden1 year ago

This Code below here from you doesn't work to me.
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?

ISR(TIMER2_COMPA_vect) {//checks for incoming midi every 128us
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
}
}
while (Serial.available() > 2);//when at least three bytes available
}

amandaghassaei (author)  forgoden1 year ago
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)

First of all, many thanks for this awesome tutorial! It really helped me a lot.

Unfortunately, I'm having the same problem. Removing >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.

Very helpful! Thank you!!

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

Hi your tutorial is very usefull :-)

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.

/*
By Amanda Ghassaei
July 2012
http://www.instructables.com/id/Send-and-Receive-M...


*/

byte commandByte;
byte noteByte;
byte velocityByte;

byte noteOn = 144;


void setup(){

Serial.begin(56000);
pinMode(13,OUTPUT);
pinMode(12,OUTPUT);
pinMode(11,OUTPUT);

digitalWrite(13,LOW);
digitalWrite(12,LOW);
digitalWrite(11,LOW);

}

void directblink13(){
digitalWrite(13,HIGH);//turn on led
delay(1000);
digitalWrite(13,LOW);
}
void directblink12(){
digitalWrite(12,HIGH);//turn on led
delay(1000);
digitalWrite(12,LOW);
}
void directblink11(){
digitalWrite(11,HIGH);
delay(1000);
digitalWrite(11,LOW);
}

void checkMIDI(){
do{
if (Serial.available()){
commandByte = Serial.read();//read first byte
noteByte = Serial.read();//read next byte
velocityByte = Serial.read();//read final byte
if (commandByte == noteOn){//if note on message
//check if note == 60 and velocity > 0
if (noteByte == 60 && velocityByte > 0){directblink13;}

else if(noteByte == 61 && velocityByte > 0){directblink12;}

else if(noteByte == 62 && velocityByte > 0){ directblink12;}
}



}

}
while (Serial.available() > 2);//when at least three bytes available
}


void loop(){
checkMIDI();
delay(1);

}

Thanks :-)

fizzlesticks7 months ago

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.

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!

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.

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?

Many thanks! :-)

rice_crisp1 year ago

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?

amandaghassaei (author)  rice_crisp11 months ago

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?

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.

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?


#include <Adafruit_NeoPixel.h>

Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

byte commandByte;

byte noteByte;

byte velocityByte;

byte noteOn = 144;

byte noteOff = 128;

void setup(){

Serial.begin(31250);

strip.begin();

}

void loop(){

checkMIDI();

strip.show();

delay(10);

}

void checkMIDI(){

do {

if (Serial.available()){

commandByte = Serial.read();//read first byte

noteByte = Serial.read();//read next byte

velocityByte = Serial.read();//read final byte

if (commandByte == noteOn){//if note on message

if (velocityByte > 0) {

strip.setPixelColor(noteByte-30, 0, 0, velocityByte);

} else {

strip.setPixelColor(noteByte-30, 0, 0, 0);

}

} else if (commandByte == noteOff) {

strip.setPixelColor(noteByte-30, 0, 0, 0);

}

}

}

while (Serial.available() > 2);//when at least three bytes available

}

Hi Amanda,

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

Leinard9 months ago

sorry, apparently that error appears when I connect to the MIDI output, how do I connect to the application of the piano?

Leinard Leinard9 months ago

does not matter because I decided it was custión create a virtual MIDI port, I installed "loopMIDI" and it worked. thanks for the tutorial, this rather detailed.

Leinard9 months ago
when I try to use the MIDI Hairless and try to connect with the port of arduino, the error "this application has Requested the Runtime to terminate it in an unusual way" shows how I can fix this?
edil101 year ago

Hi Amanda,

Thanks for the excellents Midi Instructables you have shared!

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.

I am planning to build a wireless midi transmissor and that sketch will be the first step.

Thanks in advance for your help.

Edilberto

amandaghassaei (author)  edil101 year ago
have you tried Serial.println(Serial.read()) ?
frikkn1 year ago

hello,

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?

AmpOwl1 year ago

Is there a way you could send the signal through USB directly, without having to use a separate adapter?

AmpOwl AmpOwl1 year ago

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).

amandaghassaei (author)  AmpOwl1 year ago

if you're sending MIDI to your comp, you could run an application like this 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 firmware.

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.

amandaghassaei (author)  AmpOwl1 year ago
You can use the USB on the arduino, I added some info in step 5

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.

amandaghassaei (author)  AmpOwl1 year ago

no, I don't think so.

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?

http://arduino.cc/en/Reference/SoftwareSerial#.Uv8...

http://arduino.cc/en/Tutorial/SoftwareSerial#.Uv8g...

amandaghassaei (author)  AmpOwl1 year ago

you can use this to send serial data to electronics, but I'm not sure it will communicate with your computer.

I want to making you know that I had some trouble making my arduino speaking MIDI. Finally I got it with Hairless Serial<>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.
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.
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.

I haven't tried to receive, manage and process incoming MIDI data. I'm going step by step.

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!

Alberto
which arduino board are you using?
1-40 of 163Next »