Changing Pot MIDI Channel by Bank Select

Hi Pieter,

is it possible to change my pot MIDI Channel according to the bank #? In my code, I have 1 pot only to change the parameter values and it's working on the 3 buttons but when I change banks, the buttons reflect the back change (MIDI Channel) but not the pot. Is it possible?

Thanks.

Code:

#include <Control_Surface.h>  // Include the Control Surface library

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};  // CC numbers 

// Define two buttons for bank selection
Bank<4> bank(1);

//*** PARTIAL SELECT***
//Bankable::CCButton partial_Sel[] {
//{bank, 4, {25, CHANNEL_1}},  // Button to select Bank 1
//{bank, 5, {26, CHANNEL_1}},  // Button to select Bank 2
//};

// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<4> selector {
    bank,       // Bank to manage
    {5, 4},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<4> function_Sel[] = {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

// Potentiometer on pin A0
CCPotentiometer potentiometer = {A0, {ccNumbers[0], CHANNEL_1}};  // Default to the first CC number

// Function to update the potentiometer's CC number
void updatePotCC(uint8_t ccNumber) {
    potentiometer.setAddress({ccNumber, CHANNEL_1});  // Update potentiometer CC using setAddress
}

void setup() {
    // Initialize Control Surface
    Control_Surface.begin();
}

void loop() {
    // Check if any of the latched function buttons are pressed
    for (int i = 0; i < 3; ++i) {
        if (function_Sel[i].getButtonState() == Button::Falling) {
            updatePotCC(ccNumbers[i]);  // Update the potentiometer based on the selected button
        }
    }

    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
}

I was able to fix my code and it worked for the first day but now banks 1 to 4 don't work! Any idea why?


#include <Control_Surface.h>  // Include the Control Surface library

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};  // CC numbers

// Define a bank with 4 options
Bank<5> bank(1);

// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<5> selector {
    bank,       // Bank to manage
    {5, 4},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};


// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<5> function_Sel[] = {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

// Pointer to active potentiometer (starts with first CC number)
Bankable::CCPotentiometer* activePot = nullptr;

void setup() {
    // Initialize Control Surface
    Control_Surface.begin();

    // Initialize the first potentiometer instance
    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[0]);
}

void loop() {
    // Get the current bank selection (zero-based, so add 1 for MIDI channel)
    const uint8_t midiChannel = bank.getSelection() + 1;

    // Check if any of the function buttons are pressed
    for (int i = 0; i < 3; ++i) {
        if (function_Sel[i].getButtonState() == Button::Falling) {
            // Delete previous potentiometer to avoid memory leaks
            delete activePot;

            // Create a new potentiometer instance dynamically
            switch (i) {
                case 0:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[0]);
                    break;
                case 1:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[1]);
                    break;
                case 2:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[2]);
                    break;
            }
        }
    }



    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
}

I have deleted your other cross-post @yyz999 .

Cross-posting is against the Arduino forum rules. The reason is that duplicate posts can waste the time of the people trying to help. Someone might spend a lot of time investigating and writing a detailed answer on one topic, without knowing that someone else already did the same in the other topic.

Repeated cross-posting can result in a suspension from the forum.

In the future, please only create one topic for each distinct subject matter. This is basic forum etiquette, as explained in the "How to get the best out of this forum" guide. It contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Hi there, I apologize, I really didn’t think of it.

Thanks.

1 Like

You might want to ask @PieterP about this.

Hi all, my new code worked for 2 days...however, the third 3 banks 1 to 4 are not registering. I didn't change anything. Could it be related to some cache issue or something?

This code is preliminary as I need close to 80 buttons all controlled by a single pot. On a side note, I wonder if the switch case method is appropriate seeing that I was unable to find how to dynamically set both the CC# and MIDI channel of the pot as per the selected parameter button and bank. The switch case is the only way I was able to make it work.

Here's my new code:

#include <Control_Surface.h>  // Include the Control Surface library

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};  // CC numbers

// Define a bank with 4 options
Bank<5> bank(1);

// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<5> selector {
    bank,       // Bank to manage
    {5, 4},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};


// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<5> function_Sel[] = {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

// Pointer to active potentiometer (starts with first CC number)
Bankable::CCPotentiometer* activePot = nullptr;

void setup() {
    // Initialize Control Surface
    Control_Surface.begin();

    // Initialize the first potentiometer instance
    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[0]);
}

void loop() {
    // Get the current bank selection (zero-based, so add 1 for MIDI channel)
    const uint8_t midiChannel = bank.getSelection() + 1;

    // Check if any of the function buttons are pressed
    for (int i = 0; i < 3; ++i) {
        if (function_Sel[i].getButtonState() == Button::Falling) {
            // Delete previous potentiometer to avoid memory leaks
            delete activePot;

            // Create a new potentiometer instance dynamically
            switch (i) {
                case 0:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[0]);
                    break;
                case 1:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[1]);
                    break;
                case 2:
                    activePot = new Bankable::CCPotentiometer({bank, BankType::CHANGE_CHANNEL}, A0, ccNumbers[2]);
                    break;
            }
        }
    }

    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
}

