Send 1 Sysex message depending on momentary switch State

Status
Not open for further replies.

Ripper

Well-known member
Hi guys.
I am just starting on this Teensy/Arduino thing.
I have a sketch to send usbmidi joystick for my Korg M3 module. It works for the joystick part. If i only needed that I would have my small midi controller ready, but I also need to send Sysex with 2 push buttons and that is where I am not having success with it.
The Sysex messages I need to send are dependent on the High (off) or Low (on) state of the momentary switches I have in Digital pins 0 and 1. These on/off states must be controlled by changing sequencialy everytime the buttons are pressed.

For Pin 0 the messages are:
in ON state:
0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7

in OFF state:
0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7

For Pin 1 the messages are:
in ON state:
0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7

in OFF state:
0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7

I thing there should be Bouce and fallingEdge ou RaisingEdge involved, but for now it is giving me a good fight to succeed.

This is my sketch with only usbmidi joystick

// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// ******CONSTANT VALUES******** - customize code behaviour here!

// SET THESE FOUR VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;


// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin,true};
ResponsiveAnalogRead readMod = {modPin,true};




void setup() {

}

void loop() {
getAnalogData();
while (usbMIDI.read()) {
}
}


//************ANALOG SECTION**************
void getAnalogData(){
readPitch.update();
if(readPitch.hasChanged()) {
pitchRaw = readPitch.getValue();
// remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
pitch = map(pitchRaw,4,1019,0,16383);
pitch = max(pitch,0); // need this now that the bottom isn't zero
pitch = min(pitch,16383); // cap to avoid overflow
if (abs(pitch - pitchLag)>0 && pitchUpdate > MIDIdelay ){
pitchLag = pitch;
usbMIDI.sendPitchBend( pitch, channel);
pitchUpdate = 0;
}
}

readMod.update();
if(readMod.hasChanged()) {
modRaw = readMod.getValue();
// remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
mod = map(modRaw,4,1019,0,127); // N.B. - map does not limit values
mod = max(mod,0); // minimum could overflow is modRaw is greater than calabrated
//mod = min(mod,127);
if (mod != modLag && modUpdate > MIDIdelay ){ // resolution reduction should be enough wi
modLag = mod;
usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
modUpdate = 0;
}
}
}
Can you please guide me on this?
Oh: I'm using Teensy ++2 and should be receiving a 3.6 this week.

Thank you
 
Last edited:
Bounce would probably be the easiest way to do it. Have a variable that tracks what step you are at that gets incremented each falling edge and a boolean 'haveSentSysex' that tracks if you have sent the updated counter value yet (keeping buttons asynch from your coms code).

Would suggest doing some playing just with bounce and the onboard LED to get an idea of how it goes together to make something that toggles (say make LED cycle between three different blink rates), rather than trying to graft it into your existing code straight up.
 
Bounce would probably be the easiest way to do it. Have a variable that tracks what step you are at that gets incremented each falling edge and a boolean 'haveSentSysex' that tracks if you have sent the updated counter value yet (keeping buttons asynch from your coms code).

Would suggest doing some playing just with bounce and the onboard LED to get an idea of how it goes together to make something that toggles (say make LED cycle between three different blink rates), rather than trying to graft it into your existing code straight up.

Thanks GremlinWrangler! ;)

My problem is writing the code for it. Anyway i will try.
Once again, thank you.

Best regards from Portugal,

Joao
 
Sending short midi messages is itself quite simple (reading data a little less so).

usbMIDI.sendSysEx(dataLength, data); // SEND

(I believe the length is exclusive of the status and end bytes... so 14 bytes for yours by my count)

Reading the current state of pin (HIGH/LOW) is simple enough too... then you build conditional statements to fire the correct message under the current conditions.

I'm not entirely clear on the desired output.

Is there any interaction between the two states in their output?

It sounds like you want note-on/note-off type behavior but with sysex...

If so you would replace those midi messages with yours starting with Paul's 'transmit' example:

Code:
#include <Bounce.h>  // Bounce library makes button change detection easy
const int channel = 1;

Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons
void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

}

