Use a single knob for mutli variables?

Hi all…

I have been designing a small synth with the Dsp g1 synth chip with the arduino. I need to keep hardware UI small and so keep buttons and knobs to a minimum.

I have set up a sketch to control the midi cc via potnetiometers and there are 16 midi cc to control in total.

Rather than use 16 pots to control everything i was hoping it might be possible to setup just 4 potentiometers and switch between the midi cc…

for example…

if pots 1-4 are set to midi cc 77, 70, 79, 71 then at the touch of a button the pots set to different group of 4 midi cc…

This way i can use just 4 Pots to control all 16 Parameters of the synth…

Could someone give me some help or pointers on how i might implements a way to switch the 4 pots to different midi controllers… i have included my sketch that uses 4 knobs set to control 4 different midi cc’s

im new to programming in the arduino and programming in general so im sorry for my ignorance if this is a trivial task…

thanks in advance.

nathan

  /*
 * edited from roguescience sketch
 * 
 *
 * digital pin 11 (OUTPUT/PWM) --> LED
 * digital pin 2 (INPUT) <-- button
 * analog pin 0 <-- pot
 * tx1 <-- pin 5 (5 PIN DIN aka MIDI jack)
 *
 * Send a MIDI note when the button is pressed and sends MIDI
 * CC data when a potentiometer is turned.
 */

int ledPin = 11;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int ledPin2 = 10;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int ledPin3 = 9;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int ledPin4 = 6;                //choose the pin for the LED - needs to be (3,5,6,9,10, or 11)
int buttonPin = 2;               //choose the input pin for a pushbutton

int potPin = 0;                  //choose the input pin for a potentometer
int potPin2 = 1;                  //choose the input pin for a potentometer 2 filter
int potPin3 = 2;                  //choose the input pin for a potentometer 3 
int potPin4 = 3;                  //choose the input pin for a potentometer 4 




int buttonVal = 0;                    //variable for reading the button status
int buttonState = 0;            //variable to hold the buttons current state
int bounceCheck = 0;            //variable for debouncing

int potVal = 0;                //variable for reading potentiometer value
int potVal2 = 0;                //variable for reading potentiometer 2 filter value
int potVal3 = 0;                //variable for reading potentiometer 3 value
int potVal4 = 0;                //variable for reading potentiometer 3 value

int mappedPotVal = 0;          //variable for holding remapped pot filter value
int mappedPotVal2 = 0;          //variable for holding remapped pot 2 filter value
int mappedPotVal3 = 0;          //variable for holding remapped pot 3 value
int mappedPotVal4 = 0;          //variable for holding remapped pot 3 value



int prevPotVal = 0;               //variable for storing our prev pot value
int prevPotVal2 = 0;               //variable for storing our prev pot value
int prevPotVal3 = 0;               //variable for storing our prev pot value
int prevPotVal4 = 0;               //variable for storing our prev pot value   LAST PHYSICAL POT


int THRESHOLD = 2;            //threshold amount



void setup() {
  pinMode(ledPin, OUTPUT);          //declare LED as output
   pinMode(ledPin2, OUTPUT);           //declare LED as output
   pinMode(ledPin3, OUTPUT);              //declare LED as output
    pinMode(ledPin4, OUTPUT);                 //declare LED as output
  pinMode(buttonPin, INPUT);                         //declare pushbutton as input
  Serial.begin(31250);              //MIDI communicates at 31250 baud
}

void loop(){

  buttonVal = digitalRead(buttonPin);     //read input value from button
  delay(10);                                 //wait 10ms
  bounceCheck = digitalRead(buttonPin);         //check again
  if(buttonVal == bounceCheck){           //if val is the same then not a bounce
    if (buttonVal == HIGH && buttonState == 1) {   //check if the input is HIGH
      digitalWrite(ledPin, LOW);                       //turn LED OFF
      midiOUT(0x90, 1, 0); //Note ON (CH 1), middle C, zero velocity turns note off
      buttonState = 0;
    }
    if(buttonVal == LOW && buttonState == 0){
      digitalWrite(ledPin, HIGH);       //turn LED ON
      midiOUT(0x90, 1, 127); //Note ON (CH 1), middle C, velocity 127
      buttonState = 1;
    }

  }

   potVal = analogRead(potPin);         //read input from potentiometer
   mappedPotVal = map(potVal, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal - prevPotVal) >= THRESHOLD){
     midiOUT(0xB0, 7, mappedPotVal); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin, HIGH);
     prevPotVal = mappedPotVal;
   }
   else{
      digitalWrite(ledPin, LOW);
   }
   
   