No that sounds like a hardware problem.
Something like a power supply related issue and your wiring of it.

That is we need to see a schematic of how things are wired up.

Is there a battery involved? That can cause problems if you don't take the right precautions.

Don't use new and delete (not just in this instance, they should generally not be used in high-level code).

Here's a simpler approach that sends the MIDI messages directly in the main loop:

#include <Control_Surface.h>

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};

// Define a bank with 5 options
Bank<5> bank(1);

// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<5> selector {
    bank,       // Bank to manage
    {5, 4},     // push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<5> functionSel[] {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

AH::FilteredAnalog<7> potentiometer {A0};
uint8_t ccPotentiometer = ccNumbers[0];

void setup() {
    Control_Surface.begin();
}

void loop() {
    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
    // Check if any of the function buttons are pressed
    for (int i = 0; i < 3; ++i)
        if (functionSel[i].getButtonState() == Button::Falling)
            ccPotentiometer = ccNumbers[i];
    // If value of the potentiometer changed, send this new value
    if (potentiometer.update()) {
        MIDIAddress addr{ccPotentiometer, Channel{bank.getSelection()}};
        Control_Surface.sendControlChange(addr, potentiometer.getValue());
    }
}

Hi Pieter,

Thanks for the help. I increase the banks to 12 and I uploaded to code and it's working. However, I still don't know why the first 4 banks aren't registering. When I select bank 1 nothing happens. Bank 2, 3, 4...nothing, but then bank 5 up to bank 12 are working. Any idea why?

So I modified my code to use the ManyButtonsSelector for 5 banks and the code compiles but only bank 5 on pin 7 works...I'm at a loss!

#include <Control_Surface.h>

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};

// Define a bank with 5 options
Bank<5> bank(1);

// Instantiate a Bank selector to control which one of the four Banks is active.
//IncrementDecrementSelector<12> selector {
//    bank,       // Bank to manage
//    {5, 4},     // push button pins (increment, decrement)
//    Wrap::Wrap, // Wrap around
//};


// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<5> functionSel[] {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

AH::FilteredAnalog<7> potentiometer {A0};
uint8_t ccPotentiometer = ccNumbers[0];

// Selector to select the active bank
ManyButtonsSelector<5> selector = {
 bank,
  {{4, 5, 6, 7, 8}}, // button pins
  };

void setup() {
    Control_Surface.begin();
}

void loop() {
    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
    // Check if any of the function buttons are pressed
    for (int i = 0; i < 3; ++i)
        if (functionSel[i].getButtonState() == Button::Falling)
            ccPotentiometer = ccNumbers[i];
    // If value of the potentiometer changed, send this new value
    if (potentiometer.update()) {
        MIDIAddress addr{ccPotentiometer, Channel{bank.getSelection()}};
        Control_Surface.sendControlChange(addr, potentiometer.getValue());
    }
}

Resolved. My breadboard had connections that were not working. So here's code now with 5 banks and LEDs. I will modify to 12 banks and upward of 80 buttons. Thank you all.

#include <Control_Surface.h>

// Initialize USB MIDI interface
USBMIDI_Interface midi;

// Define CC numbers for the parameters
const uint8_t ccNumbers[] = {22, 23, 24};

// Define a bank with 5 options
Bank<5> bank(1);

// Instantiate a Bank selector to control which one of the four Banks is active.
//IncrementDecrementSelector<12> selector {
//    bank,       // Bank to manage
//    {5, 4},     // push button pins (increment, decrement)
//    Wrap::Wrap, // Wrap around
//};


// Define three buttons to select CC functions (latched)
Bankable::CCButtonLatched<5> functionSel[] {
    {{bank, BankType::CHANGE_CHANNEL}, 3, {ccNumbers[0], CHANNEL_1}},  // Button on pin 3 for CC 22
    {{bank, BankType::CHANGE_CHANNEL}, 2, {ccNumbers[1], CHANNEL_1}},  // Button on pin 2 for CC 23 
    {{bank, BankType::CHANGE_CHANNEL}, 1, {ccNumbers[2], CHANNEL_1}}   // Button on pin 1 for CC 24 
};

pin_t leds1 [] {
15, 16, 17, 18, 19 
};

AH::FilteredAnalog<7> potentiometer {A0};
uint8_t ccPotentiometer = ccNumbers[0];

// Selector to select the active bank
ManyButtonsSelectorLEDs<5> selector = {
 bank,
  {{4, 5, 6, 7, 8}}, // button pins
  {{15, 16, 17, 18, 19 }}, // LED pins
  };

void setup() {
    Control_Surface.begin();
    pinMode(leds1, INPUT);
}

void loop() {
    // Process Control Surface (sends MIDI messages)
    Control_Surface.loop();
    // Check if any of the function buttons are pressed
    for (int i = 0; i < 3; ++i)
        if (functionSel[i].getButtonState() == Button::Falling)
            ccPotentiometer = ccNumbers[i];
    // If value of the potentiometer changed, send this new value
    if (potentiometer.update()) {
        MIDIAddress addr{ccPotentiometer, Channel{bank.getSelection()}};
        Control_Surface.sendControlChange(addr, potentiometer.getValue());
    }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.