void loop() {
  button1.update();
  button2.update();

  // Note On messages when each button is pressed
  if (button1.fallingEdge()) { 
    usbMIDI.sendSysEx(14, data1On)
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendSysEx(14, data2On)
  }

  // Note Off messages when each button is released
  if (button1.risingEdge()) {
    usbMIDI.sendSysEx(14, data1Off)
  }
  if (button2.risingEdge()) {
    usbMIDI.sendSysEx(14, data2Off)
  }


  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {
  }
}

This won't compile because it is missing declarations for four arrays of data:


data1On
data1Off
data2On
data2Off

But once you figure that out it shouldn't be too hard to get what you're looking for.
 
Hi oddson.
The Korg M3M synthesizer module doesn't have the keyboard as the full Korg M3 has, althought everything is equal in both versions.
It happens that the keyboard (which is detachable from the module) has a joystick, a ribbon and 2 buttons.
It's those 2 buttons that I am trying to make work in my Teensy controller (together with the joystick, but that is already sorted). Those buttons can have their CC# changed from program to program (or combi or... ) and the only way to activate or deactivate them is with Sysex.
When I enter a new program (individual sounds in Korg M3's language), or a Combi (multiple programs) it as a predefined state for the buttons, and it is that state that I want to change, as i would do with the original keyboard.
I don't know if you would call that note on/note off in Arduino language. A note on gets off when released, it doesn't seem it is what the M3 needs for the buttons.
I will work on your advise and tell you something latter.
Thank you.
 
I meant only that the behaviour I thought you were trying to achieve is similar to note on/off in that one button does not affect the other and you are not trying to replicate latching behaviour (storing on/off state based and toggling with fallingEdge).

If so, the logic of Paul's usbMIDI transmit example is readily altered into something that sends SysEx instead of note messages.

I do not understand what you are doing with the 'module' ... I was merely reading that you wish to send four sysex messages based HIGH/LOW of two pins (and it seems that the behaviour of the two buttons in independent).

I believe my approach is sound and you should be able to merge it into the Joystick code fairly easily.

FYI -- I believe you need to omit the start (0xF0) and stop (0xF7) bytes as usbSendSysEx expects only the data you're sending (just as you don't count them in the length parameter).
 
Last edited:
I tried with this code, but althought it compiles without errors, the buttons are not sending Sysex. I believe it is something like a erronious choice on the declarations type, but...

// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h> // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!


Bounce button1 = Bounce(1, 5); // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5); // which is appropriate for good quality mechanical pushbuttons


// SET THESE FOUR VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;




// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin,true};
ResponsiveAnalogRead readMod = {modPin,true};








void setup() {
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);


}


void loop() {
button1.update();
button2.update();
const byte data1On[] = {0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7 };
const byte data1Off[] = {0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7 };
const byte data2On[] = {0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7 };
const byte data2Off[] = {0xF0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7 };
// Note On messages when each button is pressed
if (button1.fallingEdge()) {
usbMIDI.sendSysEx(14, data1On);
}


if (button2.fallingEdge()) {
usbMIDI.sendSysEx(14, data2On);
}


// Note Off messages when each button is released
if (button1.risingEdge()) {
usbMIDI.sendSysEx(14, data1Off);
}
if (button2.risingEdge()) {
usbMIDI.sendSysEx(14, data2Off);
}


getAnalogData();
while (usbMIDI.read()) {
}
}




//************ANALOG SECTION**************
void getAnalogData(){
readPitch.update();
if(readPitch.hasChanged()) {
pitchRaw = readPitch.getValue();
// remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
pitch = map(pitchRaw,4,1019,0,16383);
pitch = max(pitch,0); // need this now that the bottom isn't zero
pitch = min(pitch,16383); // cap to avoid overflow
if (abs(pitch - pitchLag)>0 && pitchUpdate > MIDIdelay ){
pitchLag = pitch;
usbMIDI.sendPitchBend( pitch, channel);
pitchUpdate = 0;
}
}


readMod.update();
if(readMod.hasChanged()) {
modRaw = readMod.getValue();
// remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
mod = map(modRaw,4,1019,0,127); // N.B. - map does not limit values
mod = max(mod,0); // minimum could overflow is modRaw is greater than calabrated
//mod = min(mod,127);
if (mod != modLag && modUpdate > MIDIdelay ){ // resolution reduction should be enough wi
modLag = mod;
usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
modUpdate = 0;
}
}
}
 
