Saturday, 28 February 2015

MIDI for the Arduino - Arduino MIDI Library Input Test

Testing, Testing, 1 2 3


In this installment of the MIDI for the Arduino series, we will get our hands dirty with the software side of this project and take a look at working with the Arduino MIDI Library.

If you are new to this series, check out the last installment where we build up the Midi Input Circuit and connect it to the Arduino.

For this tutorial I am using version 4.2 of the MIDI Library and version 1.6.0 of the Arduino IDE. If you are using other versions - your mileage may vary ;)

The Arduino Midi Library can be downloaded HERE.

The MIDI Input Test program file can be found HERE.

Watch the video below for the tutorial.


24 comments:

  1. First off - great series on MIDI. This was the most straight-forward how-to I have found.

    I have an application in which I need to identify a single control change and set a pin to high (I am using a solid state relay shield)

    I tried to find documentation to that explained the correct way...but have resorted to throwing code spaghetti at the wall to see what sticks...so, nothing has.

    I have tried so many different attempts - I do not know what to try next. Here I thought I could just try and match anything with a second data-byte of 10 - but no luck.

    void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
    if (velocity = 10) digitalWrite (LED1, HIGH); //not working

    Any ideas to get my headed in the right direction?
    Thank you,

    CG

    ReplyDelete
    Replies
    1. Hi Chris. Glad you enjoyed the tutorial. If I understand you correctly, you are trying to have one note on the keyboard trigger your LED.

      To do this you will want to read the "pitch" variable instead of velocity. Lets say you want middle C on the keyboard to be the trigger note (Middle C is MIDI note 48). Your code would look like:

      if (pitch == 48) digitalWrite (LED1, HIGH);

      Remember to use '==' instead of '=' when testing if a variable is equal to something. Hope this helps. Dave.

      Delete
    2. Thanks for the fast response Dave,

      The midi command is coming from a video switcher and the "velocity" or data-byte2 seems to be important. Here is the MIDI info that I have "sniffed" when selecting different inputs on the unit.

      Type DATA1 DATA2 CHAN NOTE EVENT

      Input 1
      B0 0D 10 1 --- Control Change
      Input 2
      B0 0D 11 1 --- Control Change
      Input 3
      B0 0D 12 1 --- Control Change
      Input 4
      B0 0D 13 1 --- Control Change
      Still
      B0 0D 14 1 --- Control Change

      Thank you for the reminder on the "==", I wonder if that has caused some of my issues.

      CG

      Delete
    3. OK, that makes more sense. The switcher is putting out MIDI CC messages so you will want to handle them with a control change function. The first byte B0 means (CC Message - Chanel 1).
      The second byte 0D means (Controller ID# 13).
      The third byte 10 means (Controller Value = 16)
      As you are pushing the buttons, the switcher is changing the value of Controller #13 to 16,17,18,19,20 (I'm converting the HEX to decimal)
      You could capture the values from this control with the following:

      MIDI.setHandleControlChange(MyCCFunction);

      void MyCCFunction(byte channel, byte number, byte value){
      if (number == 13){
      if(value == 16) digitalWrite(LED1, HIGH);
      if(value == 17) digitalWrite(LED2, HIGH);
      }
      }

      Delete
    4. Thank you! That worked. Now I need to do a bit of if/else statement work.

      Thanks again,

      CG

      Delete
    5. Coding hint:
      For comparisons to constants, you can put the comstant in front:
      if (48 == x) ...
      This will lead to a syntax error if you write = instead of ==.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Hi, works so good, thanks.. I would like to put a note number and not a simple "pitch", becouse I need to light up a LED when I press note C3, another LED with note D3, and so on...
    How can I do?
    thanks so much

    ReplyDelete
    Replies
    1. Hi EnomYs. I'm glad things are working for you! The value that is passed to the pitch variable is the note number. You can use it to turn on your less. example if (pitch == 60) digitalWrite(LED1, HIGH); **LED1 is the arduino pin number of your led**

      Delete
    2. thanks for answer... where I should put the modification? inside void loop?

      Delete
    3. Hi, I made some change and it works great. I send a midi sequence from Logic Pro9 and trigger the input of a drum machine Oberheim DMX.

      #include // Add Midi Library



      //Create an instance of the library with default name, serial port and settings
      MIDI_CREATE_DEFAULT_INSTANCE();

      void setup() {
      pinMode (2, OUTPUT); // Kick
      pinMode (3, OUTPUT); // Snare
      pinMode (4, OUTPUT); // Hit Hat
      MIDI.begin(10); // Midi channel

      MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
      // tells the Midi Library which function you want to call when a NOTE ON command
      // is received. In this case it's "MyHandleNoteOn".
      MIDI.setHandleNoteOff(MyHandleNoteOff); // This command tells the Midi Library
      // to call "MyHandleNoteOff" when a NOTE OFF command is received.
      }

      void loop() { // Main loop
      MIDI.read(); // Continuously check if Midi data has been received.
      }

      void MyHandleNoteOn(byte channel, byte pitch, byte velocity) {
      if (channel == 10) //Works only with MIDI channel 10
      {
      if (pitch == 36)
      digitalWrite(2,HIGH); //Turn Kick on

      if (pitch == 38)
      digitalWrite(3,HIGH); //Turn Snare on

      if (pitch == 42)
      digitalWrite(4,HIGH); //Turn Hit Hat on

      }

      }

      void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {
      if (channel == 10)
      {
      if (pitch == 36)
      digitalWrite(2,LOW); //Turn Kick off
      if (pitch == 38)
      digitalWrite(3,LOW); //Turn Snare off
      if (pitch == 42)
      digitalWrite(4,LOW); //Turn Hit Hat off
      }

      }

      Delete
  4. Thanks for the great tutorial. I finally got it to work after hearing the 'disconnect the RX pin before uploading the program' part. My question is, does this mean using the Arduino IDE Serial Monitor is not an option? Or does Serial out still work? I'd really like a better way than LEDs to debug what I want to do next.

    ReplyDelete
    Replies
    1. Put a 1n914 Diode between RX and Pin 6 on Optocoupler, so can you upload code without disconnect the RX pin

      Delete
  5. Awesome, one of the few real straightforward how-to's amidst a lot of vague information! On top of that everything is produced with professional quality, thanks!

    ReplyDelete
  6. Hi. I want to make a midi unit that adds swing to the original midi signal. I assume that I would make the input and the midi output. I wonder whether a code for this function exists somewhere and if not, whether or not it would be a relatively straightforward? Any thoughts greatly relieved. Love the clear videos that you produce. Cheers. Simon

    ReplyDelete
  7. I hope you don't mind, but I need some help downloading your
    test file. I am on Linux mint and was wondering if there is a way to download it. Right now it takes me to a page with a button that is not clickable. Thanks

    ReplyDelete
  8. Hey, I am trying to use the Control Change function with an Tlc5940. But how ever this dont work:

    void MyCCFunction(byte channel, byte number, byte value) {
    switch (number) {
    case 21:
    mapval = map(value, 0, 127, 0, 16); //Map the Output
    Tlc.set(mapval, brightness); //Write to Mux
    Tlc.update(); //Update Mux
    }

    Any Ideas?

    ReplyDelete
  9. Can I use this code to control the zoom ms70cdr?

    ReplyDelete
  10. Fantastic work and tutorials. This is coming rather late so I hope you see it, I built the circuit add it works great, now I was wondering how to modify the sketch so I can use multiplexers for my LED outputs.

    How you see it.
    Thanks and God bless

    ReplyDelete
  11. Awesome tutorials. Congrats. I have a question, probably trivial but not for me. How do we deal with chords, i.e. multiple notes? It seems that MyHandleNoteOn just handle one note (pitch) at once. Is that correct? How do we enable chords by using MyHandleNoteOn? Are there other alternatives possible?

    Thanks,
    Cheers

    ReplyDelete
  12. Did you solve it ? im also intressed in this.

    ReplyDelete
  13. Hola Dave, estoy tratando de encender y apagar un motor a pasos NEMA 17, a través de mensaje MIDI.
    Tome tu código del encendido del led y pegue el código del motor.
    Para el envío del mensaje, estoy utilizando CUBASE.
    El si se enciende, pero el motor no se mueve.
    A continuación te envío el código, y te agradecería cualquier comentario.

    #include // Add Midi Library
    #include

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

    #define STEP 4 // pin STEP de A4988 a pin 4
    #define DIR 5 // pin DIR de A4988 a pin 5
    #define ENABLE 2 // PIN ENABLE de A4988 a pin 2
    #define M1 10 // pin M1 de 4988 a pin 10
    #define M2 11 // pin M2 de 4988 a pin 11
    #define M3 12 // pin M3 de 4988 a pin 12

    int potenciometro; // lectura del potenciometro
    int pot_mapeado;
    int vel_motor;

    //Create an instance of the library with default name, serial port and settings
    MIDI_CREATE_DEFAULT_INSTANCE();

    void setup() {

    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 notes on channel 2 only.

    pinMode (LED, OUTPUT); // Set Arduino board pin 13 to output

    //Serial.begin(9600);
    pinMode(STEP, OUTPUT); // pin 4 como salida
    pinMode(DIR, OUTPUT); // pin 5 como salida
    pinMode(M1, OUTPUT); // PIN 10 como salida
    pinMode(M2, OUTPUT); // PIN 11 como salida
    pinMode(M3, OUTPUT); // PIN 12 como salida

    MIDI.setHandleNoteOn(MyHandleNoteOn); // This is important!! This command
    // tells the Midi Library which function you want to call when a NOTE ON command
    // is received. In this case it's "MyHandleNoteOn".
    MIDI.setHandleNoteOff(MyHandleNoteOff); // This command tells the Midi Library
    // to call "MyHandleNoteOff" when a NOTE OFF command is received.


    }

    void loop() { // Main loop
    MIDI.read(); // Continuously check if Midi data has been received.



    }

    // MyHandleNoteON is the 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

    pot_mapeado = velocidad();

    digitalWrite(ENABLE, LOW);
    digitalWrite(M1, HIGH); // control con micropasos
    digitalWrite(M2, HIGH); // a un 1/16
    digitalWrite(M3, HIGH); //
    digitalWrite(DIR, HIGH); // giro en sentido horario


    digitalWrite(STEP, HIGH); // nivel alto
    //delayMicroseconds(pot_mapeado);
    delayMicroseconds(250);
    digitalWrite(STEP, LOW); // nivel bajo
    //delayMicroseconds(pot_mapeado);
    delayMicroseconds(250);

    }

    // MyHandleNoteOFF is the function that will be called by the Midi Library
    // when a MIDI NOTE OFF message is received.
    // * A NOTE ON message with Velocity = 0 will be treated as a NOTE OFF message *
    // It will be passed bytes for Channel, Pitch, and Velocity
    void MyHandleNoteOff(byte channel, byte pitch, byte velocity) {
    digitalWrite(LED,LOW); //Turn LED off

    digitalWrite(ENABLE, HIGH);
    }


    //FUNCION PARA LEER EL POTENCIOMETRO

    int velocidad(){
    potenciometro = analogRead(A0); // leemos el potenciometro
    int nuevo_potenciometro = map(potenciometro,0,1024,30,2500); // adaptamos el valor leido a un retardo
    return nuevo_potenciometro;
    }

    ReplyDelete
  14. You should take part in a contest for one of the best blogs on the web. I will recommend this site!

    Linkfly.to
    Information
    Click Here
    Visit Web

    ReplyDelete