Programming Midi Shield for Arduino

Hi guys

I'm new to programming and have a question about coding some basic midi functions for the Arduino in conjunction with the Midi Shield.

I'd like to output 2 midi notes from 2 of the shields push buttons and have them sent to the midi output on the shield. The notes are to be played as a 'one shot' (they send out the note when the button is pushed and stop straight away)

The notes can be any 2 midi notes say C1 and C2

Any help much appreciated!

Thanks

Johnny

What have you got so far (code and circuits)?

Please use code tags (the # button on the post screen) around your code. It makes it easier to read. You can edit you previous post to correct this.

I am guessing from your question that you don’t understand the way MIDI notes work. You can search for this on the internet, but this link should get you started MIDI tutorial for programmers

Once you have read that, you will understand what this does

  if(button(BUTTON1) || button(BUTTON2) || button(BUTTON3))
  {
    
    noteOn(0x95,0x3C,0x45);
    digitalWrite(STAT2,LOW);
    while(button(BUTTON1) || button(BUTTON2) || button(BUTTON3));
  }

The same note is sent no matter which button is pressed. This is what you want to change with the note of your choice to something more like this:

  if(button(BUTTON1)
  {
    noteOn(0x95,0x3C,0x45);
    digitalWrite(STAT2,LOW);
  }
   if(button(BUTTON2)
  {
    noteOn(<something else>);
    digitalWrite(STAT2,LOW);
  }   
  if(button(BUTTON3)
  {
    noteOn(<something else again>);
    digitalWrite(STAT2,LOW);
  }
while(button(BUTTON1) || button(BUTTON2) || button(BUTTON3));

btw, I am really not in favour of the while statement locking out anything from happening while one of the button is pressed. This may be ok in test code but it is really bad practice and you should try and get used to working in a more asynchronous manner (look up finite state machines and also get familiar with the techniques used in the BlinkWithoutDelay example).

Johnnydrumz1:
Hi Marco

Thanks for your reply.

I have the shield set up on the Arduino as per this tutorial…

http://www.youtube.com/watch?v=fdY1wfpomxc

I’m just using the example sketch at the moment. I’d like to be able to change the code so it fires a different midi note on each button.

Heres the example code…

#define KNOB1  0

#define KNOB2  1

#define BUTTON1  2
#define BUTTON2  3
#define BUTTON3  4

#define STAT1  7
#define STAT2  6

byte incomingByte;
byte note;
byte velocity;
int pot;

byte byte1;
byte byte2;
byte byte3;

int action=2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {

pinMode(STAT1,OUTPUT);   // declare the LED’s pin as output
  pinMode(STAT2,OUTPUT);

pinMode(BUTTON1,INPUT);
  pinMode(BUTTON2,INPUT);
  pinMode(BUTTON3,INPUT);

digitalWrite(BUTTON1,HIGH);
  digitalWrite(BUTTON2,HIGH);
  digitalWrite(BUTTON3,HIGH);

for(int i = 0;i < 10;i++)
  {
    digitalWrite(STAT1,HIGH); 
    digitalWrite(STAT2,LOW);
    delay(30);
    digitalWrite(STAT1,LOW); 
    digitalWrite(STAT2,HIGH);
    delay(30);
  }
  digitalWrite(STAT1,HIGH);   
  digitalWrite(STAT2,HIGH);

//start serial with midi baudrate 31250 or 38400 for debugging
Serial.begin(31250);     
  //Serial.begin(38400);
  //Serial.println(“MIDI Board”); 
}

//loop: wait for serial data, and interpret the message
void loop () {

/*
   // Button and knob test functions
   if(analogRead(KNOB1) > 512){ digitalWrite(STAT1,HIGH); }
   else{ digitalWrite(STAT1,LOW); }
   if(analogRead(KNOB2) > 512){ digitalWrite(STAT2,HIGH); }
   else{ digitalWrite(STAT2,LOW); }
   
   
   if(!digitalRead(BUTTON1)){ digitalWrite(STAT1,LOW); digitalWrite(STAT2,LOW); }
   else if(!digitalRead(BUTTON2)){ digitalWrite(STAT1,HIGH); digitalWrite(STAT2,LOW); }
   else if(!digitalRead(BUTTON3)){ digitalWrite(STAT1,LOW); digitalWrite(STAT2,HIGH); }
   else if(!digitalRead(BUTTON4)){ digitalWrite(STAT1,HIGH); digitalWrite(STAT2,HIGH); }
   /
 
  //
************** MIDI OUT ***************//

pot = analogRead(0);
  note = pot/8;  // convert value to value 0-127
  if(button(BUTTON1) || button(BUTTON2) || button(BUTTON3))
  {
   
    noteOn(0x95,0x3C,0x45);
    digitalWrite(STAT2,LOW);
    while(button(BUTTON1) || button(BUTTON2) || button(BUTTON3));
  }
  /while(1);
  else
  {
    noteOn(0x90,0x3C,0x00);
    digitalWrite(STAT2,HIGH);
  }
/
 
  //*************** MIDI LOOPBACK *//
  /

  if(Serial.available() > 0)
  {
    byte1 = Serial.read();
    byte2 = Serial.read();
    byte3 = Serial.read();
 
    noteOn(byte1, byte2, byte3);
   
    //digitalWrite(STAT1,HIGH); 
    //digitalWrite(STAT2,HIGH);
  }
/
  //
MIDI IN **************//
  /

  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();

// wait for as status-byte, channel 1, note on or off
    if (incomingByte== 144){ // note on message starting starting
      action=1;
    }
    else if (incomingByte== 128){ // note off message starting
      action=0;
    }
    else if (incomingByte== 208){ // aftertouch message starting
      //not implemented yet
    }
    else if (incomingByte== 160){ // polypressure message starting
      //not implemented yet
    }
    else if ( (action==0)&&(note==0) ){ // if we received a “note off”, we wait for which note (databyte)
      note=incomingByte;
      playNote(note, 0);
      note=0;
      velocity=0;
      action=2;
    }
    else if ( (action==1)&&(note==0) ){ // if we received a “note on”, we wait for the note (databyte)
      note=incomingByte;
    }
    else if ( (action==1)&&(note!=0) ){ // …and then the velocity
      velocity=incomingByte;
      playNote(note, velocity);
      note=0;
      velocity=0;
      action=0;
    }
    else{
      //nada
    }
  }*/
 
}

void noteOn(byte cmd, byte data1, byte data2) {
   Serial.write(cmd);
   Serial.write(data1);
   Serial.write(data2);
}

void blink(){
  digitalWrite(STAT1, HIGH);
  delay(100);
  digitalWrite(STAT1, LOW);
  delay(100);
}

void playNote(byte note, byte velocity)
{
  int value=LOW;
  if (velocity >10){
    value=HIGH;
  }
  else{
    value=LOW;
  }

//since we don’t want to “play” all notes we wait for a note between 36 & 44
  if(note>=36 && note<44)
  {
    byte myPin=note-34; // to get a pinnumber between 2 and 9
    digitalWrite(myPin, value);
  }

}

char button(char button_num)
{
  return (!(digitalRead(button_num)));
}
[/quote]

Thanks so much for your time and help Marco.

I'm gonna check all this stuff out Monday and let you know how I get on!

Best

Johnny

Hi Marco

Its now changing the notes thank you!

I’ve had a read of how midi notes work, i’m just not entirely sure where to enter this information. Could you help me with where to enter the ‘Note off’ code? I’d like the notes to send out a single hit and stop straight away.

This is what i have so far:

#define BUTTON1  2
#define BUTTON2  3
#define BUTTON3  4



#define STAT1  7
#define STAT2  6

byte incomingByte;
byte note;
byte velocity;
int pot;

byte byte1;
byte byte2;
byte byte3;


int action=2; //0 =note off ; 1=note on ; 2= nada

//setup: declaring iputs and outputs and begin serial
void setup() {

  pinMode(BUTTON1,INPUT);
  pinMode(BUTTON2,INPUT);
  pinMode(BUTTON3,INPUT);


  digitalWrite(BUTTON1,HIGH);
  digitalWrite(BUTTON2,HIGH);
  digitalWrite(BUTTON3,HIGH);


  for(int i = 0;i < 10;i++)
  {
    digitalWrite(STAT1,HIGH);  
    digitalWrite(STAT2,LOW);
    delay(30);
    digitalWrite(STAT1,LOW);  
    digitalWrite(STAT2,HIGH);
    delay(30);
  }
  digitalWrite(STAT1,HIGH);   
  digitalWrite(STAT2,HIGH);
 
 //start serial with midi baudrate 31250 or 38400 for debugging
 Serial.begin(31250);     
  //Serial.begin(38400); 
  //Serial.println("MIDI Board");  
}

//loop: wait for serial data, and interpret the message
void loop () {


  /* 
   // Button and knob test functions
   if(analogRead(KNOB1) > 512){ digitalWrite(STAT1,HIGH); }
   else{ digitalWrite(STAT1,LOW); }
   if(analogRead(KNOB2) > 512){ digitalWrite(STAT2,HIGH); }
   else{ digitalWrite(STAT2,LOW); }
   
   
   if(!digitalRead(BUTTON1)){ digitalWrite(STAT1,LOW); digitalWrite(STAT2,LOW); }
   else if(!digitalRead(BUTTON2)){ digitalWrite(STAT1,HIGH); digitalWrite(STAT2,LOW); }
   else if(!digitalRead(BUTTON3)){ digitalWrite(STAT1,LOW); digitalWrite(STAT2,HIGH); }
   else if(!digitalRead(BUTTON4)){ digitalWrite(STAT1,HIGH); digitalWrite(STAT2,HIGH); }
   */
  
  //*************** MIDI OUT ***************//

  pot = analogRead(0);
  note = pot/8;  // convert value to value 0-127
  if(button(BUTTON1))
  {
    
    noteOn(0x95,79,0x45);
    digitalWrite(STAT2,LOW);
  }
  
   if(button(BUTTON2))
  {
    noteOn(0x95,78,0x45);
    digitalWrite(STAT2,LOW);
  }   
  if(button(BUTTON3))
  {
    
    noteOn(0x95,77,0x45);
    digitalWrite(STAT2,LOW);
  }
while(button(BUTTON1) || button(BUTTON2) || button(BUTTON3));
  }
  
  //*************** MIDI LOOPBACK ******************//
  /*
  if(Serial.available() > 0)
  {
    byte1 = Serial.read();
    byte2 = Serial.read();
    byte3 = Serial.read();
  
    noteOn(byte1, byte2, byte3);
    
    //digitalWrite(STAT1,HIGH);  
    //digitalWrite(STAT2,HIGH);
  }*/


void noteOn(byte cmd, byte data1, byte data2) {
   Serial.write(cmd);
   Serial.write(data1);
   Serial.write(data2);
 }

void blink(){
  digitalWrite(STAT1, HIGH);
  delay(100);
  digitalWrite(STAT1, LOW);
  delay(100);
}


void playNote(byte note, byte velocity)
{
  int value=LOW;
  if (velocity >10){ 
    value=HIGH; 
  }
  else{ 
    value=LOW; 
  }

  //since we don't want to "play" all notes we wait for a note between 36 & 44
  if(note>=36 && note<44)
  { 
    byte myPin=note-34; // to get a pinnumber between 2 and 9
    digitalWrite(myPin, value);
  }

}

char button(char button_num)
{
  return (!(digitalRead(button_num)));
}

Cheers!

Johnny

while(button(BUTTON1) || button(BUTTON2) || button(BUTTON3));

This waits until you have stopped pressing the button.

It seems to me easiest to just send a note off command once the button is not pressed (ie, straight after this part of the code). I am not sure that you will hear anything if you just sent a note on then note off immediately afterwards.

Note this will only work because you have this busy loop in your code (bad practice, actually). In a more general environment you would detect when a button goes from off to on, send the note on, then detect when the button goes from on to off and send the note off. An alternative way is to do it after a certain time, in which case the technique is similar to the blinkwithoutdelay example.

Also know that a note on command with a 0 velocity is the same as note off.

Thank you Marco.

I must admit this is a little out of my depth. could u give me an example of what it would look like within the code I have already, using your method of detecting when a button goes from off to on and vice versa?

I would suggest that you start by turning a note off when you have released the button (after the while loop). Note off is the same as note on with the velocity set to zero. You have already done note on.