You have the start and stop bytes in there... you need to strip them out....
Code:
const byte data1On[] = { 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01};
 const byte data1Off[] = { 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
 const byte data2On[] = { 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01};
 const byte data2Off[] = { 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00};


I've been coding VBA all morning so I can't remember how arrays work in C at the moment so I can't tell what else may be wrong... but you definitely don't send the SysEx start and end bytes the called routine in Paul's library does that for you.
 
I am trying to make the button send one Sysex message when i press that button and another one when i press it again. The button shouldn't do anything when i release it. The same for the second button, of course a different pair of Sysex messages.
 
Ah... that's what I meant by latching...

You need a variable for each button to keep track of the current state so it knows which message to send when it get's the 'change' message from the fallingEdge....

you need two Boolean variables; button1State and button2State for example

They will initialize to false.

Then test them along with the fallingEdge (you can ignore rising edge as that's just the button recovering after release... with latched behaviour you don't do anything with it).

If the Boolean is false send the first message and then set it to true for next time.

If it's already true send the other message and set the Boolean back to false....


Code:
  if (button1.fallingEdge()) { 
	if button1State then {
	    usbMIDI.sendSysEx(14, data1Off);
            button1State = FALSE;
	} else {
	    usbMIDI.sendSysEx(14, data1On) 
            button1State = TRUE;
	}
  }

This gives the latching behaviour where the output depends on the previous output...

This is what I was trying to get clear in my first post...


btw - can you use the advance features and put posted code inside code tags? Much easier to read than quotes as it retains the mono-spacing and indenting of code.
 
Last edited:
Ah... that's what I meant by latching...

You need a variable for each button to keep track of the current state so it knows which message to send when it get's the 'change' message from the fallingEdge....

you need two Boolean variables; button1State and button2State for example

They will initialize to false.

Then test them along with the fallingEdge (you can ignore rising edge as that's just the button recovering after release... with latched behaviour you don't do anything with it).

If the Boolean is false send the first message and then set it to true for next time.

If it's already true send the other message and set the Boolean back to false....

This gives the latching behaviour where the output depends on the previous output...

This is what I was trying to get clear in my first post...


btw - can you use the advance features and put posted code inside code tags? Much easier to read than quotes as it retains the mono-spacing and indenting of code.
Like Gremlinwrangler said too.
I will study that and post when i have something.
 
K... sounds like you're getting close. There's a code fragment I was adding to my last post when you replied.
 
Hi,
I just read you suggestion and tried to implement it. I must be missing something (like braces) once that the compiler is returning:
Code:
Arduino: 1.8.2 (Windows 10), TD: 1.36, Placa:"Teensy++ 2.0, MIDI, 16 MHz, German Swiss"


MidiJoystick2combotoes: In function 'void loop()':
MidiJoystick2combotoes:55: error: expected '(' before 'button1State'
     if button1State then {


        ^


MidiJoystick2combotoes:58: error: expected '}' before 'else'
     } else {


       ^


MidiJoystick2combotoes:60: error: expected ';' before 'button1State'
       button1State = TRUE;


       ^


MidiJoystick2combotoes:48: warning: unused variable 'data1Off' 
   const byte data1Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};


              ^


MidiJoystick2combotoes:49: warning: unused variable 'data2On' 
   const byte data2On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01};


              ^


MidiJoystick2combotoes:50: warning: unused variable 'data2Off' 
   const byte data2Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00};


              ^


C:\Users\Joao\Documents\Arduino\MidiJoystick2combotoes\MidiJoystick2combotoes.ino: At global scope:


MidiJoystick2combotoes:63: error: expected unqualified-id before 'if'
   if (button2.fallingEdge()) {


   ^


expected '(' before 'button1State'

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!


Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons


// SET THESE FOUR VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed
bool button1State = false;
bool button2State = false;


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;




// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};








void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);


}


