Saturday, 28 January 2012

Fun with Arduino - Midi Input Basics

Midi In - "Hello World!"

Check out this video for a detailed Analysis of the Midi Circuit.

For a real world look at this circuit in action, check out the NaV-1 Arduino synth construction series.


Have you ever been working on a Arduino project and suddenly thought 'This thing could really use a MIDI Input'! This exact thing just happened to me. Not wanting to re-invent the wheel, I began searching around for a Library that would help. I came across the Arduino Midi Library which seemed to fit the bill. It took me a while to actually get the thing going, so I thought I would write a quick post outlining the steps to get a simple test circuit working. The following program and circuit will simply Flash the LED connected to Pin 13 on the Arduino Board when you press a note on a Midi Keyboard. But, that's really all you really need to confirm that you are correctly receiving Midi commands with your Arduino.

The Midi In Circuit

Flashing LED means you Win!!

The Arduino Midi Library

First go to this Link and download the Arduino Midi Library files.

Unzip the downloaded folder. There are two folders inside. For Windows, copy the folder called "MIDI" and paste it into your Arduino "libraries" folder. Mine was located inside the "arduino-0022" folder. Quit and restart your Arduino IDE program. Go to the Menu and open Sketch > Import Library. You should see "MIDI" as one of the choices.

Copy and paste the code at the end of this article into a new Sketch. The code is commented, so give it a quick read through.

Here are some of the key commands:

MIDI.begin(MIDI_CHANNEL_OMNI);
This initializes the Midi Library. The MIDI_CHANNEL_OMNI parameter sets the library to listen to all Midi Channels. MIDI.begin(2) would set it to listen to Channel 2 only.

MDI.setHandleNoteOn(MyHandleNoteOn);
This is an import command! The Arduino Midi Library uses something called 'Callbacks'. When a Midi event occurs, the Library will Call a function to handle it. This command tells the Library to call the 'MyHandleNoteOn' function when a 'Note On' Midi event is detected. There are many callback functions in the Library to handle the many types of Midi events (Clock, Pitch Bend, Program Change, Etc..). Use the MIDI.set... command to point to the functions you require.
 
void MyHandleNoteOn(byte channel, byte pitch, byte velocity)
This is the function I created to be called when a Midi Note On event is detected. This is the 'meat' of your program.  In this test program, I just have it flash the LED on the Arduino board. But you could just as easily have it play a note on your home made Synth circuit, Flash a spotlight on your Midi controlled lighting rig, or even command your Midi controlled Robotic Gorilla to enter 'Rampage' Mode. The sky is the limit.

MIDI.read();
This is the only function in the main loop of the program. It just checks the input buffer for any received Midi commands and passes them to the correct function.


The Hardware

The MIDI standard spells out the circuit that should be used for a MIDI INPUT so lets look at that first.

Arduino Midi In Circuit Schematic

Midi In Circuit on the Breadboard
This very simple circuit uses a 6N138 optocoupler chip. This device basically electrically isolates your circuit from the incoming Midi signal. The 1N914 diode protects the chip from an incorrectly wired Midi cable. Plug the output of the optocoupler (Pin 6) into the RX (Pin 0) socket on your arduino board. Note: Be sure to correctly identify pin 4 and 5 on the Midi In Jack.

Also note that the RX/TX pins and the USB Port on the Arduino Board share the same signals. So, you will need temporarily remove the wire from the RX Pin 0 on the Arduino Board to upload a program. Then remove the USB Cable from the computer and replace the RX wire when you run the program with a Midi Input.

  
That's really all there is to it! Connect the Midi Out port on a Midi Keyboard to the Midi In Jack on your Arduino. If the little LED next to Pin 13 on the Arduino Board flashes when you hit a key, you are correctly recieving the Midi Data. Have fun!

For a real world look at this circuit in action, check out the NaV-1 Arduino synth construction series.

Copy the following code and paste into a new Arduino Sketch:

#include <MIDI.h>  // Add Midi Library

#define LED 13    // Arduino Board LED is on Pin 13

// Below is my function that will be called by the Midi Library
// when a MIDI NOTE ON message is received.
// It will be passed bytes for Channel, Pitch, and Velocity
void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
  digitalWrite(LED,HIGH);  //Turn LED on
  if (velocity == 0) {//A NOTE ON message with a velocity = Zero is actualy a NOTE OFF
    digitalWrite(LED,LOW);//Turn LED off
  }
}

