Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 6 1 2 3 ... LastLast
Results 1 to 25 of 140

Thread: Send 1 Sysex message depending on momentary switch State

  1. #1
    Senior Member
    Join Date
    May 2017
    Posts
    102

    Send 1 Sysex message depending on momentary switch State

    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 by Ripper; 06-04-2017 at 08:55 PM. Reason: Typos

  2. #2
    Senior Member
    Join Date
    Apr 2013
    Posts
    1,874
    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.

  3. #3
    Senior Member
    Join Date
    May 2017
    Posts
    102
    Quote Originally Posted by GremlinWrangler View Post
    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

  4. #4
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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.

  5. #5
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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.

  6. #6
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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 by oddson; 06-05-2017 at 05:45 PM.

  7. #7
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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;
    }
    }
    }

  8. #8
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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.

  9. #9
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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.

  10. #10
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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 by oddson; 06-05-2017 at 08:43 PM.

  11. #11
    Senior Member
    Join Date
    May 2017
    Posts
    102
    Quote Originally Posted by oddson View Post
    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.

  12. #12
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    K... sounds like you're getting close. There's a code fragment I was adding to my last post when you replied.

  13. #13
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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 by Ripper; 06-06-2017 at 09:34 AM. Reason: Forgot the complete code

  14. #14
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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 by oddson; 06-06-2017 at 02:13 PM.

  15. #15
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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 by Ripper; 06-06-2017 at 02:58 PM.

  16. #16
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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 by oddson; 06-06-2017 at 04:24 PM.

  17. #17
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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.

  18. #18
    Senior Member
    Join Date
    May 2017
    Posts
    102
    Compiled with no errors.

    Semi happy, Sysex doesn't work

    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;
        }
      }
    }

  19. #19
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,090
    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 by oddson; 06-06-2017 at 06:28 PM.

  20. #20
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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

  21. #21
    Senior Member
    Join Date
    May 2017
    Posts
    102
    I'm affraid i'm not succeeding on doing this thing till now.

  22. #22
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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 by Ripper; 06-09-2017 at 07:39 AM.

  23. #23
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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).

  24. #24
    Senior Member
    Join Date
    May 2017
    Posts
    102
    No one has a clue on this one?

  25. #25
    Senior Member
    Join Date
    May 2017
    Posts
    102
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •