How to receive two MIDI system exclusive messages

I’m trying to receive two MIDI system exclusive messages from a Roland VR-09. The first message is:
F0 41 10 62 12 00 00 03 01 7C F7
and the second message is:
F0 41 10 62 12 00 00 03 00 7D F7
What I’m try to have happen is when the first message is received pin 11 gets set to HIGH while pin 9 is set to LOW. Once the second message is received, pin 11 would be set to LOW and pin 9 would be set to HIGH. Simply, the pins would just toggle their status from LOW to HIGH or HIGH to LOW depending on the last received message.

Any help or suggestions would be greatly appreciated!

MIDI_vr09sysex.ino (779 Bytes)

HI. Had a quick look to your code. it cannot work :

 if (vrMess[] =  { 0xF0, 0x41, 0x10, 0x62, 0x12, 0x00, 0x00, 0x03, 0x01, 0x7C, 0xF7 })
{
   digitalWrite(dPin11, HIGH);
   digitalWrite(dPin9, LOW);
 }

1/ You must use the == to compare 2 values and not the = being an affectation operator
2/ You can't use arrays in that way : , initialize first arrays as const globals then use memcmp to compare them
3/ To reduce memory consumption, define a header first , then the last part of the sysex differing
4/ I'm not sure you are using correctly the MIDI library with sysex here. If you only need to parse SYSEX, simply use the Serial.read(), and wait for SOX (0xF0) to start storing bytes in your array and EOX (0xF7) to stop storing in your main loop. Don't forget to set MIDI baud rate to 31250 in the setup section.

for example :

const byte sysExHeader[] = { 0xF0, 0x41, 0x10, 0x62, 0x12, 0x00, 0x00, 0x03 };
const byte sysEX1[]      = { 0x01, 0x7C };
const byte sysEX2[]      = { 0x00, 0x7D };

bool startSysEx = false;
bool sysExReceived = false;

byte mySysExArray[256];
unsigned  i = 0;

(...)
int readByte;

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



