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

Status
Not open for further replies.
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.
 

@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
 
@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.update();
// if the repsonsive value has change, print out 'changed'
if(analog.hasChanged()) {
data = analog.getValue()>>3;
if (data != dataLag){
dataLag = data;
usbMIDI.sendControlChange(CCID[RotNewState,i], data, 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.
 
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
 
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.
 
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:
Thank you, Mark! Everything works perfectly now. :D

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);
      }
    }
  }
}
 
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
 
Another newbie i'm afraid

Hello my question is exactly the same as "Like to build stuff" how to change cc number after programing Teensy.

I've made a 3 fader box with the code below but I would like CC numbers to be such that they can be changed by the user with a web ui or something similar.

Any help would be gratefully received.

Thanks Nick


#include <Bounce.h>

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


// 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 pins and cc codes
const int A_PINS = 3;
const int ANALOG_PINS[A_PINS] = {A1, A2, A3};
const int CCID[A_PINS] = {11, 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[0],true},
{ANALOG_PINS[1],true},
{ANALOG_PINS[2],true},
///////////////////////////////////////////////////////////////////////////
};

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

void loop(){
// MIDI Controllers should discard incoming MIDI messages.
while (usbMIDI.read()) {
// read & ignore incoming messages
}
// update the ResponsiveAnalogRead object every loop
for (int i=0;i<A_PINS;i++){
analog.update();
// if the repsonsive value has change, print out 'changed'
if(analog.hasChanged()) {
data = analog.getValue()>>3;
if (data != dataLag){
dataLag = data;
usbMIDI.sendControlChange(CCID, data, 1);
}
}
}
}





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
 
I've added some code which allows the CC number to be changed by using the serial monitor to enter the index of the CC to be changed and the CC number - e.g. 0 17
It's not exactly a web UI but it shows the basics of what's required to change an entry in the array (including removing 'const' from the array declaration).
The code compiles for a T3.2 but is untested.

Code:
#include <Bounce.h>

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


// 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 pins and cc codes
const int A_PINS = 3;
const int ANALOG_PINS[A_PINS] = {A1, A2, A3};
//>>> Removed const
int CCID[A_PINS] = {11, 1, 21};
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//>>>
// declarations for string input from the serial monitor
#define MAX_BUF 128
char inbuf[MAX_BUF];
// Index of next character to be stored in inbuf
char b_idx = 0;
// separators for strtok
char sep[] = " ,";
// token from strtok
char *token;
///////////////////////////////////////////////////////////////////////////

// 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[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
///////////////////////////////////////////////////////////////////////////
};

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

void loop()
{
// MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {
// read & ignore incoming messages
  }
// 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[i], data[i], 1);
      }
    }
  }
///////////////////////////////////////////////////////////////////////////
//>>>
// Handle input from serial monitor
  while(Serial.available() > 0) {
    char c;
    c = Serial.read();
    if(c != '\n') {
      inbuf[b_idx++] = c;
      if(b_idx >= MAX_BUF) {
        // The line is WAY too long. Throw it away
        b_idx = 0;
        continue;
      }
      continue;
    }
    // We have a linefeed. Parse the command
    // The line should be just two numbers
    // (any more than that will be ignored).
    // The first number is the index of the CC
    // to be changed and therefore must be positive
    // and less than A_PINS
    // The second number is the new value of the
    // CC number and therefore the number must be
    // positive and less than 128.
    // replace the linefeed with NULL
    inbuf[--b_idx] = 0;
    // reset the index ready for the next line
    b_idx = 0;
    // Get the first number
    token = strtok(inbuf,sep);
    if(token == NULL) {
      Serial.printf("ERROR: Input string is empty\n");
      break;
    }
    int cc_idx = atoi(token);
    // Is it valid?
    if(cc_idx < 0 || cc_idx >= A_PINS) {
      Serial.printf("ERROR: Invalid CC index '%d'\n",cc_idx);
      break;
    }

    // Now get the CC number
    token = strtok(inbuf,sep);
    if(token == NULL) {
      Serial.printf("ERROR: Second number is missing\n");
      break;
    }
    int cc_num = atoi(token);
    // Is the CC number valid?
    if(cc_num < 0 || cc_num > 127) {
      Serial.printf("ERROR: Invalid CC number '%d'\n",cc_num);
      break;
    }
    // Store the new CC number
    CCID[cc_idx] = cc_num;
  }
