Receiving MIDI Notes with unwanted bytes in the mix

Hi Guys,

I’m using the code to receive messages posted here: http://www.instructables.com/id/Send-and-Receive-MIDI-with-Arduino/?ALLSTEPS

The thing is, in the main loop, there is a 100ms delay right after calling the function to check for midi. The result is that when my MIDI program is sending to the arduino, it sends about 10 bytes upon hitting play, which causes a delay of about a second after which any notes that I want to play within that second get delayed, and that is problematic. I would like to get rid of the delay entirely. The issue is, that after I do I get unwanted bytes between some of the messages. Let me post my code:

byte commandByte;
byte noteByte;
byte velocityByte;

byte noteOn = 144;
byte noteOff = 128;


void setup() {
  Serial2.begin(31250);
  Serial.begin(9600);

  dmx_master.enable();
}

void checkMIDI() {
  do {
    if (Serial2.available()) {
      commandByte = Serial2.read();//read first byte
      noteByte = Serial2.read();//read next b#yte
      velocityByte = Serial2.read();//read final byte
      if (commandByte == noteOn) { //if note on message
        //check if note == 60 and velocity > 0
        if (noteByte == 60 && velocityByte > 0) {
          Serial.println("Note On");
          dmx_master.setChannelRange (3, 4, 255 );
        }
        else if (noteByte == 60 && velocityByte == 0) {
          Serial.println("Note Off");

          dmx_master.setChannelRange (3, 4, 0 );
        }
      }
      else if (commandByte == noteOff) {
        Serial.println("Note Off");

        dmx_master.setChannelRange (3, 4, 0 );
      }
      printBytes();
    }
  }
  while (Serial2.available() > 2);//when at least three bytes available
}


void loop() {
  checkMIDI();
  delay(1);

}

void printBytes() {
  Serial.print("1st Byte: ");
  Serial.print(commandByte);
  Serial.print("  ");
  Serial.print(commandByte, BIN);
  Serial.print("  ");
  Serial.println(commandByte, HEX);

  Serial.print("2nd Byte: ");
  Serial.print(noteByte);
  Serial.print("  ");
  Serial.print(noteByte, BIN);
  Serial.print("  ");
  Serial.println(noteByte, HEX);

  Serial.print("3rd Byte: ");
  Serial.print(velocityByte);
  Serial.print("  ");
  Serial.print  (velocityByte, BIN);
  Serial.print("  ");
  Serial.println(velocityByte, HEX);

  Serial.println("");
//  delay(100);
}

It’s a little sloppy I know, but I’m still in testing phase at the moment and aim to clean it all up a bit later.

Here is an example of the bytes I should be receiving and the problematic messages:

Some of the time I receive these messages (correct)

Note On
1st Byte: 144  10010000  90
2nd Byte: 60  111100  3C
3rd Byte: 100  1100100  64

Note Off
1st Byte: 128  10000000  80
2nd Byte: 60  111100  3C
3rd Byte: 64  1000000  40
And sometimes I receive these messages...

Note Off
1st Byte: 128  10000000  80
2nd Byte: 60  111100  3C
3rd Byte: 64  1000000  40

1st Byte: 144  10010000  90
2nd Byte: 255  11111111  FF  <-------
3rd Byte: 255  11111111  FF   <-------

1st Byte: 60  111100  3C
2nd Byte: 100  1100100  64
3rd Byte: 255  11111111  FF   <-------

Note Off
1st Byte: 128  10000000  80
2nd Byte: 60  111100  3C
3rd Byte: 255  11111111  FF    <-------

As you can see I receive these 255 bytes seemingly out of nowhere. Seeing as I never process this value, I can certainly add an exemption while the program checks the serial buffer to filter out any bytes that = 255, but I would rather find the cause of the problem and fix it.

Thanks for your help in advance :slight_smile:

Classic error.
Lessons to learn:-

  1. Most instructiables are written by idiots, never use them. In this case the idiot that wrote that did not know how to read the serial port so he put in a delay to cover up his error.

  2. The code:-

 if (Serial2.available()) {
      commandByte = Serial2.read();//read first byte
      noteByte = Serial2.read();//read next b#yte
      velocityByte = Serial2.read();//read final byte

Looks to see if there is at least one byte in the serial buffer. If there is, it then reads three bytes from the buffer, regardless of if there are three bytes to read. When you read an empty you get the number 0xff, which is what you are getting.

solution:- the simplest way is to not read three bytes from the buffer until there are three bytes to read.

 if (Serial2.available()>2) {
      commandByte = Serial2.read();//read first byte
      noteByte = Serial2.read();//read next b#yte
      velocityByte = Serial2.read();//read final byte