Having trouble with MIDI code

Hi guys,

I’ve been struggling for days with this code.

Im trying to call a function based on a MIDI note the Arduino Received. I’m not far from finding the right code but I can’t find the thing I’m doing wrong here :frowning: If you could help …

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
 
int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //what's the first note?  36 is C1 in Ableton
 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate baloon1
VarSpeedServo servoI2;   // create servo object to control a servo that Inflate balloon2



// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs
  servoI1.attach(8);   // Set I1 servo to digital pin 8
  servoI2.attach(9);   // Set I2 servo to digital pin 9

  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
}

void infslow1 () {   // Monte 1 lentement
  servoI1.write(45, 5, true); 
  delay (100);
  servoI1.write(32, 0, true);
}

void infslow2() {    // Monte 2 lentement
  servoI2.write(45, 0, true); 
  delay (100);
  servoI2.write(32, 0, true); 
}

void loop () {

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }else if (incomingByte== 127+chan){ // note off message starting
      action=0;
 
    }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      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) ){ // if we received a "note on", we wait for the note (databyte)
      velocity=incomingByte;
      moveServo(note, velocity);
      note=0;
      velocity=0;
      action=0; 
    }else{
      //nada
    }
 }
}

void moveServo(byte note, byte velocity){    //  call a function based on the note
  
switch (note){
  case lowNote: //if it's not 60
  infslow1 ();
  break;
}
  
}

Do any of you guys knows where my mistakes are?

Thanks a lot for your help

I've cheated a bit by changing the end of the code, it does work (only the first function) so I'm not far from the end but still stuck as I'm sure this is not the right way to do it.

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    if (incomingByte== 127+chan){ // note off message starting
      action=0;
      
    }else if ( (action==1)&&(note=lowNote) ){ // if we received a "note on", we wait for the note (databyte)
      infslow1 ();
    }else if ( (action==1)&&(note=lowNote+1) ){ // if we received a "note on", we wait for the note (databyte)
      infslow2 (); // this doesn't work
     
    }else{
    }
    }
   
    }
    }
    
//write an angle based on velocity to our servo

change:

    }else if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)

to

    }

    if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)

Thanks for your reply,

I’ve chanded the code as you suggested but although it does compile, it does not work :frowning:

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
 
int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //Note to be played at first
 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate baloon1
VarSpeedServo servoI2;   // create servo object to control a servo that Inflate balloon2



// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs
  servoI1.attach(8);   // Set I1 servo to digital pin 8
  servoI2.attach(9);   // Set I2 servo to digital pin 9

  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
}

void infslow1 () {   // Inflate baloon 1 slowly
  servoI1.write(45, 5, true); 
  delay (100);
  servoI1.write(32, 0, true);
}

void infslow2() {    // Inflate balloon 2 slowly
  servoI2.write(45, 0, true); 
  delay (100);
  servoI2.write(32, 0, true); 
}

void loop () {

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }else if (incomingByte== 127+chan){ // note off message starting
      action=0;
    }
    if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      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) ){ // if we received a "note on", we wait for the note (databyte)
      velocity=incomingByte;
      moveServo(note, velocity);
      note=0;
      velocity=0;
      action=0; 
    }else{
      //nada
    }
 }
}

void moveServo(byte note, byte velocity){    //  call a function based on the note
  
switch (note){
  case lowNote: //if it's not 60
  infslow1 ();
  break;
}
  
}

I’ve also changed the other }Else if by } If but it doesn’t work as well.

Any ideas?

You can see my second post where I’ve changed the end of the code by replacing note=0 by note=lowNote and it worked for ONE function even though that wasn’t the correct thing to do

You need to have a look at if...else...

You can't do this for example:

    }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) ){

because the second if clause is the same as the first, the code in that block will never get executed.

 note=incomingByte;
      note=0;

Really?

      action=2;

2? What are you trying to do with this state?

else{
      //nada
    }

Are you aware that you can have an if without an else? Delete it.

Thanks for your help guys.

here’s the changes I’ve made

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
 
int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //what's the first note?  36 is C1 in Ableton
 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate baloon1
VarSpeedServo servoI2;   // create servo object to control a servo that Inflate balloon2


// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs
  servoI1.attach(8);   // Set I1 servo to digital pin 8
  servoI2.attach(9);   // Set I2 servo to digital pin 9

  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
}

void infslow1 () {   // Monte 1 lentement
  servoI1.write(45, 5, true); 
  delay (100);
  servoI1.write(32, 0, true);
}