potVal2 = analogRead(potPin2);         //read input from potentiometer
   mappedPotVal2 = map(potVal2, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal2 - prevPotVal2) >= THRESHOLD){
     midiOUT(0xB0, 74, mappedPotVal2); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin2, HIGH);
     prevPotVal2 = mappedPotVal2;
   }
   else{
      digitalWrite(ledPin2, LOW);
   }


potVal3 = analogRead(potPin3);         //read input from potentiometer
   mappedPotVal3 = map(potVal3, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal3 - prevPotVal3) >= THRESHOLD){
     midiOUT(0xB0, 71, mappedPotVal3); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin3, HIGH);
     prevPotVal3 = mappedPotVal3;
   }
   else{
      digitalWrite(ledPin3, LOW);
   }
   
   
potVal4 = analogRead(potPin4);         //read input from potentiometer
   mappedPotVal4 = map(potVal4, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal4 - prevPotVal4) >= THRESHOLD){
     midiOUT(0xB0, 0x4C, mappedPotVal4); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin4, HIGH);
     prevPotVal4 = mappedPotVal4;
   }
   else{
      digitalWrite(ledPin4, LOW);
   }
 
}

void midiOUT(char command, char value1, char value2) {
  Serial.write(command);
  Serial.write(value1);
  Serial.write(value2);

}

Could someone give me some help or pointers on how i might implements a way to switch the 4 pots to different midi controllers.

The potentiometers are not connected to controllers. The DATA from the pots is sent to different controllers.

What, specifically, is going to switch which controller the data is sent to?

I know little or nothing about MIDI but it looks like something in lines like these

      midiOUT(0x90, 1, 0); //Note ON (CH 1), middle C, zero velocity turns note off

set the controller, note, etc If that is the case then it is these commands that need to be changed.

if pots 1-4 are set to midi cc 77, 70, 79, 71 then at the touch of a button the pots set to different group of 4 midi cc...

What is it that sets the MIDI cc to those values ? Can you not just adjust it when a button is pressed ?

Sorry for bad explanation.. yes the knobs are sending out the cc data..etc...

i want to use a button to change the 4 knobs to switch what cc data they send. i want to change all 4 at a time.. so button 1 might set the knobs to be

attack, decay, sustain, release (ie,4 midi cc's) then after pressing button 2 they might chnage to control
filter cut, filter res, f env att, f env dec (ie 4 different midi cc)

etc, etc

i understand about midi etc.. i have the the list of midi controllers and their hex values etc..

i just need a way to switch what midi cc the knobs send.. all 4 at the same time..

As I said, can't you just read an input and change the values that are sent ? Make the values a variable instead of fixed values to make it easier.

Which part of reading the input and changing the values are you stuck on ?

All of it?? lol

im not sure how to make the potvalue a variable in this case and they all need to e switched together… all 4 at the same time… also how do i choose what the variables will change to??

i know its simple… but not with my enrty level noobness.

ive only just learning programming over the last couple of weeks…

I need something like..

not real code

if button 1 is pressed then

knob1, knob2, knob3, knob4 = midi cc's (0xb0, 0x49, knob 1),(0xb0, 0x50, knob 2),(0xb0, 0x51, knob3)(0xb0, 0x59, knob 4)

if button 2 is pressed then

knob1, knob2, knob3, knob4 = midi cc's (new vlaue knob 1), (new vlaue knob 2), (new vlaue knob 3), (new vlaue knob 4)

etc etc (dont worry about the hex values they are just crude examples).

how do i implement such a thing???

how do i implement such a thing???

The best way would probably be to have an array of values and use the button pressed to determine the index to it. However, I am still not clear as to what should change between one button being pressed and another. Can you provide some real examples of what knob 1 should do when each of the 4 buttons is pressed ?

Does something change in lines like this, for instance ?
midiOUT(0x90, 1, 0);What do the 3 parameters mean ?

well the whole number is the midi data… the first is chan no. second is note no. third is velocity in this case its just hex format or dat format… similar to binary.

if it had (0xB0, 74, mapped pot val 2)

the first bit means its a cc value on channel 1, 2nd is the cc no 74 filter cutoff 3rd is the value and in this case from the pot …

maybe the answer to my question is staring me in the face now im thinking about it…

So which one(s) do you want to change by pressing a button ?
Suppose the command is

midiOUT(0x90, 1, 0);

with no button pressed, then what should it be when the button is pressed ?

When reading the switch (buttons are for shirts), follow the state change detection example, to determine when the switch BECOMES pressed, not IS pressed, and only increment the counter/index when the state changes.

I was saving that until I understood what exactly needs to change !

Here’s a quick example of using a button* to switch modes. This is based on the Arduino Debounce example and doesn’t have any actual MIDI code in it. But it should be obvious how this defines a set of modes and then does different things depending on which mode it’s in.

Notice also how the loop() function is very small - it calls other functions to do the real work.

/*
 MIDI Mode demo, with debouncing

 The circuit:
 * pushbutton attached from pin 2 to ground

 */

//mode list - change this as you see fit
enum modes {MUSIC_SPEED, MUSIC_LOUDNESS, MUSIC_OFF };
modes mode; //the current mode must be stored in a global variable

const int buttonPin = 2;    // the number of the pushbutton pin
const unsigned long debounceDelay = 50;    // the debounce time milliseconds; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);

  // set initial mode
  mode = MUSIC_OFF;
}