void loop() {
  button1.update();
  button2.update();
  const byte data1On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01};
  const byte data1Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
  const byte data2On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01};
  const byte data2Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00};
  // Button on or off messages when each button is pressed




  if (button1.fallingEdge()) {
    if button1State then {
    usbMIDI.sendSysEx(14, data1Off);
      button1State = FALSE;
    } else {
      usbMIDI.sendSysEx(14, data1On)
      button1State = TRUE;
    }
  }
  if (button2.fallingEdge()) {
    if button2State then {
    usbMIDI.sendSysEx(14, data2Off);
      button2State = FALSE;
    } else {
      usbMIDI.sendSysEx(14, data2On)
      button2State = TRUE;
    }
  }




  getAnalogData();
  while (usbMIDI.read()) {
  }
}




//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 4, 1019, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }


  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 4, 1019, 0, 127); // N.B. - map does not limit values
    mod = max(mod, 0); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,127);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
}
 
Last edited:
I was missing semi colon in my fragment on a line end or two....

You should move the const declarations out of the main loop too
 
Last edited:
Moved the const declaration out of the main loop and put de semi-colon where i noticed it was missing, but it is still not enough.
I don't know if braces (or brackets) is missing in the one of the if clause.
I could try, but i'm affraid it changes the logic.

Code:
Arduino: 1.8.2 (Windows 10), TD: 1.36, Placa:"Teensy++ 2.0, MIDI, 16 MHz, German Swiss"


MidiJoystick2combotoes: In function 'void loop()':
MidiJoystick2combotoes:55: error: expected '(' before 'button1State'
     if button1State then {


        ^


MidiJoystick2combotoes:58: error: expected '}' before 'else'
     } else {


       ^


MidiJoystick2combotoes:60: error: 'TRUE' was not declared in this scope
       button1State = TRUE;


                      ^


C:\Users\Joao\Documents\Arduino\MidiJoystick2combotoes\MidiJoystick2combotoes.ino: At global scope:


MidiJoystick2combotoes:63: error: expected unqualified-id before 'if'
   if (button2.fallingEdge()) {


   ^


expected '(' before 'button1State'

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!


Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons


// SET THESE SIX VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed
bool button1State = false;
bool button2State = false;
const byte data1On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01};
const byte data1Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
const byte data2On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01};
const byte data2Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00};


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;




// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};






void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);


}


void loop() {
  button1.update();
  button2.update();
 
  // Button on or off messages when each button is pressed




  if (button1.fallingEdge()) {
    if button1State then {
    usbMIDI.sendSysEx(14, data1Off);
      button1State = FALSE;
    } else {
      usbMIDI.sendSysEx(14, data1On);
      button1State = TRUE;
    }
  }
  if (button2.fallingEdge()) {
    if button2State then {
    usbMIDI.sendSysEx(14, data2Off);
      button2State = FALSE;
    } else {
      usbMIDI.sendSysEx(14, data2On);
      button2State = TRUE;
    }
  }




  getAnalogData();
  while (usbMIDI.read()) {
  }
}




//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 4, 1019, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }


  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 4, 1019, 0, 127); // N.B. - map does not limit values
    mod = max(mod, 0); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,127);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
}
 
Last edited:
sorry ... C conditional tests need to be in parenthesis ... http://www.cprogramming.com/tutorial/c/lesson2.html

I'm not a C programmer and was just roughing in the code yesterday (I usually warn that I've not compiled the code so errors are likely but thought it was implied)... I assumed you have some idea about how it works since you've altered my previous code to get what you need.

I can have a look later but it's the kind of thing you're going to run into a lot with your own code so you might as well learn it now.

The compiler error messages tell you what's wrong... if it doesn't make sense then check the net for hints.

I think the other errors are just fall-out from not setting up the conditional test correctly.

EDIT

oh.. and this.

MidiJoystick2combotoes:60: error: 'TRUE' was not declared in this scope

means the Booleans were not declared correctly either...
I think they're meant to be lowercase.... I did warn I was coding in VBA all day ;)
 
Last edited:
Yes, oddson. I know I will have to read, google, try and ... herm, ask, heheheh. I'm prepared for that.
No, I'm not a programmer, just a curious musician (and clerk and bodybuilder), that knows a veeeeery tinny bit on some of the basics of programming.

I'll keep my fight.