void setup() {
  pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output
  MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
// OMNI sets it to listen to all channels.. MIDI.begin(2) would set it
// to respond to channel 2 notes only.
  MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
  // tells the Midi Library which function I want called when a Note ON command
  // is received. in this case it's "MyHandleNoteOn".
}

void loop() { // Main loop
  MIDI.read(); // Continually check what Midi Commands have been received.
}

41 comments:

  1. Replies
    1. Thanks! Glad you enjoyed it.

      Delete
    2. Your breadboard diagram has an error. The diode should be at the optocoupler input not at the connector.

      Delete
    3. You are correct! I totally missed that. Thx. Functionally, it should be fine either way but I'll try to correct the diagram soon.

      Delete
  2. I have no idea what i can't seem to get this to work. Is there something I'm missing? I'm more or less following the breadboard diagram since, you know, i'm mostly an idiot.

    ReplyDelete
    Replies
    1. Hi WB. Sorry you're having trouble. What version of the Arduino IDE and Midi Library are you using? I wrote this with IDE .0022 and Midi Library V3.1.1. Are you able to compile and upload the program successfully? Here are a few things to check. Make sure that the pins on your Midi jack are correct. Remember to remove the wire from the Arduino RX pin to upload the program, then replace it to run. Make sure your keyboard is actually set to send Midi data. Let me know if this helps.

      Delete
    2. Hey Dave, Well at one point when I pressed on note on my Korg the light turned on never to turn off again. Now I'm not getting anything at all, I'm afraid I've messed up the wiring. I'm using Midi Library V3.2 and I'm not sure what version of IDE i'm using I suppose 1.0

      Delete
    3. Hey WB. If you like, send some pictures of your circuit to the email address in the "Contact" tab at the top of the page. I'd be glad to take a look.

      Delete
    4. Hey Dave, Sent it out. If you need anymore photos let me know. I really appreciate you helping with this.

      Delete
    5. I'm running into the same problem with my circuit, did you figure out WB's problem?

      Delete
    6. I believe I fixed his problem. You want to check the orientation of your Midi jack and make sure you have it connected correctly. The breadboard diagram picture may be a bit confusing as the Midi jack is shown facing toward you (this was the only midi jack graphic I could find). I added the actual pin numbers in red underneath to try to make it clearer. If you look at the actual picture of the circuit at the top of the page, you can see how the jack is actually oriented on my board. Let me know if this helps.

      Delete
    7. I recently also had a problem using the same circuit on an Uno R3. As well as temporarily removing the RX to upload the firmware via USB, I found I needed to unplug the USB from the computer before the MIDI signal was seen by the library. Luckily I had a USB wall wart available to power the board :)


      So, the process was as follow:


      A) Uploading Firmware

      1. unplug RX
      2. Plug USB into both Uno and development PC.
      3. Upload firmware.

      B) Running

      1. Reconnect RX
      2. Disconnect Uno from development PC.
      3. Apply power to Uno via jack socket and appropriate power source, or power via USB connected to a non computerpower source, such as a wall wart

      Delete
  3. hey, nice setup! Do you think it could be use to control that kind of strip with midi information : http://www.adafruit.com/products/306 ?

    ReplyDelete
  4. sorry I meant that one : http://www.adafruit.com/products/683

    ReplyDelete
    Replies
    1. Hi jkor. You could easily control that via Midi. Just replace the code inside the "MyHandleNoteOn" function with the code to drive the LEDs. Every time a Midi note is received the MyHandleNoteOn function is called.

      Delete
  5. Hi Dave,
    I think that this rgb led strip looks too weak for a stage show. I'm thinking of using a blinkM/MaxM chain with your Midi IN arduino setup. Do you have example of the http://arduino.cc midi library interfacing with blinkM/MaxM?
    Thanks for your help!

    ReplyDelete
  6. If i wanted a LED on 12 to light if one note was played, but an LED on 11 to light if another was played, how can I set certain ports to respond to certain channels?

    ReplyDelete
    Replies
    1. Hi Steve

      Are you trying to track different midi note numbers or midi channel numbers?

      Delete
  7. Hej dave,

    i'm currently in my last year of school studying electricity/electrotechnics and for my end project I chose to make a ArduinoMidicontroller wich can both send and recieve MIDI data (the recieving end for some LED indications that my teacher ensists that i put in my project )

    the recieving part is were I have a lot of questions and read many different things about.

    Is it possible, with this library, to f.e. recieve a CC(cutoff filter or something) and that it analyses that signal and i can assign the value of that CC to a led that is at is brightest when at 127 and off at 0 using analog out or PWM?
    How should I best approach this?
    and sorry for my bad English spelling..

    Thanks in advance

    Vadim

    ReplyDelete
    Replies
    1. Hi Vadim

      Welcome to the blog! You can modify the code in the article to 'listen' to CC messages instead by doing the following:

      First set the callback function
      MIDI.setHandleControlChange(myCCfunction);

      Every time a CC message is received, the function you specify will be called. The MIDI Library will pass the Channel, Controller Number, and Value of the CC that triggered it to your function.

      The function will look something like this:

      void myCCfunction (byte channel, byte number, byte value){

      if (number == 1){ ***example listen to CC #1***
      setLEDbrightness(value); **Call your LED function**
      }
      }

      I'll let you figure out setting the LED brigtness function. Good luck with your project!

      Delete
    2. Hi Dave,

      thanks for the quick reply !
      I'll experiment with the code later this day.
      For what I see from this code it's exactly what I was looking for. thank you !Hope I can get it to work.
      fingers crxssed.

      Delete
    3. Hi Dave,

      so I did some test today and i couldn't get the LED to flash when it got MIDI data.
      here's what I did:

      -Doublechekked if every connection is correct
      -tested if my midikeyboard sends signals( with midiOx thru tascam us-122)
      -Installed midi library (compiling sketch gave no errors so I supose I installed it correctly)
      -uploaded your sketch whith rx pin free of connection from MIDIIn circuit
      -connected midiIn circuit to rxPin
      -connected 9v adapter to arduino
      -disconnected USB from arduinoUNO
      -played some notes on my keyboard.
      and tried several of these steps in different orders.

      but it won't work.. something I missed?
      also I noticed when I run any kind of serial sketch on my arduino f.e. serial.print something and I cut the power by removing usb and then plugging it back in it stops the transmission... don't know if this has anything to do with it.. reallly need some help with this, can't figure out what I'm doing wrong.

      thanks in advance,
      best regards,
      Vadim

      Delete
    4. Hey Vadim

      If you can, send some pictures of your circuit to the email address in the "Contact" tab at the top of the page. I'll take a look.

      Delete
  8. Hi Dave,
    I have a school project which receives MIDI messages from an electronic keyboard and program the Arduino to process this and activate pumps to create a water fountain. This is the first time I am doing an electronic project and I am thankful that I found your post which I can use for the first part of my project. I am still researching on the approach for the second part of my project.
    I understand that MIDI messages can be sent on 16 different channels, how do I determine which channel is used to send MIDI messages from my electronic keyboard to my MIDI jack?
    In you case, you have set your channel to 2, how do you determine that?

    Sorry if my questions appear to be very basic as I do not have prior experience with electronic project or Arduino. I will be grateful if you could help me with my queries.

    Thanks and regards,
    electronicrookie

    ReplyDelete
    Replies
    1. Hi electronicrookie,
      Welcome to the blog! That sounds like quite a project you've got going. I'd love to see what you come up with.

      Your keyboard will have a 'Midi Channel' setting that can be set from 1 to 16 or to OMNI. (OMNI means that it will broadcast on all channels). The idea is that you could have 16 different synths all hooked up you keyboard controller and by changing the channel number, you could select which synth you wanted to hear.

      On the receiving end, you would set your device to receive Midi commands on a certain channel (channel 2 for example). It would then ignore all information not on channel 2.

      In my example code, I set it to OMNI mode so it will receive any information on any channel with the line MIDI.begin(MIDI_CHANNEL_OMNI); If I only want to recieve on channel 2 I would change this to MIDI.begin(2);

      Hope this helps

      Delete
    2. Thanks, Dave! Will check out my keyboard.

      electronicrookie

      Delete
  9. Hi Dave,

    You are right! I could get the MIDI channel from my keyboard, it has been preset to '01'.

    I have some questions regarding sketches:
    1) A sketch is stored in the Flash memory of the arduino microcontroller after I have uploaded it to the board from my computer, does it mean there is no need to connnect my USB cable from my computer to the board when I run the sketch on my board? Is it necessary to power my arduino board with an external battery or can the board run on its own?

    2) Can the board be uploaded with several sketches? Or does it keep only the latest one uploaded?

    Thanks again!

    electronicrookie

    ReplyDelete
    Replies
    1. Hi ER

      Glad it worked for you. To answer your questions:

      1) Yes, once the sketch is loaded, the arduino will run independently without USB connection. You will need to power it with an external adapter. Read this http://playground.arduino.cc/Learning/WhatAdapter

      2) The Arduino can only store one sketch at a time.

      Good Luck

      Delete
    2. Hi Dave,

      I am going to start creating the circuit and arduino sketch but I have problem locating your codes from the MIDI library which I downloaded.

      All I could get is '#include ' when I accesses the MIDI folder. Is there somewhere else that I can find your codes?

      Thanks,
      ER

      Delete
    3. I meant '#inlcude '

      ER

      Delete
    4. Hi Dave,

      You have mentioned that RX0 must be disconnected when uploading program to arduino.

      After uploading the program and reconnecting RX0, can I also reconnect the USB cable to power the arduino? Or do I have to use an external power source such as a battery pack?

      Thanks and regards,
      electronicrookie

      Delete
    5. Hi ER

      1) You don't have to access the MIDI folder. Just install it to the Arduino Library as described. Then forget about it.. Copy and paste the code at the end of my article into a new sketch and upload.

      2) You can leave the USB cable plugged in. Just unplug the RX0 wire when you upload sketch and plug back in to run. If the Arduino is receiving MIDI data while trying to upload a sketch they will conflict and your sketch will not upload.

      Delete
    6. Hi Dave,

      I have done the circuit and uploaded the sketch to arduino but not getting any response.

      I have emailed some photos to you, grateful if you could tell me what I have done wrong.

      Thanks!

      Delete
  10. I used the schematic above for a MIDI project I'm working on. The pinout on the MIDI jack is weird, I had to reverse the connections for pins 4 and 5 to get it to work at all. And then I kept getting random read failures (the serial reads were getting the wrong values). Eventually I figured out that I needed to tie ping 7 of the optoisolator to ground with a 1k resistor, now it works perfectly.

    Got the updated schematic here:

    http://www.electro-tech-online.com/microcontrollers/116584-midi-thru-using-6n138-74hc14.html

    ReplyDelete
  11. Hi!

    Total NOOB here. Question: I only want to receive Program change messages and have the arduino turn off/on leds or relays with them. Is this the blog to learn how to do this? Or is it easier just to program the arduino to do something when it gets 0xC0 and not include the midi library? big thanks!! great blog!!

    ReplyDelete
  12. Hi Dave,

    imho your code is not correct (anymore). The led will never switch off. You try to switch off the led in your function "MyHandleNoteOn()" calling from
    MIDI.setHandleNoteOn(MyHandleNoteOn);
    in your setup function.
    But: A NoteOff event has to be called from "HandleNoteOff()". Adding a
    MIDI.setHandleNoteOff(MyHandleNoteOn); would fix the code.

    Great site anyway :)

    ReplyDelete
  13. Hi Dave, how would you make this listen to say 8 different midi notes, would you have to set a different name for each, any chance of posting a quick example? Also do you have to set note offs to turn LEDs off?

    Thx

    ReplyDelete
    Replies
    1. Hi BBBB. Parsing incoming MIDI data is pretty straight forward (with a couple of exceptions). When the MIDI Library receives Note Data, it will call the function you set and pass a Channel number, a Note Number, and a Velocity number. Your function can use these numbers to play the correct note on your sound source (whatever that may be). In my sample code I used a note with Velocity=0 as a note off (turn the light off). It keeps the code simpler for this example.

      You just need to keep track of the notes that are playing and make sure they get shut off when the key is released. Check out my NaV-1 project to see how I coded this for a Mono Synth. One thing you need to account for is if someone holds a key down, then presses and releases a second key. The code should remember the original key and re-trigger it (think of a trill between two keys). Kind of hard to describe this in a comment so I hope it makes some sense. Good luck!

      Delete
  14. what a great post, thank you for clearifying a lot for me :)

    ReplyDelete