void infslow2() {    // Monte 2 lentement
  servoI2.write(45, 0, true); 
  delay (100);
  servoI2.write(32, 0, true); 
}

void loop () {

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }else if (incomingByte== 127+chan){ // note off message starting
      action=0;
 
    }if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      velocity=0;
    } if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
    } if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      velocity=incomingByte;
      moveServo(note, velocity);
      velocity=0;
      action=0; 
    }
    }
 
}

void moveServo(byte note, byte velocity){    //  call a function based on the note
  
switch (note){
  case lowNote: //if it's not 60
  infslow1 ();
  break;
}
  
}

because the second if clause is the same as the first, the code in that block will never get executed.

You’re right, I have removed the else.

Really?

I’ve removed it, that seemed weird as well but it was originally part of another piece of code that wasn’t working without it.

2? What are you trying to do with this state?

Well I thought that 2 would be null.
int action=2; //0 =note off ; 1=note on ; 2= null

I’ve removed it as well as you can see in my code above. I’ve made all the changes but still, doesn’t seems to be working.

I’ve also tried to remove velocity and to only use note=incomingByte as a value but still, doesn’t work.

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
 
int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //what's the first note?  36 is C1 in Ableton
 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate baloon1
VarSpeedServo servoI2;   // create servo object to control a servo that Inflate balloon2


// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs
  servoI1.attach(8);   // Set I1 servo to digital pin 8
  servoI2.attach(9);   // Set I2 servo to digital pin 9

  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
}

void infslow1 () {   // Monte 1 lentement
  servoI1.write(45, 5, true); 
  delay (100);
  servoI1.write(32, 0, true);
}

void infslow2() {    // Monte 2 lentement
  servoI2.write(45, 0, true); 
  delay (100);
  servoI2.write(32, 0, true); 
}

void loop () {

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }else if (incomingByte== 127+chan){ // note off message starting
      action=0;
 
    }if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      velocity=0;
    } if ( (action==1)&&(note==0) ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
      moveServo(note);
  
    }
    }
 
}

void moveServo(byte note){    //  call a function based on the note
  
switch (note){
  case lowNote: //if it's not 60
  infslow1 ();
  break;
}
  
}

Don't do this:

    }if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)

It makes the code very difficult to read, and does not logically make sense. Keep logical block together.

Instead, do this:

    }

    // beginning of new logical block, in this case, a new "if" block
    if ( (action==0)&&(note==0) ){ // if we received a "note off", we wait for which note (databyte)

Your code doesn't look too far out, but will be difficult to debug without a serial monitor port.

At this stage, if I were you I would either:

  1. Use an Arduino with 2 serial ports so I could use 1 for the midi, and the 2nd to print out debug messages.

or 2) Get my code working using the serial port as a debug port. So, you attach the arduino IDE monitor to the serial port instead of your MIDI controller. Then you type thing into the monitor port, check if your program is reading it correctly, and what it sends to the serial port. You could also send additional printfs to the serial port to see where your proram is going wrong.

It’s working!!! Thanks to all of you guys

Here’s the correct code:

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
 
int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //what's the first note?  36 is C1 in Ableton
 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate baloon1
VarSpeedServo servoI2;   // create servo object to control a servo that Inflate balloon2


// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs
  servoI1.attach(8);   // Set I1 servo to digital pin 8
  servoI2.attach(9);   // Set I2 servo to digital pin 9

  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
}

void infslow1 () {   // Monte 1 lentement
  servoI1.write(45, 5, true); 
  delay (100);
  servoI1.write(32, 0, true);
}

void infslow2() {    // Monte 2 lentement
  servoI2.write(45, 0, true); 
  delay (100);
  servoI2.write(32, 0, true); 
}

void loop () {

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

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }
    
    if (incomingByte== 127+chan){ // note off message starting
      action=0;
 
    }
    
    if ( (action==0)/*&&(note==0)*/ ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      velocity=0;
    } 
    
    if ( (action==1)/*&&(note==0)*/ ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
      moveServo(note);
  
    }
    }
 
}

void moveServo(byte note){    //  call a function based on the note
  
switch (note){
  case lowNote: //if it's not 60
  infslow1 ();
  break;
  case lowNote+8: //if it's not 60
  infslow2 ();
  break;
}
  
}

It was the &&note==0 that was causing the issue.

debug without a serial monitor port.

You’re 100% right but as I was using the hairless to Serial port I couldn’t use the Serial port to get the data as it was already being used by the MIDI. I was going to build a hardware MIDI interface in order to get the serial port available again but I’ve found what was causing the issue.

Thanks for your help guys!