Thank You for the kind help you are giving me.
 
Compiled with no errors. :p

Semi happy, Sysex doesn't work :rolleyes:

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!




Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons




// SET THESE SIX VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed
bool button1State = false;
bool button2State = false;
byte data1On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01};
byte data1Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00};
byte data2On[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01};
byte data2Off[] = {0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00};




const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;








// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};












void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);




}




void loop() {
  button1.update();
  button2.update();
 
  // Button on or off messages when each button is pressed








  if (button1.fallingEdge()) {
    if (button1State ==false) {
    usbMIDI.sendSysEx(14, data1Off);
      button1State = false;
    } else {
      usbMIDI.sendSysEx(14, data1On);
      button1State = true;
    }
  }
  if (button2.fallingEdge()) {
    if (button2State ==false) {
    usbMIDI.sendSysEx(14, data2Off);
      button2State = false;
    } else {
      usbMIDI.sendSysEx(14, data2On);
      button2State = true;
    }
  }








  getAnalogData();
  while (usbMIDI.read()) {
  }
}








//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 4, 1019, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }




  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 4, 1019, 0, 127); // N.B. - map does not limit values
    mod = max(mod, 0); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,127);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
}
 
Hmmm... looks like it should be sending something... you said it was working before but with the wrong behaviour (not latching) correct?


EDIT:

Do you have a proper MIDI monitor in software?

You could try inserting 'Serial.print(data1On);" where the booleans are reset and see if the array contains the correct data and weather the code is even firing as expected.

I'm not sure if you can serial print an array of bytes in one go like that. (I'm again not at a computer with Arduinio IDE)... but you could ask for the byte you're interested in: 'Serial.print(data1On[8]);"

Note: C arrays are zero indexed so the ninth element's index will be '8'.

Sorry.. without the IDE it's kinda hard to debug. Anyone else?
 
Last edited:
Already sending SYSEX, but only the dataxOff when pressing for both buttons.
I had to change the size of the SYSEX array to 16 and put the start/stop parts.

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!




Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons




// SET THESE SIX VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed
bool button1State = false;
bool button2State = false;
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};




const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;








// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};












void setup() {
  Serial.begin(31250);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);




}




void loop() {
  button1.update();
  button2.update();
 
  // Button on or off messages when each button is pressed




  if (button1.fallingEdge()) {
    if (button1State ==false) {
    usbMIDI.sendSysEx(16, data1Off);
      button1State = false;
    } else {
      usbMIDI.sendSysEx(16, data1On);
      button1State = true;
      Serial.print(data1On[7]);
    }
  }
  if (button2.fallingEdge()) {
    if (button2State ==false) {
    usbMIDI.sendSysEx(16, data2Off);
      button2State = false;
    } else {
      usbMIDI.sendSysEx(16, data2On);
      button2State = true;
    }
  }








  getAnalogData();
  while (usbMIDI.read()) {
  }
  }






//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 4, 1019, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }




  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 4, 1019, 0, 127); // N.B. - map does not limit values
    mod = max(mod, 0); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,127);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
}

Almost, I know, hehehehe
 
It works now.
The only thing that is bugging me is that when i press the other button for the first time, it will send the last sysex that the first button sent. Pushing it again will send the right sysex and alter the sysex sent according to what I want it to do, as it should.
It does this for both Button1 and Button2, whether I push button1 or button2 first, it will always send the last sysex that was sent by the other button.

For instance, i connect the teensy to usb and press Button1. It will send, as it should:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};

If I push the same button again, it will send, as it should:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};

If i then push Button2, it will send, wrongly:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};

Pushing it again will send, as is should:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};

Pushing it again will send, as it should:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};

Pushing it again will send, as is should:

Code:
{0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};


... and so on...


The code i'm using at the moment is: (Some comments are wrong, once that i changed the "if(digitalRead(x) == LOW)" form "if(digitalRead(x) == HIGH)", because it was continuously doing the usbMIDI.sendSysEx without even pushing the buttons)


Code:
int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //I'll explain later
int OldButton2 = 0; //I'll explain later
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};




void setup() {
 pinMode(1, INPUT_PULLUP); //Pin 1 is an Input
 pinMode(2, INPUT_PULLUP); //Pin 2 is an Input
}


