8.2 MIDI spec / MIDI port

Uncategorized — roguescience @ 11:59 am

Next use the following spec and image to wire up a midi jack so we can send our MIDI serial data from the Arduino to a MIDI interface using a MIDI cable:

Thanks to ITP Physical Computing for the MIDI OUT schematic.

And finally copy, save, compile and upload the following code to your Arduino:

/*
 * 7.1 Midi OUT controller
 * roguescience.org
 *
 * digital pin 11 (OUTPUT/PWM) --> LED
 * digital pin 2 (INPUT) <-- button
 * analog pin 0 <-- pot
 * tx1 <-- pin 5 (5 PIN DIN aka MIDI jack)
 *
 * Send a MIDI note when the button is pressed and sends MIDI
 * CC data when a potentiometer is turned.
 */

int ledPin = 11;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int buttonPin = 2;               //choose the input pin for a pushbutton
int potPin = 0;                  //choose the input pin for a potentometer
int buttonVal = 0;                    //variable for reading the button status
int buttonState = 0;            //variable to hold the buttons current state
int bounceCheck = 0;            //variable for debouncing
int potVal = 0;                //variable for reading potentiometer value
int mappedPotVal = 0;          //variable for holding remapped pot value
int prevPotVal = 0;               //variable for storing our prev pot value
int THRESHOLD = 2;            //threshold amount

void setup() {
  pinMode(ledPin, OUTPUT);      //declare LED as output
  pinMode(buttonPin, INPUT);     //declare pushbutton as input
  Serial.begin(31250);            //MIDI communicates at 31250 baud
}

void loop(){

  buttonVal = digitalRead(buttonPin);     //read input value from button
  delay(10);                              //wait 10ms
  bounceCheck = digitalRead(buttonPin);   //check again
  if(buttonVal == bounceCheck){           //if val is the same then not a bounce
    if (buttonVal == HIGH && buttonState == 1) {   //check if the input is HIGH
      digitalWrite(ledPin, LOW);         //turn LED OFF
      midiOUT(0x90, 60, 0); //Note ON (CH 1), middle C, zero velocity turns note off
      buttonState = 0;
    }
    if(buttonVal == LOW && buttonState == 0){
      digitalWrite(ledPin, HIGH);       //turn LED ON
      midiOUT(0x90, 60, 127); //Note ON (CH 1), middle C, velocity 127
      buttonState = 1;
    }

  }

   potVal = analogRead(potPin);         //read input from potentiometer
   mappedPotVal = map(potVal, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal - prevPotVal) >= THRESHOLD){
     midiOUT(0xB0, 7, mappedPotVal); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin, HIGH);
     prevPotVal = mappedPotVal;
   }
   else{
      digitalWrite(ledPin, LOW);
   }

}

void midiOUT(char command, char value1, char value2) {
  Serial.print(command, BYTE);
  Serial.print(value1, BYTE);
  Serial.print(value2, BYTE);

}

To test this out we will hook it up to a MIDI interface connected to my computer and see if it can communicate with Garage Band.

5 Comments »

  1. Hi Justin,

    Great series on building a MIDI controller with Arduino. There’s a bug in your code on this page. MIDI CC messages have a range of 0-127, so your call to the map function should be:

    mappedPotVal = map(potVal, 0, 1023, 0, 127); //map value to 0-127

    …instead of 0-255.

    Also, though not 100% a bug, the datatype passed to your midiOUT() function should be byte, not char. While debugging the map() bug I added to midiOUT():

    Serial.print(command, HEX);
    Serial.print(command, DEC);

    If command is a char and 0xB0 is pased in, 0xFFFFFFB0 is printed for the HEX and -80 for DEC, but if command is a byte, all is correct. I’m guessing that when BYTE is passed to Serial.print() the upper bits are masked. Since the data always has a range of byte, it just makes sense to keep everything a byte and not have any data conversion.

    Jeff

    Comment by Jeff — June 16, 2009 @ 6:22 pm
  2. Thanks Jeff! I’ve corrected the code. I think you are probably right about the unnecessary conversion - I’ll look into it.

    cheers,

    Justin

    Comment by roguescience — June 17, 2009 @ 1:27 pm
  3. In the setup do you have to
    pinMode(potPin, INPUT);
    For the pot?

    Comment by Ben — April 11, 2010 @ 12:30 pm
  4. Hi Ben - the ANALOG pins on the Arduino are INPUT ONLY so the pin mode does not have to be specified. ANALOG OUTPUT is emulated using pulse width modulation (PWM) on a DIGITAL pin (which does need to be set to OUTPUT) - see section 4.1 for details i.e. http://roguescience.org/wordpress/?page_id=13

    cheers,

    Justin

    Comment by roguescience — April 11, 2010 @ 1:14 pm
  5. Ah, I missed that page completely, thanks for the explanation, I appreciate it.

    Comment by Ben — April 11, 2010 @ 3:51 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2010 Roguescience Arduino Tutorials | powered by WordPress with Barecity