void loop() {
(...)

/// Real time event are ignored (cf MIDI specs)
if ( ( readByte = Serial.read() )  >= 0 && readByte < 0xF8)  {

  if ( readByte == 0xF0)   {
         startSysEx = true;
         sysExReceived = false;
         i = 0;
         mySysExArray[i++] = readByte;         
  }  
  else 
  if ( readByte == 0xF7 && startSysEx) {
   sysExReceived = true;
   startSysEx = false;
   mySysExArray[i++] = readByte;         
  }
  else 
  if ( startSysEx && readByte <= 0x7F)  {
        mySysExArray[i++] = readByte;         
  }

  

if ( sysExReceived ) {

(...)

  if ( memcmp(mySysExArray, sysExHeader,sizeof(sysExHeader)) == 0)
  {

        if ( memcmp(&mySysExArray[8], sysEx1,sizeof(sysEx1)) == 0)
       {
            // Do something for SYSEX1
       }
       else
       if ( memcmp(&mySysExArray[8], sysEx2,sizeof(sysEx2)) == 0) {

      // Do something for SYSEX2
       }
  }

(...)

That could be optimized more to store only sysex msg concerning your Roland MIDI device, starting I suppose with 0xF0, 0x41, 0x10, 0x62. But the code is more complex.

Something like this?

[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExStart[/color] [color=#434f54]=[/color] [color=#000000]0xF0[/color][color=#000000];[/color]

[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExMatch_A[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0x41[/color][color=#434f54],[/color] [color=#000000]0x10[/color][color=#434f54],[/color] [color=#000000]0x62[/color][color=#434f54],[/color] [color=#000000]0x12[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x03[/color][color=#434f54],[/color] [color=#000000]0x01[/color][color=#434f54],[/color] [color=#000000]0x7C[/color][color=#000000]}[/color][color=#000000];[/color]
[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExMatch_B[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0x41[/color][color=#434f54],[/color] [color=#000000]0x10[/color][color=#434f54],[/color] [color=#000000]0x62[/color][color=#434f54],[/color] [color=#000000]0x12[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x03[/color][color=#434f54],[/color] [color=#000000]0x01[/color][color=#434f54],[/color] [color=#000000]0x7D[/color][color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]const[/color] [b][color=#d35400]size_t[/color][/b] [color=#000000]buffersize[/color] [color=#434f54]=[/color] [color=#d35400]max[/color][color=#000000]([/color][color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExMatch_A[/color][color=#000000])[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExMatch_B[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]

[color=#5e6d03]template[/color] [color=#434f54]<[/color][b][color=#d35400]size_t[/color][/b] [color=#000000]N[/color][color=#434f54]>[/color] [color=#00979c]bool[/color] [color=#d35400]match[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#000000]cmp1[/color][color=#434f54],[/color] [b][color=#d35400]size_t[/color][/b] [color=#d35400]length[/color][color=#434f54],[/color] [color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]cmp2[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]N[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]length[/color] [color=#434f54]!=[/color] [color=#000000]N[/color][color=#000000])[/color]
    [color=#5e6d03]return[/color] [color=#00979c]false[/color][color=#000000];[/color]
  [color=#5e6d03]return[/color] [color=#d35400]memcmp[/color][color=#000000]([/color][color=#000000]cmp1[/color][color=#434f54],[/color] [color=#000000]cmp2[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#000000])[/color] [color=#434f54]==[/color] [color=#000000]0[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#000000]handleSysEx[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#000000]SysEx[/color][color=#434f54],[/color] [b][color=#d35400]size_t[/color][/b] [color=#d35400]length[/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]match[/color][color=#000000]([/color][color=#000000]SysEx[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#434f54],[/color] [color=#000000]SysExMatch_A[/color][color=#000000])[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#d35400]digitalWrite[/color][color=#000000]([/color][color=#00979c]LED_BUILTIN[/color][color=#434f54],[/color] [color=#00979c]HIGH[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]match[/color][color=#000000]([/color][color=#000000]SysEx[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#434f54],[/color] [color=#000000]SysExMatch_B[/color][color=#000000])[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#d35400]digitalWrite[/color][color=#000000]([/color][color=#00979c]LED_BUILTIN[/color][color=#434f54],[/color] [color=#00979c]LOW[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]}[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000]31250[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#d35400]pinMode[/color][color=#000000]([/color][color=#00979c]LED_BUILTIN[/color][color=#434f54],[/color] [color=#00979c]OUTPUT[/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#00979c]static[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExBuffer[/color][color=#000000][[/color][color=#000000]buffersize[/color][color=#000000]][/color][color=#000000];[/color]
  [color=#00979c]static[/color] [b][color=#d35400]size_t[/color][/b] [color=#000000]index[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000];[/color]
  [color=#00979c]static[/color] [color=#00979c]bool[/color] [color=#000000]reading[/color] [color=#434f54]=[/color] [color=#00979c]false[/color][color=#000000];[/color]
  
  [color=#5e6d03]if[/color] [color=#000000]([/color][b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]available[/color][color=#000000]([/color][color=#000000])[/color] [color=#434f54]>[/color] [color=#000000]0[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#00979c]uint8_t[/color] [color=#000000]data[/color] [color=#434f54]=[/color] [b][color=#d35400]Serial[/color][/b][color=#434f54].[/color][color=#d35400]read[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
    [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]reading[/color][color=#000000])[/color] [color=#000000]{[/color]
      [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]data[/color] [color=#434f54]>=[/color] [color=#000000]0x80[/color][color=#000000] && data < 0xF8)[/color] [color=#000000]{[/color] [color=#434f54]// if it's a MIDI header[/color]
        [color=#000000]handleSysEx[/color][color=#000000]([/color][color=#000000]SysExBuffer[/color][color=#434f54],[/color] [color=#000000]index[/color][color=#000000])[/color][color=#000000];[/color]
        [color=#000000]reading[/color] [color=#434f54]=[/color] [color=#00979c]false[/color][color=#000000];[/color]
      [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#000000]{[/color]
        [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]index[/color] [color=#434f54]==[/color] [color=#000000]buffersize[/color][color=#000000])[/color] [color=#000000]{[/color] [color=#434f54]// SysEx is larger than buffer[/color]
          [color=#000000]reading[/color] [color=#434f54]=[/color] [color=#00979c]false[/color][color=#000000];[/color]
        [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#000000]{[/color]
          [color=#000000]SysExBuffer[/color][color=#000000][[/color][color=#000000]index[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]data[/color][color=#000000];[/color]
          [color=#000000]index[/color][color=#434f54]++[/color][color=#000000];[/color]
        [color=#000000]}[/color]
      [color=#000000]}[/color]
    [color=#000000]}[/color]    
    [color=#5e6d03]if[/color] [color=#000000]([/color][color=#000000]data[/color] [color=#434f54]==[/color] [color=#000000]SysExStart[/color][color=#000000])[/color] [color=#000000]{[/color]
      [color=#000000]index[/color] [color=#434f54]=[/color] [color=#000000]0[/color][color=#000000];[/color]
      [color=#000000]reading[/color] [color=#434f54]=[/color] [color=#00979c]true[/color][color=#000000];[/color]
    [color=#000000]}[/color]
  [color=#000000]}[/color]
[color=#000000]}[/color]

Pieter

You can make it a bit more efficient by matching the bytes they have in common separately:

[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExHeader[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0x41[/color][color=#434f54],[/color] [color=#000000]0x10[/color][color=#434f54],[/color] [color=#000000]0x62[/color][color=#434f54],[/color] [color=#000000]0x12[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x00[/color][color=#434f54],[/color] [color=#000000]0x03[/color][color=#434f54],[/color] [color=#000000]0x01[/color][color=#000000]}[/color][color=#000000];[/color] [color=#434f54]// The common bytes of all messages[/color]
[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExMatch_A[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0x7C[/color][color=#000000]}[/color][color=#000000];[/color]
[color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]SysExMatch_B[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]0x7D[/color][color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]const[/color] [b][color=#d35400]size_t[/color][/b] [color=#000000]buffersize[/color] [color=#434f54]=[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExHeader[/color][color=#000000])[/color] [color=#434f54]+[/color] [color=#d35400]max[/color][color=#000000]([/color][color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExMatch_A[/color][color=#000000])[/color][color=#434f54],[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExMatch_B[/color][color=#000000])[/color][color=#000000])[/color][color=#000000];[/color]

[color=#5e6d03]template[/color] [color=#434f54]<[/color][b][color=#d35400]size_t[/color][/b] [color=#000000]N[/color][color=#434f54]>[/color] [color=#00979c]bool[/color] [color=#d35400]match[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#000000]cmp1[/color][color=#434f54],[/color] [b][color=#d35400]size_t[/color][/b] [color=#d35400]length[/color][color=#434f54],[/color] [color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]cmp2[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]N[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]length[/color] [color=#434f54]!=[/color] [color=#000000]N[/color][color=#000000])[/color]
    [color=#5e6d03]return[/color] [color=#00979c]false[/color][color=#000000];[/color]
  [color=#5e6d03]return[/color] [color=#d35400]memcmp[/color][color=#000000]([/color][color=#000000]cmp1[/color][color=#434f54],[/color] [color=#000000]cmp2[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#000000])[/color] [color=#434f54]==[/color] [color=#000000]0[/color][color=#000000];[/color]
[color=#000000]}[/color]
[color=#5e6d03]template[/color] [color=#434f54]<[/color][b][color=#d35400]size_t[/color][/b] [color=#000000]N[/color][color=#434f54]>[/color] [color=#00979c]bool[/color] [color=#000000]matchHeader[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#000000]cmp1[/color][color=#434f54],[/color] [b][color=#d35400]size_t[/color][/b] [color=#d35400]length[/color][color=#434f54],[/color] [color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#000000]([/color][color=#434f54]&[/color][color=#000000]header[/color][color=#000000])[/color][color=#000000][[/color][color=#000000]N[/color][color=#000000]][/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]length[/color] [color=#434f54]<[/color] [color=#000000]N[/color][color=#000000])[/color]
    [color=#5e6d03]return[/color] [color=#00979c]false[/color][color=#000000];[/color]
  [color=#5e6d03]return[/color] [color=#d35400]memcmp[/color][color=#000000]([/color][color=#000000]cmp1[/color][color=#434f54],[/color] [color=#000000]header[/color][color=#434f54],[/color] [color=#000000]N[/color][color=#000000])[/color] [color=#434f54]==[/color] [color=#000000]0[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#000000]handleSysEx[/color][color=#000000]([/color][color=#00979c]const[/color] [color=#00979c]uint8_t[/color] [color=#434f54]*[/color][color=#000000]SysEx[/color][color=#434f54],[/color] [b][color=#d35400]size_t[/color][/b] [color=#d35400]length[/color][color=#000000])[/color] [color=#000000]{[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#434f54]![/color][color=#000000]matchHeader[/color][color=#000000]([/color][color=#000000]SysEx[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#434f54],[/color] [color=#000000]SysExHeader[/color][color=#000000])[/color][color=#000000])[/color]
    [color=#5e6d03]return[/color][color=#000000];[/color]
  [color=#000000]SysEx[/color] [color=#434f54]+=[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExHeader[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#d35400]length[/color] [color=#434f54]-=[/color] [color=#00979c]sizeof[/color][color=#000000]([/color][color=#000000]SysExHeader[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]match[/color][color=#000000]([/color][color=#000000]SysEx[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#434f54],[/color] [color=#000000]SysExMatch_A[/color][color=#000000])[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#d35400]digitalWrite[/color][color=#000000]([/color][color=#00979c]LED_BUILTIN[/color][color=#434f54],[/color] [color=#00979c]HIGH[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]}[/color] [color=#5e6d03]else[/color] [color=#5e6d03]if[/color] [color=#000000]([/color][color=#d35400]match[/color][color=#000000]([/color][color=#000000]SysEx[/color][color=#434f54],[/color] [color=#d35400]length[/color][color=#434f54],[/color] [color=#000000]SysExMatch_B[/color][color=#000000])[/color][color=#000000])[/color] [color=#000000]{[/color]
    [color=#d35400]digitalWrite[/color][color=#000000]([/color][color=#00979c]LED_BUILTIN[/color][color=#434f54],[/color] [color=#00979c]LOW[/color][color=#000000])[/color][color=#000000];[/color]
  [color=#000000]}[/color]
[color=#000000]}[/color]

Very elegant coding Pieter. I like the match template !
A point concerning SYSEX : real time one byte midi events can be mixed within SYSEX,

so testing only the bit 7 in the following code is not enough...it works but it's not midi compliant.

if (data & 0x80) { // if it's a MIDI header
handleSysEx(SysExBuffer, index);
reading = false;

should be :

if ((data & 0x80) && data < 0xF8 )

or :

if (data >= 0x80 && data < 0xF8 )

or

if ( data >= 0xF8 ) return;
if (data & 0x80) { // if it's a MIDI header
...

TheKikGen:
A point concerning SYSEX : real time one byte midi events can be mixed within SYSEX,

so testing only the bit 7 in the following code is not enough...it works but it's not midi compliant.

if (data & 0x80) { // if it's a MIDI header
handleSysEx(SysExBuffer, index);
reading = false;

should be :

if ((data & 0x80) && data < 0xF8 )

or :

if (data >= 0x80 && data < 0xF8 )

or

if ( data >= 0xF8 ) return;
if (data & 0x80) { // if it's a MIDI header
...

You are correct.

Thank you for the tremendous amount of help! I still to this day use the code and have been adding to it since! I greatly appreciate your time!