void loop() {
 if(digitalRead(1) == LOW) { //If Pin 1 is low (At 5 Volts)
   Button1 = 1 - Button1; //If Button1 is set as 0 then Button = 1 - 0 (=1) and if Button1 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button1 == 1 && OldButton1 == 0) { //If Button1 is 1 and OldButton1 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data1On); //Send SysEX for SW1 On
 }
 
 if(Button1 == 0 && OldButton1 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data1Off);//Send SysEX for SW1 Off
 }


 OldButton1 = Button1; //The data is now old
delay(100);




 if(digitalRead(2) == LOW) { //If Pin 2 is high (At 5 Volts)
   Button2 = 1 - Button2; //If Button2 is set as 0 then Button = 1 - 0 (=1) and if Button2 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button2 == 1 && OldButton2 == 0) { //If Button2 is 1 and OldButton2 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data2On); //Send SysEX for SW2 On
 }
 
 if(Button2 == 0 && OldButton2 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data2Off);//Send SysEX for SW2 Off
 }


 OldButton2 = Button2; //The data is now old
 delay(100);
}

The code I'm trying is from https://forum.arduino.cc/index.php?topic=58284.0 adapted to my case.
 
Last edited:
The complete code, which is working is:

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!


Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons


// SET THESE SIX VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down??? read note from DOEPFER on 2nd pot reversed
int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //Variable to store button1 old value
int OldButton2 = 0; //Variable to store button2 old value
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int pitchRaw;
int modRaw;
int pitchLag;
int modLag;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;




// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};






void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
 
}

void loop() {
 if(digitalRead(1) == LOW) { //If Pin 1 is low (At 5 Volts)
   Button1 = 1 - Button1; //If Button1 is set as 0 then Button = 1 - 0 (=1) and if Button1 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button1 == 1 && OldButton1 == 0) { //If Button1 is 1 and OldButton1 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data1On); //Delay for half a second
 }
 
 if(Button1 == 0 && OldButton1 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data1Off);//Send SysEX to Channel1
 }

 OldButton1 = Button1; //The data is now old
delay(100);


 if(digitalRead(2) == LOW) { //If Pin 2 is high (At 5 Volts)
   Button2 = 1 - Button2; //If Button2 is set as 0 then Button = 1 - 0 (=1) and if Button2 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button2 == 1 && OldButton2 == 0) { //If Button2 is 1 and OldButton2 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data2On); //Delay for half a second
 }
 
 if(Button2 == 0 && OldButton2 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data2Off);//Send SysEX to Channel1
 }

 OldButton2 = Button2; //The data is now old
 delay(100);




  getAnalogData();
  while (usbMIDI.read()) {
  }
  }



//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 3, 999, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }


  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 3, 999, 0, 127); // N.B. - map does not limit values
    mod = max(mod, 0); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,127);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
}

I'm now trying to figure out how to put CC#1 for joystick up (positive values, or >= 64, if working with the standard 0-127 range) and CC#2 for joystick down (negative values or <=63).
 
I can already make the joystick send different CC# as Joystick Y position goes Center-Up or Center-Down. My only problem is that CC#2 (which is the one I am using for the Center-Up fragment is also cending for on the Center-Down.
CC#1 Is correctly sending on Center-Down, only.
The code is:

Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
// ******CONSTANT VALUES******** - customize code behaviour here!


Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good quality mechanical pushbuttons


// SET THESE SIX VALUES!
const int pitchPin = 0; // PIN numbers ** MUST CHANGE!
const int modPin = 1;
const int modPin2 = 1;
const int pitchMaxRaw = 1019; // Max reading with full bend up... as raw 10-bit value
const int modMaxRaw = 1019; // Max reading full mod down

int Button1 = 0; //This is the default "Button Off" and 1 is "Button On"
int Button2 = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton1 = 0; //Variable to store button1 old value
int OldButton2 = 0; //Variable to store button2 old value
byte data1On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data1Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};
byte data2On[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf7};
byte data2Off[] = {0xf0, 0x42, 0x30, 0x75, 0x41, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7};


