Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: How can I change which CC's my MIDI controller is sending AFTER the initial setup?

  1. #1

    How can I change which CC's my MIDI controller is sending AFTER the initial setup?

    I just built a MIDI CC controller using a Teensy 3.2. I copied the code that someone else had used and it uses the code below to assign which CC's the six potentiometers on my controller will send.

    // define pins and cc codes
    const int A_PINS = 6;
    const int ANALOG_PINS[A_PINS] = {A0, A1, A2, A3, A4, A5};
    const int CCID[A_PINS] = {11, 1, 4, 2, 1, 21};

    // a data array and a lagged copy to tell when MIDI changes are required
    byte data[A_PINS];
    byte dataLag[A_PINS];

    // ititialize the ReponsiveAnalogRead objects
    ResponsiveAnalogRead analog[]{
    ///////////////////////////////////////////////////////////////////////////
    {ANALOG_PINS[1],true},
    {ANALOG_PINS[2],true},
    {ANALOG_PINS[3],true},
    {ANALOG_PINS[4],true},
    {ANALOG_PINS[5],true},
    {ANALOG_PINS[0],true},

    That works fine, but I'd like to have the ability to update the CC assignments to one of five predefined "sets" while the program is running. I have a selector switch wired up and it's working fine, but I don't know what command could be used to update the CC assignments for the 6 pots while the program is looping. I tried using CCID[A_PINS] = {11, 1, 4, 2, 1, 21}; and that caused an error*, so I'm thinking that command may only work during setup. Any help will be greatly appreciated!


    * ERROR:
    Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy 3.2 / 3.1, MIDI, 96 MHz (overclock), Faster, US English"

    CCID[A_PINS] = {11, 11, 11, 1, 1, 11};
    ^
    C:\Users\Family Dell 2016\Documents\Arduino\MIDI_Controller_V5_with-5Banks\MIDI_Controller_V5_with-5Banks.ino:99:17: error: cannot convert '<brace-enclosed initializer list>' to 'const int' in assignment

    Error compiling for board Teensy 3.2 / 3.1.

  2. #2
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    229
    @LikeToBuildStuff:

    You are essentially correct that the line that you attempted to "reuse" is only used to set things up. The line that you pointed out is a variable declaration (CCID[A_PINS]) for an array named CCID that contains integers (int), with the number of elements defined by A_PINS. This declaration of CCID includes an initializer (= {11, 1, 4, 2, 1, 21}), which means that it is filled with those particular known values at the startup of your program. In addition, this particular variable declaration includes the syntax (const) which specifies that the contents of the array are not allowed to change while your program is running.

    So, reading from left to right, your variable declaration statement says the following:

    This is an unchanging array which contains 6 integers, & the values of the integers will be 11, 1, 4, 2, 1, 21, where 11 will be stored in the first element of the array (CCID[0]), 1 will be stored in the second element of the array (CCID[1]), etc. with 21 stored in the last element of the array (CCID[5]).

    The simplest way to expand what you have is to turn the CCID array of pins into a 2-dimensional array. You can change what you have to the following (this is written with the assumption that you will have 3 sets of pin definitions . . . change this as appropriate):

    Code:
    const int A_PINS = 6;
    const int CC_SETS = 3;
    const int CCID[CC_SETS, A_PINS] = {{11, 1, 4, 2, 1, 21}, {12, 2, 5, 3, 2, 22}, {13, 3, 6, 4, 3, 23}};
    This definition & initializer will cause the values for the first set to be set to 11, 1, 4, 2, 1, & 21, the second set to 12, 2, 5, 3, 2, 22, & the third set to 13, 3, 6, 4, 3, 23. Of course, you will need to substitute the appropriate values for your desired CC messages for each set.

    Now, in your program, lets say you have a variable called "pin" that keeps track of which pin you are reading, & you have a variable called "set" which keeps track of which set of CC definitions that you want to use. So, with use of these variables, for example, if you want to use the first set of pin definitions & reference the CC for the third pin, you'll set "set = 0;", along with "pin = 2;". Then, using these settings, you would reference CCID[set, pin] to get the appropriate CC value for the intended analog pin.

    Hope this helps. Feel free to ask more questions . . .

    Mark J Culross
    KD5RXT

  3. #3
    Quote Originally Posted by kd5rxt-mark View Post
    @LikeToBuildStuff:

    Hope this helps. Feel free to ask more questions . . .

    Mark J Culross
    KD5RXT
    Mark - thank you so much for the thorough and clear response. I think I understand your suggestions and tried to implement them in my program, but I'm getting another error so I must have some syntax incorrect. I've copied my entire program below so that you can see what I've done. Sorry for all the 1's and 11's - they are not the final CC values I will use but will make it easier to check my controller is responding correctly. Thanks again for your help!

    #include <Bounce.h>

    ///////////////////////////////////////////////////////////////////////////
    // define how many pots are active up to number of available analog inputs
    #define analogInputs 6
    //////////////////////////////////////////////////////////////////////////


    // define arrays for input values and lagged input values
    int inputAnalog[analogInputs];
    int iAlag[analogInputs];
    // define array of cc values
    int ccValue[analogInputs];
    // include the ResponsiveAnalogRead library
    #include <ResponsiveAnalogRead.h>

    // Define variables for Rotary Switch function (used to define one of 5 CC sets)
    int RotNewState;
    int Pin1State;
    int Pin3State;
    int Pin4State;
    int Pin7State;


    ///////////////////////////////////////////////////////////////////////////
    // define pins and cc codes
    const int A_PINS = 6;
    const int ANALOG_PINS[A_PINS] = {A0, A1, A2, A3, A4, A5};
    const int CC_SETS = 5;
    const int CCID[CC_SETS, A_PINS] = {{11,11,11,1,1,11},{11,11,1,11,1,11},{11,1,11,11,1 ,11},{1,11,11,11,1,11},{11,11,11,11,1,1}};
    ///////////////////////////////////////////////////////////////////////////

    // //////// REFERENCE INFO /////////////////////////////////////////////
    // Four sliders left-to-right are A3, A2, A1, A0, A5. Footpedal is A4
    //0=bank, 1=mod, 2=Breath, 7=Vol, 8=Bal, 10=pan, 4=foot, 11=Expr, 21=Vib 64=pedal
    /////////////////////////////////////////////////////////////////////////

    // a data array and a lagged copy to tell when MIDI changes are required
    byte data[A_PINS];
    byte dataLag[A_PINS];

    // ititialize the ReponsiveAnalogRead objects
    ResponsiveAnalogRead analog[]{
    ///////////////////////////////////////////////////////////////////////////
    {ANALOG_PINS[1],true},
    {ANALOG_PINS[2],true},
    {ANALOG_PINS[3],true},
    {ANALOG_PINS[4],true},
    {ANALOG_PINS[5],true},
    {ANALOG_PINS[0],true},
    ///////////////////////////////////////////////////////////////////////////
    };

    // the setup routine runs once when you press reset:
    void setup() {
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);

    // Define Input pins (from 5-position Rotary Switch)
    pinMode (1,INPUT);
    pinMode (3,INPUT);
    pinMode (4,INPUT);
    pinMode (7,INPUT);

    }

    void loop(){

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


    // Determine the state of the 4 pins coming from the rotary switch
    Pin1State=digitalRead(1);
    Pin3State=digitalRead(3);
    Pin4State=digitalRead(4);
    Pin7State=digitalRead(7);

    // Deduce the "CC Set" selected on the Rotary Switch and store in variable "RotNewState";
    if (Pin3State==HIGH && Pin7State==HIGH){
    RotNewState=1;
    }
    if (Pin4State==HIGH && Pin7State==HIGH){
    RotNewState=2;
    }
    if (Pin4State==HIGH && Pin7State==LOW){
    RotNewState=3;
    }
    if (Pin1State==HIGH && Pin4State==HIGH){
    RotNewState=4;
    }
    if (Pin1State==HIGH && Pin4State==LOW){
    RotNewState=5;
    }


    // Serial.println(RotNewState); //was used to check function of determining rotary switch position -> worked fine.

    }

    // update the ResponsiveAnalogRead object every loop
    for (int i=0;i<A_PINS;i++){
    analog[i].update();
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
    data[i] = analog[i].getValue()>>3;
    if (data[i] != dataLag[i]){
    dataLag[i] = data[i];
    usbMIDI.sendControlChange(CCID[RotNewState,i], data[i], 1);
    }
    }
    }
    }


    *********** ERROR RECEIVED ****************

    C:\Users\Family Dell 2016\Documents\Arduino\MIDI_Controller_V7_with-5CCsets\MIDI_Controller_V7_with-5CCsets.ino:31:23: error: expected ']' before ',' token
    const int CCID[CC_SETS, A_PINS] = {{11,11,11,1,1,11},{11,11,1,11,1,11},{11,1,11,11,1 ,11},{1,11,11,11,1,11},{11,11,11,11,1,1}};
    ^
    C:\Users\Family Dell 2016\Documents\Arduino\MIDI_Controller_V7_with-5CCsets\MIDI_Controller_V7_with-5CCsets.ino:31:31: error: expected initializer before ']' token
    const int CCID[CC_SETS, A_PINS] = {{11,11,11,1,1,11},{11,11,1,11,1,11},{11,1,11,11,1 ,11},{1,11,11,11,1,11},{11,11,11,11,1,1}};
    ^
    Error compiling for board Teensy 3.2 / 3.1.

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,568
    The syntax for the two-dimensional array is wrong. It should be this:
    Code:
    const int CCID[CC_SETS][A_PINS] = {{11,11,11,1,1,11},{11,11,1,11,1,11},{11,1,11,11,1 ,11},{1,11,11,11,1,11},{11,11,11,11,1,1}};
    Similarly, the reference to the array should be like this:
    Code:
    usbMIDI.sendControlChange(CCID[RotNewState][i], data[i], 1);
    Pete

  5. #5
    Quote Originally Posted by el_supremo View Post
    The syntax for the two-dimensional array is wrong. It should be this:
    Code:
    const int CCID[CC_SETS][A_PINS] = {{11,11,11,1,1,11},{11,11,1,11,1,11},{11,1,11,11,1 ,11},{1,11,11,11,1,11},{11,11,11,11,1,1}};
    Similarly, the reference to the array should be like this:
    Code:
    usbMIDI.sendControlChange(CCID[RotNewState][i], data[i], 1);
    Pete
    Pete - Thanks very much for the prompt reply. I made the two syntax changes you suggested and that part of the code no longer causes errors, however I am now getting the errors below. I'm a bit puzzled since that part of the code worked fine before I made CCID an array (ie, when I just had one set of CC assignments). Any suggestions for what could be wrong now will be much appreciated.

    *************** NEW ERROR ******************
    C:\Users\Family Dell 2016\Documents\Arduino\MIDI_Controller_V8_with-5CCsets\MIDI_Controller_V8_with-5CCsets.ino:103:25: error: 'i' does not name a type
    for (int i=0;i<A_PINS;i++){
    ^
    C:\Users\Family Dell 2016\Documents\Arduino\MIDI_Controller_V8_with-5CCsets\MIDI_Controller_V8_with-5CCsets.ino:114:1: error: expected declaration before '}' token
    }
    ^
    Error compiling for board Teensy 3.2 / 3.1.

  6. #6
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    229
    LikeToBuildStuff:

    Dang it !! Sorry, I wasn't at my primary PC when I typed my first reply. I'll use the excuse that I'm old & something else, but I'm having trouble remembering what the other thing is . . . oh yeah, forgetful !! I'm forgetful, so that's my excuse for the poor syntax . . . I was in a rush to help, but I really should have actually tested what I typed before I hit the send button. Nothing like posting suggestions that cause more errors instead of less !! Thanks to Pete for jumping in to provide corrections !!

    When you post code, it helps if the code is surrounded with CODE tags (just click the "#" in the bar of icons right above the text composition window here on the forum, then paste your code between the two tags). Also, for your own benefit, if you're using the Arduino IDE, you can use CTRL-T to auto (re)format the code with indentations, etc. That will make it much easier for you (& others as well) to read. Definitely don't take these suggestions as any kind of criticism . . . I applaud you for diving into this with both feet !!

    Here's a slightly updated version of the code that you posted earlier (reformatted) . . . it looks like you had one too many closing braces (}) . . . the closing brace right before the for loop was removed in the code below:

    Code:
    #include <Bounce.h>
    
    ///////////////////////////////////////////////////////////////////////////
    // define how many pots are active up to number of available analog inputs
    #define analogInputs 6
    //////////////////////////////////////////////////////////////////////////
    
    
    // define arrays for input values and lagged input values
    int inputAnalog[analogInputs];
    int iAlag[analogInputs];
    // define array of cc values
    int ccValue[analogInputs];
    // include the ResponsiveAnalogRead library
    #include <ResponsiveAnalogRead.h>
    
    // Define variables for Rotary Switch function (used to define one of 5 CC sets)
    int RotNewState;
    int Pin1State;
    int Pin3State;
    int Pin4State;
    int Pin7State;
    
    
    ///////////////////////////////////////////////////////////////////////////
    // define pins and cc codes
    const int A_PINS = 6;
    const int ANALOG_PINS[A_PINS] = {A0, A1, A2, A3, A4, A5};
    const int CC_SETS = 5;
    const int CCID[CC_SETS][A_PINS] = {{11, 11, 11, 1, 1, 11}, {11, 11, 1, 11, 1, 11}, {11, 1, 11, 11, 1 , 11}, {1, 11, 11, 11, 1, 11}, {11, 11, 11, 11, 1, 1}};
    ///////////////////////////////////////////////////////////////////////////
    
    // //////// REFERENCE INFO /////////////////////////////////////////////
    // Four sliders left-to-right are A3, A2, A1, A0, A5. Footpedal is A4
    //0=bank, 1=mod, 2=Breath, 7=Vol, 8=Bal, 10=pan, 4=foot, 11=Expr, 21=Vib 64=pedal
    /////////////////////////////////////////////////////////////////////////
    
    // a data array and a lagged copy to tell when MIDI changes are required
    byte data[A_PINS];
    byte dataLag[A_PINS];
    
    // ititialize the ReponsiveAnalogRead objects
    ResponsiveAnalogRead analog[] {
       ///////////////////////////////////////////////////////////////////////////
       {ANALOG_PINS[1], true},
       {ANALOG_PINS[2], true},
       {ANALOG_PINS[3], true},
       {ANALOG_PINS[4], true},
       {ANALOG_PINS[5], true},
       {ANALOG_PINS[0], true},
       ///////////////////////////////////////////////////////////////////////////
    };
    
    // the setup routine runs once when you press reset:
    void setup() {
       // initialize serial communication at 9600 bits per second:
       Serial.begin(9600);
    
       // Define Input pins (from 5-position Rotary Switch)
       pinMode (1, INPUT);
       pinMode (3, INPUT);
       pinMode (4, INPUT);
       pinMode (7, INPUT);
    
    }
    
    void loop() {
    
       // MIDI Controllers should discard incoming MIDI messages.
       while (usbMIDI.read()) {
          // read & ignore incoming messages
       }
    
    
       // Determine the state of the 4 pins coming from the rotary switch
       Pin1State = digitalRead(1);
       Pin3State = digitalRead(3);
       Pin4State = digitalRead(4);
       Pin7State = digitalRead(7);
    
       // Deduce the "CC Set" selected on the Rotary Switch and store in variable "RotNewState";
       if (Pin3State == HIGH && Pin7State == HIGH) {
          RotNewState = 1;
       }
       if (Pin4State == HIGH && Pin7State == HIGH) {
          RotNewState = 2;
       }
       if (Pin4State == HIGH && Pin7State == LOW) {
          RotNewState = 3;
       }
       if (Pin1State == HIGH && Pin4State == HIGH) {
          RotNewState = 4;
       }
       if (Pin1State == HIGH && Pin4State == LOW) {
          RotNewState = 5;
       }
    
    
       // Serial.println(RotNewState); //was used to check function of determining rotary switch position -> worked fine.
    
    
    
       // update the ResponsiveAnalogRead object every loop
       for (int i = 0; i < A_PINS; i++) {
          analog[i].update();
          // if the repsonsive value has change, print out 'changed'
          if (analog[i].hasChanged()) {
             data[i] = analog[i].getValue() >> 3;
             if (data[i] != dataLag[i]) {
                dataLag[i] = data[i];
                usbMIDI.sendControlChange(CCID[RotNewState][i], data[i], 1);
             }
          }
       }
    }
    Keep at it . . . you're almost there !!

    Good luck & have fun !!

    Mark J Culross
    KD5RXT
    Last edited by kd5rxt-mark; 03-06-2021 at 03:16 AM. Reason: corrected wording

  7. #7
    Thank you, Mark! Everything works perfectly now.

    And I appreciate your helpful suggestions for formatting and posting code. It's so nice that there are folks like you and Pete willing to help solve issues like this.

    [One last thing in case others want to re-use any of this code. I had to make my variable "RotNewState" go from 0 to 4 (rather than from 1 to 5) in order for everything to work correctly when sending MIDI CC's.]

    Here is my final code with all corrections and formatting;
    Code:
    #include <Bounce.h>
    
    ///////////////////////////////////////////////////////////////////////////
    // define how many pots are active up to number of available analog inputs
    #define analogInputs 6
    //////////////////////////////////////////////////////////////////////////
    
    
    // define arrays for input values and lagged input values
    int inputAnalog[analogInputs];
    int iAlag[analogInputs];
    // define array of cc values
    int ccValue[analogInputs];
    // include the ResponsiveAnalogRead library
    #include <ResponsiveAnalogRead.h>
    
    // Define variables for Rotary Switch function (used to define one of 5 CC sets)
    int RotNewState;
    int Pin1State;
    int Pin3State;
    int Pin4State;
    int Pin7State;
    
    
    ///////////////////////////////////////////////////////////////////////////
    // define pins and cc codes
    const int A_PINS = 6;
    const int ANALOG_PINS[A_PINS] = {A0, A1, A2, A3, A4, A5};
    const int CC_SETS = 5;
    const int CCID[CC_SETS][A_PINS] = {{11, 11, 11, 1, 1, 11}, {11, 11, 1, 11, 1, 11}, {11, 1, 11, 11, 1 , 11}, {1, 11, 11, 11, 1, 11}, {11, 11, 11, 11, 1, 1}};
    ///  1's and 11's are for testing the controller only.  Update to desired CC's in final version 
    ///////////////////////////////////////////////////////////////////////////
    
    // //////// REFERENCE INFO /////////////////////////////////////////////
    // Four sliders left-to-right are A3, A2, A1, A0, A5. Footpedal is A4
    //0=bank, 1=mod, 2=Breath, 7=Vol, 8=Bal, 10=pan, 4=foot, 11=Expr, 21=Vib 64=pedal
    /////////////////////////////////////////////////////////////////////////
    
    // a data array and a lagged copy to tell when MIDI changes are required
    byte data[A_PINS];
    byte dataLag[A_PINS];
    
    // ititialize the ReponsiveAnalogRead objects
    ResponsiveAnalogRead analog[] {
      ///////////////////////////////////////////////////////////////////////////
      {ANALOG_PINS[1], true},
      {ANALOG_PINS[2], true},
      {ANALOG_PINS[3], true},
      {ANALOG_PINS[4], true},
      {ANALOG_PINS[5], true},
      {ANALOG_PINS[0], true},
      ///////////////////////////////////////////////////////////////////////////
    };
    
    // the setup routine runs once when you press reset:
    void setup() {
      // initialize serial communication at 9600 bits per second:
      Serial.begin(9600);
    
      // Define Input pins (from 5-position Rotary Switch)
      pinMode (1, INPUT);
      pinMode (3, INPUT);
      pinMode (4, INPUT);
      pinMode (7, INPUT);
    
    }
    
    void loop() {
    
      // MIDI Controllers should discard incoming MIDI messages.
      while (usbMIDI.read()) {
        // read & ignore incoming messages
      }
    
    
      // Determine the state of the 4 pins coming from the rotary switch
      Pin1State = digitalRead(1);
      Pin3State = digitalRead(3);
      Pin4State = digitalRead(4);
      Pin7State = digitalRead(7);
    
      // Deduce the "CC Set" selected on the Rotary Switch and store in variable "RotNewState";
      if (Pin3State == HIGH && Pin7State == HIGH) {
        RotNewState = 0;
      }
      if (Pin4State == HIGH && Pin7State == HIGH) {
        RotNewState = 1;
      }
      if (Pin4State == HIGH && Pin7State == LOW) {
        RotNewState = 2;
      }
      if (Pin1State == HIGH && Pin4State == HIGH) {
        RotNewState = 3;
      }
      if (Pin1State == HIGH && Pin4State == LOW) {
        RotNewState = 4;
      }
    
    
      // Serial.println(RotNewState); //was used to check function of determining rotary switch position -> worked fine.
    
    
    
      // update the ResponsiveAnalogRead object every loop
      for (int i = 0; i < A_PINS; i++) {
        analog[i].update();
        // if the repsonsive value has change, print out 'changed'
        if (analog[i].hasChanged()) {
          data[i] = analog[i].getValue() >> 3;
          if (data[i] != dataLag[i]) {
            dataLag[i] = data[i];
            usbMIDI.sendControlChange(CCID[RotNewState][i], data[i], 1);
          }
        }
      }
    }

  8. #8
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    229
    Glad I could help in a small way. Pete & others kindly helped me when I first got started with Teensy, so I try to pay my appreciation forward to others in a similar way whenever I can.

    Mark J Culross
    KD5RXT

Posting Permissions

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