void loop() {
  readButtons();
  readPots();
  midiOut();
  displayMode();
}

void readButtons() {
  //read the button(s) in and change modes accordingly
  //currently this example only shows one button
  
  //store some static variables that we need to remember over the long term
  static bool lastButtonState = LOW;   // the previous reading from the input pin
  static bool buttonState = HIGH;     // the current state of the button
  static unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

  // read the state of the switch into a local variable:
  bool reading = digitalRead(buttonPin);

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      //Only change mode if the new button state is LOW (pressed)
      //depending on which mode we are in, we may jump to a different one
      if (buttonState == LOW) {
        switch (mode) {
          case MUSIC_OFF:
            mode = MUSIC_SPEED;
            break;
          case MUSIC_SPEED:
            mode = MUSIC_LOUDNESS;
            break;
          case MUSIC_LOUDNESS:
            mode = MUSIC_OFF;
            break;
          default:
            //something random changed mode to an invalid value? Get it back on track.
            mode = MUSIC_OFF;
            break;
        }
      }
    }
  }

  // save the button reading
  lastButtonState = reading;
}

void readPots() {
  //read in the potentiometer values.
  //Depending on the mode, this will update different global variables
  switch (mode) {
    case MUSIC_OFF:
      //
      break;
    case MUSIC_SPEED:
      //
      break;
    case MUSIC_LOUDNESS:
      //
      break;
  }
}
  
void midiOut() {
  //produce the appropriate MIDI outputs.
  //This may just send all the global variables or it may switch different things depending on the mode
}

void displayMode() {
  //Turn on an LED or some other display method so the musician can see what mode it's in
}

*The shirt I’m wearing now has a zip - the button is on the breadboard.

UKHeliBob:
So which one(s) do you want to change by pressing a button ?
Suppose the command is

midiOUT(0x90, 1, 0);

with no button pressed, then what should it be when the button is pressed ?

just the middle number is needed to be changed.. but will need to be changed at the same for all 4 knobs

We are finally getting there.
Declare an array of values and an index to the array

byte values[] = {1, 2, 3, 4};
byte index = 0;

The MIDI command will then look like this

midiOUT(0x90, values[index], 0);

When the button becomes pressed increment the index and the value of the middle parameter will change accordingly even though the MIDI command remains the same.

yes i see what you are doing there... althought im still struggling with how i apply it.

what does byte index 0 meean?? and how does the button increment using this or how do i tell the button to increment the value of the index???

im sorry but i find code hard at the moment.. im sure in a few months or so things wont be so hard..

so do i apply it like this....

  byte midicc[] = {73, 74, 01, 4};
     byte index = 0;
   potVal = analogRead(potPin);         //read input from potentiometer
   mappedPotVal = map(potVal, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal - prevPotVal) >= THRESHOLD){
     midiOUT(0xB0, midicc[index], mappedPotVal); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin, HIGH);
     prevPotVal = mappedPotVal;
   }
   else{
      digitalWrite(ledPin, LOW);
   }
   
   byte midicc2[] = {80, 16, 52, 83};
    byte index2 = 0;
  potVal2 = analogRead(potPin2);         //read input from potentiometer
   mappedPotVal2 = map(potVal2, 0, 1023, 0, 127);  //map value to 0-127
   if(abs(mappedPotVal2 - prevPotVal2) >= THRESHOLD){
     midiOUT(0xB0, midicc2[index2], mappedPotVal2); //Control Change (Ch 1), Controller 7 - default control for volume.
     digitalWrite(ledPin2, HIGH);
     prevPotVal2 = mappedPotVal2;
   }
   else{
      digitalWrite(ledPin2, LOW);
   }

could it be that easy?? i hope so?? i now got to apply the buton to increment the index?

*The shirt I'm wearing now has a zip - the button is on the breadboard.

Sewn on with conductive thread, I hope.

That depends if you can help me increment the value with a switch the??