///////////////////////////////////////////////////////////////////////////
}

Pete
 
Hello Pete

That is very generous of you to write that code for me.

The sort of GUI I had in mind was one like this which I think relies on sys ex commands.

faderbox gui.jpg

Can my sketch be modified to respond to commands from this Gui?

I've tried to attach the code from this HTML page.

Thanks again for your help.

Nick

I've added some code which allows the CC number to be changed by using the serial monitor to enter the index of the CC to be changed and the CC number - e.g. 0 17
It's not exactly a web UI but it shows the basics of what's required to change an entry in the array (including removing 'const' from the array declaration).
The code compiles for a T3.2 but is untested.

Code:
#include <Bounce.h>

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


// 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 pins and cc codes
const int A_PINS = 3;
const int ANALOG_PINS[A_PINS] = {A1, A2, A3};
//>>> Removed const
int CCID[A_PINS] = {11, 1, 21};
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//>>>
// declarations for string input from the serial monitor
#define MAX_BUF 128
char inbuf[MAX_BUF];
// Index of next character to be stored in inbuf
char b_idx = 0;
// separators for strtok
char sep[] = " ,";
// token from strtok
char *token;
///////////////////////////////////////////////////////////////////////////

// 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[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
///////////////////////////////////////////////////////////////////////////
};

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

void loop()
{
// MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {
// read & ignore incoming messages
  }
// 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[i], data[i], 1);
      }
    }
  }
///////////////////////////////////////////////////////////////////////////
//>>>
// Handle input from serial monitor
  while(Serial.available() > 0) {
    char c;
    c = Serial.read();
    if(c != '\n') {
      inbuf[b_idx++] = c;
      if(b_idx >= MAX_BUF) {
        // The line is WAY too long. Throw it away
        b_idx = 0;
        continue;
      }
      continue;
    }
    // We have a linefeed. Parse the command
    // The line should be just two numbers
    // (any more than that will be ignored).
    // The first number is the index of the CC
    // to be changed and therefore must be positive
    // and less than A_PINS
    // The second number is the new value of the
    // CC number and therefore the number must be
    // positive and less than 128.
    // replace the linefeed with NULL
    inbuf[--b_idx] = 0;
    // reset the index ready for the next line
    b_idx = 0;
    // Get the first number
    token = strtok(inbuf,sep);
    if(token == NULL) {
      Serial.printf("ERROR: Input string is empty\n");
      break;
    }
    int cc_idx = atoi(token);
    // Is it valid?
    if(cc_idx < 0 || cc_idx >= A_PINS) {
      Serial.printf("ERROR: Invalid CC index '%d'\n",cc_idx);
      break;
    }

    // Now get the CC number
    token = strtok(inbuf,sep);
    if(token == NULL) {
      Serial.printf("ERROR: Second number is missing\n");
      break;
    }
    int cc_num = atoi(token);
    // Is the CC number valid?
    if(cc_num < 0 || cc_num > 127) {
      Serial.printf("ERROR: Invalid CC number '%d'\n",cc_num);
      break;
    }
    // Store the new CC number
    CCID[cc_idx] = cc_num;
  }
///////////////////////////////////////////////////////////////////////////
}

Pete
 

Attachments

  • VS_Faderbox gui.txt
    20.5 KB · Views: 67
Sorry, I can't help with that. I've done practically nothing with Teensy related to interacting with a web page.

Pete
 
Hi Pete
I'm sorry I'm pretty clueless about this.

Using the code you kindly wrote for me can I write something in a terminal window and send it to the teensy? to change the CC settings.

Thanks Nick




Sorry, I can't help with that. I've done practically nothing with Teensy related to interacting with a web page.

Pete
 
Hi Pete
I'm sorry I'm pretty clueless about this.

Using the code you kindly wrote for me can I write something in a terminal window and send it to the teensy? to change the CC settings.

Thanks Nick

Looking at the code this:
Code:
// Handle input from serial monitor
  while(Serial.available() > 0) {

Will take Terminal or Serial Monitor input from the USB Serial port and act on it to change the values as indicated.
 
To expand a bit on what @defragster wrote: When that code is run, the USB port on the Teensy will appear as a COM port on the PC. You don't have to have the serial monitor on that COM port. A terminal emulator will work just as well as long as it is configured to add a linefeed at the end of each line. If you can write your web UI to talk to the COM port, it will work as well.

Pete
 
Status
Not open for further replies.
Back
Top