How to send SysEx MIDI messages?

Status
Not open for further replies.

intergalatico

Well-known member
Hello folks,

would someone help me to write a function to control my Boss SY 300 Guitar Synthesizer?

I managed to build and write the code for my Teensy based expression pedal with multiple CV outputs. (https://forum.pjrc.com/threads/44499-One-expression-pedal-multiple-devices)
Now I have this Boss unity and need to control with my expression pedal too. I am already using all CV outputs and the good thing is that the Boss accept MIDI messages from USB and Teensy can send MIDI messages from the USB jack.

I am not a programmer and with much stroggle (and help from you guys here) I wrote this code. But dealing with SysEx is a little beyond of me.

I would like to have a function just like the midi library, like:

MIDI.sendControlChange(controlNumber, controlValue, channel);

Here is the MIDI implementation pdf from the BOSS SY 300: https://static.roland.com/assets/media/pdf/SY-300_MIDI_Imple_e02.pdf

And here is what I suppose to be what I need:
Code:
                   Control Change Number #1 - #31, #64 - #95
                        Status      2nd Byte    3rd Byte
                        ------      --------    --------
                        BnH         ccH         vvH


                        n  = MIDI Channel Number   : 0H - FH(0 - 15)    0=ch.1  15=ch.16
                        cc = Control Change Number : 01H - 1FH(1 - 31)  40H - 5FH(64-95)
                        vv = Value                 : 00H - 7FH(0 - 127)


                        You can use control change messages from an USB (computer) to control functions that would bedifficult to control using the SY-300's own controllers.
                        "MIDI" In "Editing: Assigning Favorite Parameters to the Switches and External Pedals" of Owner's Manual, set "SOURCE NUMBER" to "CC#1-#31, CC#64-#95" and set "TARGET" to specify the parameter that will be controlled.

And here is my code for the mentioned "Expressionator" (sorry for the mess):

Code:
#include<ButtonV2.h>
#include <AH_MCP4922.h>
#include <ResponsiveAnalogRead.h>


// ButtonV2 Library
ButtonV2 Button1;
ButtonV2 Button2;
ButtonV2 Button3;

const byte ButtonPin1 = 18;
const byte ButtonPin2 = 17;
const byte ButtonPin3 = 16;

//MCP4922 Liybrary
//define AnalogOutput (MOSI_pin, SCK_pin, CS_pin, DAC_x, GAIN) 

// Chip 1
AH_MCP4922 AnalogOutput1(11,13,10,LOW,HIGH);     // DAC_A = LOW, DAC_B = High 
AH_MCP4922 AnalogOutput2(11,13,10,HIGH,HIGH);    // Gain 1x = HIGH, Gain 2x = LOW

// Chip 2
AH_MCP4922 AnalogOutput12(7,13,15,LOW,HIGH);
AH_MCP4922 AnalogOutput22(7,13,15,HIGH,HIGH);



ResponsiveAnalogRead analogOne(A5, true); // Define Pin and Sleep Enable


// For the Calibration:
const int sensorPin = A5;
int sensorValue = 0;         // the sensor value
int hallSensorMin = 275;        // minimum sensor value 1023
int hallSensorMax = 698;           // maximum sensor value 0
int holdButtonInstant = 0;

//#define hallSensorMin 252 // The Hall Sensor is not already definetly fixed. This helps to quick adapt the values when the sensor moves 
//#define hallSensorMax 772



int expressionPedalValueOld = 0;
int expressionPedalValue = 0;
int expressionPedalValueH9 = 0; // For the Eventide H9 the Max Vout should be 3.2V, the other ones 5V

int Vout1 = 0;
int Vout2 = 0;
int Vout3 = 0;

// Taper
int expressionTaper100 = 0;
int hallSensor = 0;             // Raw hall sensor output
int taper = 0;
int val = 0;

  //Arrays: 
//out[] holds the values wanted in %
int out[] = { 0, 30, 45, 60, 65, 67, 70, 75, 80, 85, 90, 95, 100 };//13

// in[] holds the measured analogRead() values for defined % outputs
// note: the in array should have increasing values
int in[]  = { 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100}; // 13



// RGB LEDS
int redPin1 = 4;
int greenPin1 = 3;
int bluePin1 = 5;

int redPin2 = 6;
int greenPin2 = 9;
int bluePin2 = 23;

int redPin3 = 22;
int greenPin3 = 21;
int bluePin3 = 20;



//Led State
bool led1State = false;
bool led2State = false;
bool led3State = false;
bool led4State = false;

//


void setup()
{
  
  pinMode(ButtonPin1, INPUT_PULLUP);
  pinMode(ButtonPin2, INPUT_PULLUP);
  pinMode(ButtonPin3, INPUT_PULLUP);

//pinMode(LEDpin, OUTPUT);
  pinMode(redPin1, OUTPUT);
  pinMode(greenPin1, OUTPUT);
  pinMode(bluePin1, OUTPUT); 

  pinMode(redPin2, OUTPUT);
  pinMode(greenPin2, OUTPUT);
  pinMode(bluePin2, OUTPUT); 

  pinMode(redPin3, OUTPUT);
  pinMode(greenPin3, OUTPUT);
  pinMode(bluePin3, OUTPUT); 

  
  Serial.begin(115200);
  Serial.println("ready");
  
  Button1.SetStateAndTime(LOW, 250);
  Button2.SetStateAndTime(LOW, 250);
  Button3.SetStateAndTime(LOW, 250);
  

  // Calibration of the Hall Sensor on the first 5 seconds
  /*while (millis() < 5000) {

    analogOne.update();
    sensorValue = analogOne.getValue();

    // record the maximum sensor value
    if (sensorValue > hallSensorMax) {
      hallSensorMax = sensorValue;
    }

    // record the minimum sensor value
    if (sensorValue < hallSensorMin) {
      hallSensorMin = sensorValue;
    }
    setColor1(0, 20, 0);
    setColor2(15, 0, 0);
    setColor3(0, 0, 20);
    
      
    }
    setColor1(0, 0, 0);
    setColor2(0, 0, 0);
    setColor3(0, 0, 0);

    */

// Initial Value:
    AnalogOutput1.setValue(1330); // H9 50%
    AnalogOutput2.setValue(4095);
    AnalogOutput12.setValue(4095);
    AnalogOutput22.setValue(4095);
    
  
}

void loop()
{

  analogOne.update();
  hallSensor = analogOne.getValue();

//multiMap:
  expressionTaper100 = map(hallSensor, hallSensorMin, hallSensorMax, 100, 0); // Turn the Values to 0 - 100 Range
  val = expressionTaper100;
  taper = multiMap(val, in, out, 13);
  
  expressionPedalValue = map(taper, 0, 100, 0, 4095); // max 5V    Vref=5.14 Vcc= 5.15
  expressionPedalValueH9 = map(taper, 0, 100, 0, 2650); //max 3.2V



  byte type1 = Button1.CheckButton(ButtonPin1); // current time and length of time to press the button as many times as you can ie. 1.5 seconds
  switch (type1)
  {
    case WAITING:
      break;
    case PRESSED:
      //AnalogOutput1.setValue(expressionPedalValue);
      
      Serial.println("B1 pressed 1 time");
      break;
    case DOUBLE_PRESSED:
      Serial.println("B1 pressed 2 times");
      break;
    case MULTI_PRESSED:
      Serial.println("B1 pressed 3 times");
      break;
    case HELD:
      Serial.println("B1 Button HELD");
      holdButtonInstant = millis();
      break;
  }



  byte type2 = Button2.CheckButton(ButtonPin2); // current time and length of time to press the button as many times as you can ie. 1.5 seconds
  switch (type2)
  {
    case WAITING:
      break;
    case PRESSED:
      Serial.println("B2 pressed 1 time");
      break;
    case DOUBLE_PRESSED:
      Serial.println("B2 pressed 2 times");
      break;
    case MULTI_PRESSED:
      Serial.println("B2 pressed 3 times");
      break;
    case HELD:
      Serial.println("B2 Button HELD");
      break;
  }

  byte type3 = Button3.CheckButton(ButtonPin3); // current time and length of time to press the button as many times as you can ie. 1.5 seconds
  switch (type2)
  {
    case WAITING:
      break;
    case PRESSED:
      Serial.println("B2 pressed 1 time");
      break;
    case DOUBLE_PRESSED:
      Serial.println("B2 pressed 2 times");
      break;
    case MULTI_PRESSED:
      Serial.println("B2 pressed 3 times");
      break;
    case HELD:
      Serial.println("B2 Button HELD");
      break;
  }

Vout1 = map(expressionPedalValue, 4095, 0, 514, 0);    // Output in Volts (5.14V = 514)
Vout2 = map(expressionPedalValue, 4095, 0, 514, 0);    // Output in Volts (5.14V = 514)
Vout3 = map(expressionPedalValueH9, 2650, 0, 320, 0);  // Output in Volts (3.2V = 320)  

//Button 1

  if (led1State == false) {

    if (type1 == PRESSED){
    
      setColor1(0, 20, 0); //Green          
      led1State = true;
                         }   
                       }   

 else {

    if (type1 == PRESSED){
    
      setColor1(0, 0, 0);             
      led1State = false;
      //AnalogOutput1.setValue(0);// Set the Vout when the Button is OFF
                         }   
                          }
                          
if (led1State == true && expressionPedalValue != expressionPedalValueOld){

      AnalogOutput1.setValue(expressionPedalValueH9);
      Serial.println("Vout1: "); 
      Serial.println(Vout1);
        
                           }
       //expressionPedalValueOld = expressionPedalValue;

if (type1 == HELD) {

   setColor1(10, 0, 10);
   AnalogOutput1.setValue(2000);
   led1State = false;
   
  
} 


//Button 2

  if (led2State == false) {

    if (type2 == PRESSED){
    
      setColor2(0, 15, 5);   //Aqua 
      led2State = true;
                         }   
                       }   

 else {

    if (type2 == PRESSED){
    
      setColor2(0, 0, 0);             
      led2State = false;
      AnalogOutput2.setValue(4095);// Set the Vout when the Button is OFF
                         }   
                          }
                          
if (led2State == true && expressionPedalValue != expressionPedalValueOld){

      AnalogOutput2.setValue(expressionPedalValue);
      Serial.println("Vout2: "); 
      Serial.println(Vout2);
        
                           }
       //expressionPedalValueOld = expressionPedalValue;

if (type2 == HELD) {

   setColor2(10, 0, 10);
   AnalogOutput2.setValue(2000);
   led2State = false;
   
  
} 

//Button 3

  if (led3State == false) {

    if (type3 == PRESSED){
    
      setColor3(0, 0, 20);             
      led3State = true;
                         }   
                       }   

 else {

    if (type3 == PRESSED){
    
      setColor3(0, 0, 0);             
      led3State = false;
      led4State = false;
      //AnalogOutput12.setValue(0);// Set the Vout when the Button is OFF
                         }   
                          }
                          
if (led3State == true && expressionPedalValue != expressionPedalValueOld){

      AnalogOutput12.setValue(expressionPedalValue);
      Serial.println("Vout3: "); 
      Serial.println(Vout3);
        
                           }
       

if (type3 == HELD) {

   //setColor3(10, 0, 10);
   //AnalogOutput12.setValue(2000);
   //led3State = false;   
}




// Output 4 (Ravish)

//Button 4

  if (led4State == false) {

    if (type3 == PRESSED){
    
      
                         }   
                       }   

 else {

    if (type3 == PRESSED){
    
      
      //AnalogOutput12.setValue(0);// Set the Vout when the Button is OFF
                         }   
                          }
                          
if (led4State == true && expressionPedalValue != expressionPedalValueOld){

      AnalogOutput22.setValue(expressionPedalValue);
      
                           }
       

if (type3 == HELD) {

   setColor3(0, 10, 10);
   
   led4State = true;   
}


expressionPedalValueOld = expressionPedalValue;


delay(1);

// CALIBRATION

if (type1 == HELD && type2 == HELD){
  
    // Calibration of the Hall Sensor on the first 5 seconds
  while (millis() - holdButtonInstant < 5000) {

    analogOne.update();
    sensorValue = analogOne.getValue();

    // record the maximum sensor value
    if (sensorValue > hallSensorMax) {
      hallSensorMax = sensorValue;
    }

    // record the minimum sensor value
    if (sensorValue < hallSensorMin) {
      hallSensorMin = sensorValue;
    }
    setColor1(5, 0, 0);
    setColor2(10, 0, 0);
    setColor3(15, 0, 0);
  }
  setColor1(0, 0, 0);
  setColor2(0, 0, 0);
  setColor3(0, 0, 0);

  led1State = false;
  led2State = false;
  led3State = false;
}
                                                    
   delay(1);

  Serial.print("    Min: "); 
  Serial.print(hallSensorMin);
  Serial.print("    Max: "); 
  Serial.print(hallSensorMax);
  Serial.print("    Hall Sensor: "); 
  Serial.print(hallSensor);
   Serial.print("   Hall Sensor Constrain: ");  
  Serial.println("          ");
  Serial.print("Vout1: "); 
  Serial.print(Vout1);
  Serial.print("   Vout2: "); 
  Serial.print(Vout2);
  Serial.print("   Vout3: "); 
  Serial.print(Vout3);

  delay(1);
 
}


// RGB LED VOID

void setColor1(int red, int green, int blue)
    {
      #ifdef COMMON_ANODE
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
      #endif
      analogWrite(redPin1, red);
      analogWrite(greenPin1, green);
      analogWrite(bluePin1, blue);  
    }

    void setColor2(int red, int green, int blue)
    {
      #ifdef COMMON_ANODE
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
      #endif
      analogWrite(redPin2, red);
      analogWrite(greenPin2, green);
      analogWrite(bluePin2, blue);  
    }

    void setColor3(int red, int green, int blue)
    {
      #ifdef COMMON_ANODE
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
      #endif
      analogWrite(redPin3, red);
      analogWrite(greenPin3, green);
      analogWrite(bluePin3, blue);  
    }
 /*
      setColor(80, 0, 0);  // red
      setColor(0, 80, 0);  // green
      setColor(0, 0, 80);  // blue
      setColor(80, 80, 0);  // yellow
      setColor(80, 0, 80);  // purple
      setColor(0, 80, 80);  // aqua
      */ 

      // note: the _in array should have increasing values
int multiMap(int val, int* _in, int* _out, uint8_t size)
{
  // take care the value is within range
  // val = constrain(val, _in[0], _in[size-1]);
  if (val <= _in[0]) return _out[0];
  if (val >= _in[size-1]) return _out[size-1];

  // search right interval
  uint8_t pos = 1;  // _in[0] allready tested
  while(val > _in[pos]) pos++;

  // this will handle all exact "points" in the _in array
  if (val == _in[pos]) return _out[pos];

  // interpolate in the right segment for the rest
  return (val - _in[pos-1]) * (_out[pos] - _out[pos-1]) / (_in[pos] - _in[pos-1]) + _out[pos-1];
}

I really appreciate any help!

Cheers!
 
While the sysEx section of that document is extensive the part you are quoting relates to a standard MIDI CC message type. Exactly the one you've quoted from the MIDI library.

So the MIDI 'send control change' call:

MIDI.sendControlChange(controlNumber, controlValue, channel);


becomes:

usbMIDI.sendControlChange(controlNumber, controlValue, channel);

https://www.pjrc.com/teensy/td_midi.html

But you must feed it the appropriate CC number (from the standard owners manual as indicated in the note you've quoted) and your analog value reduced to seven bits; i.e. in the range [0,127].


Typically you might also limit the update rate of new messages, limit updates to changes values and possible implement a 'dead zone' around the current reading to require changes to pass some threshold from the stored value before becoming 'active' for new updates.

As you are already using ResponsiveAnalogRead() and are reducing the resolution significantly you are unlikely to have to do more than limit updates to new values.
 
Thank's oddson!

That's awesome! You mean I can just call:

usbMIDI.sendControlChange(control, value, channel);

and it will work? Sounds to easy to me, but hey, what I know?!

I thought I would need to include data like "Devide Number", "Device ID", "Begin of the message", "End of the messge" kind of stuff. Like this:

Code:
               System Exclusive Message


                Status  Data Byte               Status
                ------  ---------               ------
                F0H     41H, ddH, ..., eeH      F7H


                Byte                 Explanation
                ----                 -----------
                F0H:                 System Exclusive Message status
                41H:                 Manufacturer ID (Roland)
                dd,...,ee = data:    00H-7FH(0-127)
                F7H:                 EOX(End Of Exclusive)

                 Universal Non-Realtime System Exclusive Messages

                        Identity Request Message (Device Inquiry)

                                Status  Data Byte             Status
                                ------  ---------             ------
                                F0H     7EH, ddH, 06H, 01H,   F7H


                                Byte    Explanation
                                ----    -----------
                                F0H     Exclusive status
                                7EH     ID number (Universal Non-realtime Message)
                                ddH     Device ID (dev: 00H-1FH, 7FH)  * 7FH = BroadCast
                                06H     Sub ID # 1 (General Information)
                                01H     Sub ID # 2 (Identity Request)
                                F7H     EOX (End Of Exclusive)



Can you please help me to convert the 0-127 range to the seven bits range? I am not good in it!

Now I have to order the proper usb cable.

Thanks a lot!

Cheers
 
...You mean I can just call:

usbMIDI.sendControlChange(control, value, channel);

and it will work? Sounds to easy to me, but hey, what I know?!
How much you know definitely affects how I would answer this.

Are you aware that you have to compile the code for the specific Teensy for a USB type that includes MIDI.

When you do the usb MIDI library is added and those calls become available. Please read the material the link I provided if you are not already familiar.

The problem is, as I read you now, you want to connect directly a synth as a device, rather than with the Teensy as a device to a PC which is how a standard MIDI controller works.

I thought maybe the synth itself was a MIDI host to support controllers directly but it is not (at least from the connector on the back from a web image).

If you want a Teensy to act as a MIDI host you should get a Teensy 3.6 which has everything but the USB connection built in (otherwise it's a third-party USB-host shield and I would not recommend that route).

Reports are this is easily done but I have not tried it myself and so can't really help you.

Others have used standard MIDI to control pedals directly but that opens up some hardware issues -- refer to this page:
https://www.pjrc.com/teensy/td_libs_MIDI.html
(although if you want to send only then you just need a few passives and don't need the IC used in the circuit).

I recall someone having problems with a guitar-synth via 5-pin DIN MIDI but I don't recall if it was Boss for sure (but I don't think it was Roland so you might want to see if there are reports about connections).

You might want to seek some advice from their user forum before getting in too deep if you choose this route.

Also if you go this way you don't call usbMIDI. but MIDI.

The only other connection route would be to have your PC send the MIDI back to the synth if that would work for you (with it's obvious shortcoming).


I thought I would need to include data like "Device Number", "Device ID", "Begin of the message", "End of the messge" kind of stuff. Like this:
Those are explanations the document is providing to tell you what the hexadecimal values mean (That's the F7H and 04H but in C code 0xF7 and 0x04).

MIDI itself if very terse. Because the rate of communications is very slow each message is as tiny as it can be. Three bytes is a full standard message; the first can be omitted if there is a stream of the same status type on the same channel. Some one-byte messages like MIDI clock pulses also exist. Sysex is for everything else and gets complicated but the documentation you've pointed to is showing how all those bytes are stacked together into a message.
Can you please help me to convert the 0-127 range to the seven bits range? I am not good in it!

0-127 range IS the seven bit range... but I believe your code uses 12 or14 bits (I can't recall ATM). Even if it uses the default 10 bits you need to rescale to seven before sending as MIDI CC.



To do that you need to divide by a power of two or, which is exactly the same thing, use the bit shift operator to rescale by the difference in resolution. If going from 10 to 7 bits (which is common in Teensy MIDI because it's the default resolution) then you need to shift by the difference: 10-7=3 bits.

Often you can include the bit reduction directly with the MIDI call (although keeping a separate variable usually makes sense since you need to check if it's different before sending again)

MIDI.sendControlChange(CCnumber, 10BitValue>>3, channel);

That's equivalent to 10BitValue/8



You can shift the other direction with <<.

To move from 12 bit to seven you would use >>5
For 14 to seven >>7






Now I have to order the proper usb cable.
This is how I realized you wanted a USB MIDI host solution...
 
Thankso much to taking the time to help me! I really appreciate it!

The problem is, as I read you now, you want to connect directly a synth as a device, rather than with the Teensy as a device to a PC which is how a standard MIDI controller works.

Yes, I want that mine teensy 3.2 connects with the SY 300 trough a simple usb cable (mini USB on the teensy side and "printer" USB on the SY 300 side). So the teensy will act like a USB MIDI controller. I can't use a 5pin MIDI Jack because mine teensy hardware is already build and enclosured and I can't change it anymore. In the way it is, I have acess to the the mini USB.

(Just as a info, I already build a MIDI Controller with Teensy but using the standard 5-pin Midi Jack connected like the instructions here https://www.pjrc.com/teensy/td_libs_MIDI.html So I am a little bit familiar with the MIDI library. Saying that I don't mean I am experienced programmer, I just research, try help on forums and try to understand the Library's. I am just a musician.)

I thought maybe the synth itself was a MIDI host to support controllers directly but it is not (at least from the connector on the back from a web image).

The SY 300 do support MIDI controllers. It has 5pin In and Out Midi Jacks and the USB. I supposed that I can use the USB to control the unity because the SY 300 have a PC Software Editor that uses the USB to control it. I am just assuming it... I am wrong? I suppose the PC communicates with the SY 300 with SysEx messages, right?

The only other connection route would be to have your PC send the MIDI back to the synth if that would work for you (with it's obvious shortcoming).

I don't want to use a computer for it.

Thank you for the Hex explanation. Although I didn't really got it... but maybe let's handle it after we clear if the teensy can do what I am willing to do.

But let's say the SY 300 can accept standard USB MIDI messages from the teensy. That is how I imagine the code would look like. Let's say I want to send a CC message on the channel 1, CC# 1 and the readings from my expression pedal:

Code:
int analogPin = 3;
int expressionPedal = 0;

expressionPedal = analogRead(analogPin);

usbMIDI.sendControlChange(1, expressionPedal, 1);

But lets say the USB from the SY 300 takes only SysEx messages (what I was thinking). How it would the same message looks like? (Based on the Midi Implementation document provided on the first post)

usbMIDI.sendSysEx(length, array, hasBeginEnd);

Thank you again!

Cheers!
 
One side or the other of a USB connection must be the host!

Have you bought a USB-micro to USB-B cable yet? That's the Teensy to Printer cable.

There's a reason they are not readily available; because both ends are meant to connect to a 'slave' device rather than a 'master' host.

A MIDI controller is normally connected to an instrument via a DIN connector. The USB-B connector is meant to connect to a PC.

Some instruments, but not yours, can act as a USB host for the communications with a controller.

As yours cannot be the host, and yet one side or the other must be the host, then the ONLY option (for USB) is for Teensy to be the host.

And there is no way for any Teensy to host USB via the USB-micro-B connection built in to the Teensy.

You will either need a USB-host shield or use a Teensy 3.6 that has a built-in USB host and just needs the physical connection (to an A or C type connector used for hosts).


....MIDI
None of this has anything to do with MIDI except that USB-MIDI is handled by Paul's Teensy library while DIN MIDI uses an Arduino MIDI library.

Paul just recently realigned his to the other so they are nearly call-for-call equivalent.

...I supposed that I can use the USB to control the unity because the SY 300 have a PC Software Editor that uses the USB to control it. I am just assuming it... I am wrong? I suppose the PC communicates with the SY 300 with SysEx messages, right?
The PC is the host. It works because it hosts MIDI messaging over the USB communications link. SysEx is just a type of MIDI message.


...But let's say the SY 300 can accept standard USB MIDI messages from the teensy. That is how I imagine the code would look like. Let's say I want to send a CC message on the channel 1, CC# 1 and the readings from my expression pedal:...
You're very close on the actual code. All that's missing for your call to work is that the reading would default to 10-bits [0-1023] and you need to drop it to seven before sending.

expressionPedal = analogRead(analogPin)>>3;


But lets say the USB from the SY 300 takes only SysEx messages (what I was thinking). How it would the same message looks like? (Based on the Midi Implementation document provided on the first post)
The device has a lot of SysEx built in but I'm pretty confident you will not need it just to control a parameter. (And the part you quote is clearly a standard 3 byte MIDI CC number/value pair).

But if you later discover the need to send SysEx or for anyone who later stumbles on this thread from its title looking for how to do so, here's an example where I have my foot controller send a minimal acknowledge message after it receives data from a PC. Before you send you need to build an array of bytes that you can send with the sendSysEx command.

Code:
    byte data[] = { 0xF0, 0x7D, 0xF7 }; // ACK msg - should be safe for any device even if listening for 7D
    usbMIDI.sendSysEx(3, data, True);         // SEND

Normally the array of data sent would be much larger (and all those documentation pages are meant to show you how to put those together).

The first and last bytes are always the same -- it's how the receiver knows it's listening to a SysEx... So the third parameter lets you tell the call whether they are already present (True) or not (False).
[Full disclosure: I've not compiled/tested since the ability to feed it an array without terminal bytes was made available.]

But if you run into something that requires sending a SysEx message all you have to do is decipher what that message needs to contain from the documentation and then to build an array of bytes and feed that to the send command (preceded by the length).
 
Status
Not open for further replies.
Back
Top