Go Down

Topic: How to send SysEx Messages with Midi Library (Read 11838 times) previous topic - next topic

tmk_009

Hey guys,

I'm pretty lucky with using the Midi Library and I want to use it further. I'm looking after a simple how-to about sending sysex with the midi library, in order to control an old synth by different events like incoming CC-Values into the arduino.

Lets say the sysex message has to be like this (14 bits), where XX is the value:

Code: [Select]
F0 43 10 26 02 06 01 00 1F 01 78 00 XX F7

How to write the code properly while it should be controlled by Midi CC 3:

Code: [Select]

#include <MIDI.h>

void setup() {
 MIDI.begin();
}

void loop() {
 if (MIDI.getType() == midi::ControlChange && MIDI.getData1() == 3) {  // only responds to values from Midi CC 3
      MIDI.sendSysEx(14, F0 43 10 26 02 06 01 00 1F 01 78 00 HEXVALUEFROMMIDICC3 F7); //this is crap
   }
}


Any ideas? Thanks!!


capicoso

#1
Mar 26, 2014, 03:18 am Last Edit: Mar 26, 2014, 03:22 am by capicoso Reason: 1
You have 14 bytes there, not bits.
If you check the MIDI library reference you'll see you're missing a parameter:
Code: [Select]
void sendSysEx (int length, const byte *const array, bool ArrayContainsBoundaries=false)
the first parameter is the length of the array to send, it says int, that's two bytes, but i think they meant byte.
The second parameter is the array containing the sysex message, and the third is a boolean one, which asks you if the array has the start and end bytes included, if they're, you set it to true, if not, you set it to false.

Like you said, your sysex part is crap.
First you have to declare a sysex array, for example

Code: [Select]
byte sysexArray[14] = {F0, 43, 10, 26, 02, 06, 01, 00, 1F, 01, 78, 00, 00, F7};
and then you send that array with:
Code: [Select]
MIDI.sendSysEx(14, sysexArray, true);

You want to vary the 12th element of your sysexArray.
When you receive your CC message, just change that position of the array with the incoming value.
So you want to pass your 2nd byte of your CC message to the 12th element of the sysexArray.
It would look something like:
Code: [Select]
CC = MIDI.getData2();
sysexArray[12] = CC;
MIDI.sendSysEx(14, sysexArray, true);

It's not tested, but you get the idea

tmk_009

This sounds very right! At first I have to write the array correctly, then send a hard programmed sequence to the synth to test it. Will post it soon!

tmk_009

#3
Apr 09, 2014, 11:16 am Last Edit: Apr 09, 2014, 12:04 pm by tmk_009 Reason: 1
It helped a lot and it's almost finished. There is one thing i don't get:

How to convert incoming values e.g. 127 into 0x7F (with leading 0x) on the fly? It works if I send the HEX value manually:

Code: [Select]
sysexArray[12] = (0x7F);
MIDI.sendSysEx(14, sysexArray, true);


The final array has to look like this:

Code: [Select]
byte sysexArray[14] = {0xF0, 0x43, 0x10, 0x26, 0x02, 0x06, 0x01, 0x00, 0x21, 0x01, 0x7F, 0x00, 0x7F, 0xF7};

If I just use string(127,HEX) it returns it without the leading 0x.

I tried sprintf, but well.... hm. help  :(

capicoso

It doesn't matter. You can send decimal and/or hex. The compiler doesn't care what it is. For it, it's binary, just that. Using decimal or hex is your choice. Instead of 0xF0 and 0xF7 for the sysex flag it can be 240 and 247.

tmk_009

#5
Apr 10, 2014, 03:41 pm Last Edit: Apr 10, 2014, 03:44 pm by tmk_009 Reason: 1
Are you sure this is correct? If i just ignore it then the array would look at the 12th value like

Code: [Select]
byte sysexArray[14] = {0xF0, 0x43, 0x10, 0x26, 0x02, 0x06, 0x01, 0x00, 0x21, 0x01, 0x7F, 0x00, 127, 0xF7};

And will of course be ignored by the Synth...

capicoso

Why don't you just put all in decimal?
If you don't believe me try it yourself. I tried it with a few synths and it worked.

tmk_009

Oooh you mean instead of F0, 43, 10 etc the corresponding decimals? Wow this would be awesome... I'll check this out next week when I'll be back.

This would be so easy.

Too easy.

capicoso

Yes. For example, I send midi clock with
Code: [Select]
Serial.write(248);

tmk_009

Great, i works! capicoso, i love your pragmatic approach! Its possible now to send CC-values from a new synth to an old synth and the arduino converts the cc-values to syses messages.

Code: [Select]

byte Sysexvalue[14] = {240, 67, 16, 38, 2, 6, 1, 0, 33, 1, 127, 0, 127, 247};
...
CC = 127 * 1,9448; // 127 is written manually for testing issues. Multiply to get scaling 0-127 > 0-247
Sysexvalue[12] = CC;
MIDI.sendSysEx(14, Sysexvalue, true);


Maybe there is a better way to convert CC Values 0-127 > 0-247 than multiply?

And I'll put a little delay to the sysex part not to flood the old synth.

kooroshi60

I need to do the exact same thing this topic is opened for.

I wrote this code according to Capiscoso instructions:
Code: [Select]
#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>

//Scale tuning switch for Roland Jv-1010

byte onArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x01, 0x78, 0xf7}; // ON array
byte offArray[12] = {0xf0, 0x41, 0x10, 0x6a, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x79, 0xf7}; // OFF array

void setup()
{
  MIDI.begin();
}

void loop()
{
  MIDI.sendSysEx(12, onArray, true);
  MIDI.sendSysEx(12, offArray, true);
}


But compiler is giving error " 'MIDI' was not declared in this scope"
This is going to be a Scale tuning ON/OFF switch for my Roland synth. So I'll add two switches for each array later.

But Now I need to figure out how to successfully transmit these 12 byte SysEx arrays to the MIDI device.

Grumpy_Mike

Quote
But compiler is giving error " 'MIDI' was not declared in this scope"
Have you installed the MIDI libiary correctly?

tonybaker2004

Hi Grumpy_Mike

Did you get your problem sorted out.  I've just started playing with this stuff and came across this thread.
It looks to me like you're missing "MIDI_CREATE_DEFAULT_INSTANCE();"
Your sketch complied OK when I added that line.

Grumpy_Mike

Quote
Hi Grumpy_Mike
Did you get your problem sorted out.
Well seeing as it was not my problem - no.

lokki

Great, i works! capicoso, i love your pragmatic approach! Its possible now to send CC-values from a new synth to an old synth and the arduino converts the cc-values to syses messages.

Code: [Select]

byte Sysexvalue[14] = {240, 67, 16, 38, 2, 6, 1, 0, 33, 1, 127, 0, 127, 247};
...
CC = 127 * 1,9448; // 127 is written manually for testing issues. Multiply to get scaling 0-127 > 0-247
Sysexvalue[12] = CC;
MIDI.sendSysEx(14, Sysexvalue, true);


Maybe there is a better way to convert CC Values 0-127 > 0-247 than multiply?

And I'll put a little delay to the sysex part not to flood the old synth.
you cannot send values higher than 127 in a sysex string.... if you want to send higher values you have to use multiple bytes, but the implementation varies from manufacturer to manufacturer

Go Up