const int channel = 1; // MIDI channel
const int MIDIdelay = 5; // will update MIDI only if this many milliseconds have passed
//******VARIABLES***********
// data variables and a lagged copy to compare before updating MIDI value
int pitch;
int mod;
int mod2;
int pitchRaw;
int modRaw;
int modRaw2;
int pitchLag;
int modLag;
int modLag2;
elapsedMillis pitchUpdate;
elapsedMillis modUpdate;
elapsedMillis modUpdate2;




// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead readPitch = {pitchPin, true};
ResponsiveAnalogRead readMod = {modPin, true};
ResponsiveAnalogRead readMod2 = {modPin2, true};







void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
 
}

void loop() {
 if(digitalRead(1) == LOW) { //If Pin 1 is low (At 5 Volts)
   Button1 = 1 - Button1; //If Button1 is set as 0 then Button = 1 - 0 (=1) and if Button1 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button1 == 1 && OldButton1 == 0) { //If Button1 is 1 and OldButton1 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data1On); //Delay for half a second
 }
 
 if(Button1 == 0 && OldButton1 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data1Off);//Send SysEX to Channel1
 }

 OldButton1 = Button1; //The data is now old
delay(100);


 if(digitalRead(2) == LOW) { //If Pin 2 is high (At 5 Volts)
   Button2 = 1 - Button2; //If Button2 is set as 0 then Button = 1 - 0 (=1) and if Button2 is 1 then Button=1 - 1 (=0)
 }
 
 if(Button2 == 1 && OldButton2 == 0) { //If Button2 is 1 and OldButton2 is 0 (This means basically means "If the button1 was just pressed"
     //Put what you want to happen when "SW1" is on here
    usbMIDI.sendSysEx(16, data2On); //Delay for half a second
 }
 
 if(Button2 == 0 && OldButton2 == 1) {
   //Put what you want to happen when "SW1" is off here
   usbMIDI.sendSysEx(16, data2Off);//Send SysEX to Channel1
 }

 OldButton2 = Button2; //The data is now old
 delay(100);




  getAnalogData();
  while (usbMIDI.read()) {
  }
  }



//************ANALOG SECTION**************
void getAnalogData() {
  readPitch.update();
  if (readPitch.hasChanged()) {
    pitchRaw = readPitch.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    pitch = map(pitchRaw, 3, 1019, 0, 16383);
    pitch = max(pitch, 0); // need this now that the bottom isn't zero
    pitch = min(pitch, 16383); // cap to avoid overflow
    if (abs(pitch - pitchLag) > 0 && pitchUpdate > MIDIdelay ) {
      pitchLag = pitch;
      usbMIDI.sendPitchBend( pitch, channel);
      pitchUpdate = 0;
    }
  }


  readMod.update();
  if (readMod.hasChanged()) {
    modRaw = readMod.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod = map(modRaw, 510, 1019, 64, 127); // N.B. - map does not limit values
    mod = max(mod, 64); // minimum could overflow is modRaw is greater than calabrated
    //mod = min(mod,64);
    if (mod != modLag && modUpdate > MIDIdelay ) { // resolution reduction should be enough wi
      modLag = mod;
      usbMIDI.sendControlChange(1, mod, channel); // CC = 1 is mod wheel in standard MIDI
      modUpdate = 0;
    }
  }
  readMod2.update();
  if (readMod2.hasChanged()) {
    modRaw2 = readMod2.getValue();
    // remap to output data and send if changed and MIDIdelay has lapsed since last update for that parameter
    mod2 = map(modRaw2, 3, 508, 0, 63); // N.B. - map does not limit values
    mod2 = max(mod2, 0); // minimum could overflow is modRaw2 is greater than calibrated
    //mod = min(mod,0);
    if (mod2 != modLag2 && modUpdate2 > MIDIdelay ) { // resolution reduction should be enough wi
      modLag2 = mod2;
      usbMIDI.sendControlChange(2, mod2, channel); // CC = 2 is Breath Control in standard MIDI -In this case it is 
      modUpdate2 = 0;
    }
  {
  }
  }
  }

I know it is a detail I'm missing, but for now I haven't succeeded on discovering my bug.
 
Status
Not open for further replies.
Back
Top