Control surface CD74HC4067 digital buttons

Hello.
I am trying to build a midi foot-switch with several potentiometers and digital buttons with two CD74HC4067 multiplexer on arduino uno (original).

I was using midi.h library..but now i am confused on this new library control surface.

When i am trying to add one multiplexer and one potentiometer..then compile..arduino uno its 66%full global vars.
I cant add one more multiplexer..

Can someone help me please.
Here early stages on my midi footswitch

Each individual object in Control Surface takes up some extra RAM to support things like automatic initialization and updating. When you instantiate 32 or more buttons, this overhead adds up, and this is especially noticeable on an Arduino Uno, which has the least amount of memory of all Arduino boards.

If you want to use many buttons, the trick is to create a single object that reads all 32 buttons instead of 32 separate objects that read one button each.

I imagine your code looking something like this:

CD74HC4067 mux1 {
  A0,          // Analog input pin
  {3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CD74HC4067 mux2 {
  A1,          // Analog input pin
  {3, 4, 5, 6} // Address pins S0, S1, S2, S3
};

CCButton buttons[] {
  {mux1.pin(0), 0},
  {mux1.pin(1), 1},
  {mux1.pin(2), 2},
  {mux1.pin(3), 3},
  {mux1.pin(4), 4},
  {mux1.pin(5), 5},
  {mux1.pin(6), 6},
  {mux1.pin(7), 7},
  {mux1.pin(8), 8},
  {mux1.pin(9), 9},
  {mux1.pin(10), 10},
  {mux1.pin(11), 11},
  {mux1.pin(12), 12},
  {mux1.pin(13), 13},
  {mux1.pin(14), 14},
  {mux1.pin(15), 15},
  {mux2.pin(0), 16 + 0},
  {mux2.pin(1), 16 + 1},
  {mux2.pin(2), 16 + 2},
  {mux2.pin(3), 16 + 3},
  {mux2.pin(4), 16 + 4},
  {mux2.pin(5), 16 + 5},
  {mux2.pin(6), 16 + 6},
  {mux2.pin(7), 16 + 7},
  {mux2.pin(8), 16 + 8},
  {mux2.pin(9), 16 + 9},
  {mux2.pin(10), 16 + 10},
  {mux2.pin(11), 16 + 11},
  {mux2.pin(12), 16 + 12},
  {mux2.pin(13), 16 + 13},
  {mux2.pin(14), 16 + 14},
  {mux2.pin(15), 16 + 15},
};

Try replacing it with:

// Instantiate a multiplexer
CD74HC4067 mux1 {
  A0,          // Analog input pin
  {3, 4, 5, 6} // Address pins S0, S1, S2, S3
};
CD74HC4067 mux2 {
  A1,          // Analog input pin
  {3, 4, 5, 6} // Address pins S0, S1, S2, S3
};

CCButtons<32> buttons {
  copyAs<Button>(cat(mux1.pins(), mux2.pins())), {0, CHANNEL_1}, {1, 0},
};

The cat function concatenates the arrays of pins of the two multiplexers into one array of 32 pins, and the copyAs<Button> function converts this array of pins into an array of buttons, which is what the CCButtons constructor expects.

This change should save around 17% of RAM.

You can also try disabling functionality you don’t need, such as MIDI SysEx input support or being able to invert individual buttons.
I’ve just added a short FAQ entry about it: Control Surface: Frequently Asked Questions

While it’s possible to optimize the memory usage even further, the best solution is usually to upgrade to an Arduino board with more memory. The Arduino Uno is simply not a good choice to build MIDI controllers, it lacks things like USB MIDI support and its 2KiB of RAM is simply not enough for many bigger projects.
Arduino has modern ARM-based boards that are both cheaper than the Uno and have much better features (plenty of RAM, a 32-bit CPU, USB support, faster IO, etc.).

Control Surface will continue to support the Arduino Uno for the foreseeable future (simply because of its popularity), but optimizing the memory usage to be able to add multiple multiplexers and many inputs on an Uno is not a priority, it’s much easier to just get a more suitable board, such as an ARM-based Arduino or a Teensy.

Pieter

Thanks…
My problem was adding analog multiplexer and digital multiplexer…two multiplexers total.

Adding 10 buttons…cc or note signal for example…and adding 16 potentiometers cc
The arduino gets 88%ram (global vars).

I have got some arduino megas and i want to learn this library…your library midi.h was great…but now i know this one…the control surface seems to be perfect for build a midi footswitch…

So i am getting started with arduino mega and control surface library…i will post my advances thank you…

On my new code.(16 potentiometers and 10 buttons…all CC signals) only takes 20% ram arduino mega 2560. No multiplexers yet.

#include <Control_Surface.h>
USBMIDI_Interface midi;
CCPotentiometer potentiometer1 = { A0, {MIDI_CC::Channel_Volume, CHANNEL_1} };
CCPotentiometer potentiometer2 = { A1, {MIDI_CC::Channel_Volume, CHANNEL_2} };
CCPotentiometer potentiometer3 = { A2, {MIDI_CC::Channel_Volume, CHANNEL_3} };
CCPotentiometer potentiometer4 = { A3, {MIDI_CC::Channel_Volume, CHANNEL_4} };
CCPotentiometer potentiometer5 = { A4, {MIDI_CC::Channel_Volume, CHANNEL_5} };
CCPotentiometer potentiometer6 = { A5, {MIDI_CC::Channel_Volume, CHANNEL_6} };
CCPotentiometer potentiometer7 = { A6, {MIDI_CC::Channel_Volume, CHANNEL_7} };
CCPotentiometer potentiometer8 = { A7, {MIDI_CC::Channel_Volume, CHANNEL_8} };
CCPotentiometer potentiometer9 = { A8, {MIDI_CC::Channel_Volume, CHANNEL_9} };
CCPotentiometer potentiometer10 = { A9, {MIDI_CC::Channel_Volume, CHANNEL_10} };
CCPotentiometer potentiometer11 = { A10, {MIDI_CC::Channel_Volume, CHANNEL_11} };
CCPotentiometer potentiometer12 = { A11, {MIDI_CC::Channel_Volume, CHANNEL_12} };
CCPotentiometer potentiometer13 = { A12, {MIDI_CC::Channel_Volume, CHANNEL_13} };
CCPotentiometer potentiometer14 = { A13, {MIDI_CC::Channel_Volume, CHANNEL_14} };
CCPotentiometer potentiometer15 = { A14, {MIDI_CC::Channel_Volume, CHANNEL_15} };
CCPotentiometer potentiometer16 = { A15, {MIDI_CC::Channel_Volume, CHANNEL_16} };

CCButton button = { 5, {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}, };    
CCButton button2 = { 6, {MIDI_CC::General_Purpose_Controller_2, CHANNEL_2}, }; 
CCButton button3 = { 7, {MIDI_CC::General_Purpose_Controller_3, CHANNEL_3}, };   
CCButton button4 = { 8, {MIDI_CC::General_Purpose_Controller_4, CHANNEL_4}, };
CCButton button5 = { 9, {MIDI_CC::General_Purpose_Controller_5, CHANNEL_5}, };   
CCButton button6 = { 10, {MIDI_CC::General_Purpose_Controller_6, CHANNEL_6}, }; 
CCButton button7 = { 21, {MIDI_CC::General_Purpose_Controller_7, CHANNEL_7}, };    
CCButton button8 = { 22, {MIDI_CC::General_Purpose_Controller_8, CHANNEL_8}, };
CCButton button9 = { 23, {MIDI_CC::General_Purpose_Controller_8, CHANNEL_9}, };    
CCButton button10 = { 24, {MIDI_CC::General_Purpose_Controller_2, CHANNEL_10}, };


void setup() {
  // put your setup code here, to run once:
 Control_Surface.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
Control_Surface.loop();
}

Hello!

Imagine this config for one pedal on amplitube or guitar rig


How Could i build one “CC change button” for change CC on this three pots and two buttons?
For example:
I press the button and now the pots are changing CC…now the pots are : 70 , 71 and 72 respectively (before pressing the button the pots was 67, 68 and 69).
And the same for the buttons…before pressing the “CC change button” was 65 and 66…and now i press the button and the buttons change to 70 and 71.

I am trying to understand how could i use your library and use the info,

I see one example on arduino about changing channel with rotary encoder…
and i have tried to modified no success…

Do you think it´s mad using midi.h controller.h and controlsurface.h …all libraries in the same sketch?? (
I am on early stages right now but i think its the best option for me… this works well for me at this moment…

#include <MIDI.h>

#include "Controller.h"

MIDI_CREATE_DEFAULT_INSTANCE();

byte NUMBER_BUTTONS = 2;

byte NUMBER_POTS = 0;

byte NUMBER_MUX_BUTTONS = 0;

byte NUMBER_MUX_POTS = 0;

Button BU5(5, 2, 66, 1, 5 );    
Button BU6(6, 2, 67, 1, 5 );
Button *BUTTONS[] {&BU5, &BU6};
Pot *POTS[] {};
Button *MUXBUTTONS[] {};
Pot *MUXPOTS[] {};

#include <Control_Surface.h>

USBMIDI_Interface usbmidi;

const int speedMultiplier = 1;

Bank<2> bank(4); // A bank with four channels, and 2 bank settings

Bankable::CCPotentiometer faders[] = {
  {{bank, BankType::CHANGE_CHANNEL}, A0, {67, CHANNEL_1}},
  {{bank, BankType::CHANGE_CHANNEL}, A1, {68, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL}, A2, {69, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL}, A3, {MIDI_CC::Channel_Volume, CHANNEL_4}},
};
CCPotentiometer knobsTop[] = {
  {A4, 70},
  {A5, 71},
  {A6, MIDI_CC::General_Purpose_Controller_3},
  {A7, MIDI_CC::General_Purpose_Controller_4},
};
Bankable::CCPotentiometer knobsSide[] = {
  {{bank, BankType::CHANGE_CHANNEL}, A8, {MIDI_CC::Pan, CHANNEL_1}},
  {{bank, BankType::CHANGE_CHANNEL}, A9, {MIDI_CC::Pan, CHANNEL_2}},
  {{bank, BankType::CHANGE_CHANNEL}, A10, {MIDI_CC::Pan, CHANNEL_3}},
  {{bank, BankType::CHANGE_CHANNEL}, A11, {MIDI_CC::Pan, CHANNEL_4}},
};
Bankable::NoteButtonLatching switches[] = {
  {{bank, BankType::CHANGE_ADDRESS}, 10, MCU::MUTE_1},
  {{bank, BankType::CHANGE_ADDRESS}, 9, MCU::MUTE_2},
  {{bank, BankType::CHANGE_ADDRESS}, 8, MCU::MUTE_3},
  {{bank, BankType::CHANGE_ADDRESS}, 7, MCU::MUTE_4},
};
CCPotentiometer enc = { A1, {MIDI_CC::Channel_Volume, CHANNEL_2} };
SwitchSelector selector = {bank, 11};
void setup() {
  Control_Surface.begin();
  pinMode(LED_BUILTIN, OUTPUT);
   MIDI.begin(MIDI_CHANNEL_OFF);
}
void loop() { 
  Control_Surface.loop();
  digitalWrite(LED_BUILTIN, digitalRead(13));
  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_POTS != 0) updatePots();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
  if (NUMBER_MUX_POTS != 0) updateMuxPots();
}
//*****************************************************************
void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break; 
       
      }
      
    }

    //  Button is not pressed
    if (message == 1) {
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
          
      }
    }
 
  }
}

//*******************************************************************
void updateMuxButtons() {

  // Cycle through Mux Button array
  for (int i = 0; i < NUMBER_MUX_BUTTONS; i = i + 1) {

    MUXBUTTONS[i]->muxUpdate();
    byte message = MUXBUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (MUXBUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 1;
          }
          else if (MUXBUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 0;
          }
          break;
         
      }
    }
    //  Button is not pressed
    if (message == 1) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
          
      }
    }
  }
}
//***********************************************************************
void updatePots() {
  for (int i = 0; i < NUMBER_POTS; i = i + 1) {
    byte potmessage = POTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(POTS[i]->Pcontrol, potmessage, POTS[i]->Pchannel);
  }
}
//***********************************************************************
void updateMuxPots() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(MUXPOTS[i]->Pcontrol, potmessage, MUXPOTS[i]->Pchannel);
  }
}

I have got two more tabs…controller.cpp and controller.h (i don´t understand absolutely nothing about this tabs and the library controller.h)and i think it´s useless because no multiplexers are connected right no,but i think this weird thing works well for me by now :frowning:
Its my best option right now
Hope i will find out and understand more things on controlsurface.h library
Thanks!!

chichiforever:
How Could i build one “CC change button” for change CC on this three pots and two buttons?
For example:
I press the button and now the pots are changing CC…now the pots are : 70 , 71 and 72 respectively (before pressing the button the pots was 67, 68 and 69).

This is done through banks. You want to have two possible settings, so you would create two banks. The offset between the addresses of the two banks is three (70 - 67 = 3), so you would use:

Bank<2> bank {3};

Then you create three bankable potentiometers and make their addresses depend on the bank you’ve just created:

Bankable::CCPotentiometer pots[] {
  {bank, A0, 67},
  {bank, A1, 68},
  {bank, A2, 69},
};

If the first bank is selected, these potentiometers send messages on their base addresses [67, 68, 69]. When the second bank is selected, an offset of 3 is added (this was the argument you used when creating the bank), so the addresses of the potentiometers become [70, 71, 72].
Then you need something to control which bank is active, this is usually done using a Selector. If you want to use a toggle switch to control the banks, use a SwitchSelector, if you want to use a momentary push button, use an IncrementSelector<2>.

chichiforever:
Do you think it´s mad using midi.h controller.h and controlsurface.h …all libraries in the same sketch?? (
I am on early stages right now but i think its the best option for me… this works well for me at this moment…

I wouldn’t recommend it, they might interfere in unexpected ways.
It looks like you’re only using two buttons of the Controller.h library. If I understand the code and comments correctly, these can very easily be replaced by the following Control Surface equivalent:

CCButtonLatched buttons[] {
  {5, 66},
  {6, 67},
};

Control Surface doesn’t care what kind of pins you use, you don’t have to do anything special to make this work with a multiplexer, for example, simply replace the pins:

CCButtonLatched buttons[] {
  {mux.pin(0), 66},
  {mux.pin(1), 67},
};

In general:

  • Buttons and Mux Buttons with option 0 can be replaced by Control Surface’s NoteButton class,
  • Buttons and Mux Buttons with option 1 can be replaced by Control Surface’s CCButton class,
  • Buttons and Mux Buttons with option 2 can be replaced by Control Surface’s CCButtonLatched class,
  • Pots and Mux Pots can be replaced by Control Surface’s CCPotentiometer class.

Perfect,thank you Pieter..

The principal reason i was using the midi.h library was the toggle buttons.

Toggle buttons allows you to switch on or off pedals ,correctly on DAWs ...
Normal buttons on MIDI are like sending two signal when you press one time the button..
Toggle buttons only send one signal and it works perfect to switch on or off the pedal..

Now you have explained me..i don´t want and i don´t need midi.h library.

The next reason (controller.h library with controller.cpp and controller.h tabs on the sketch) its about potentiometers..

There must be a reason i don´t know why potentiometers doesnt works so perfect as they did on midi.h library..
Let me explain you..potentiometers doesnt works perfect...especially when you are reaching both sides of potentiometer (end and start) it´s like a little bit disfunctioning...
On midi.h potentiometers are working sooo perfect...

anyway..i see one example on arduino ide called "CCPotentiometer map" (it´s under control surface library)
i must try this sketch on every single one potentiometer..i think and i hope this will solve my potentiometer problems.

Thanks for your reply..thanks a lot

chichiforever:
The next reason (controller.h library with controller.cpp and controller.h tabs on the sketch) its about potentiometers..

There must be a reason i don´t know why potentiometers doesnt works so perfect as they did on midi.h library..
Let me explain you..potentiometers doesnt works perfect...especially when you are reaching both sides of potentiometer (end and start) it´s like a little bit disfunctioning...
On midi.h potentiometers are working sooo perfect...

I've done some tests comparing the Controller.h potentiometer performance with Control Surface and I'm unable to reproduce this. In the absence of noise, they both perform almost identically, in the presence of noise, Control Surface outperforms the Controller.h code.

The red line is Controller.h, the blue line is Control Surface. As you can see, Control Surface does a better job of filtering out the noise. On the right side of the graph, the potentiometer didn't move, but Controller.h still thought it was moving due to noise on the analog input.

If you have more noise than before, it's a good idea to check your hardware and wiring. Did you solder the potentiometers or are you using a breadboard and jumper wires? Jumper wires don't always give the best connections.

Yes that´s true i see the two lines on your graph they are almost the same…
Certainly… i was full of noise problems one week ago, and this it´s noticeable on midi.h and controller.h.
Theres so much more noise on midi.h and controller.h…this its absolutely true on my case…control surface works pretty well about the noise…

The noise comes on +5 volts and ground wires…you must be careful about this problem when you wire up.
But now for me works pretty well. no protoboards and i think i got correct wiring and soldering.
If you have noise problems you will see the ghost midi signals on your DAW…makes everything so much more complicated.

But my problem was moving potentiometers…i think there was more performed movement for the pots before…
moving the pot, when i reach the end … or moving to zero… i see strange things happens! i see this on the amplitube screen pot.

But i must try the control surface example solution…“the ccpotentiometer map”
this it´s my next step…now i am trying to solve my pot moves problem.

But otherwise i got one big problem trying to understand the library info
For example the selector…
do you think i must build a new tab and copy and paste the IncrementSelector.hpp from your website?
Of course i am very interested on increment selector but i don´t understand how to use it on a CCButtonLatched or a CCButton.

No need to confess i am reading arduino programming books (level one :confused:) but sometimes i find my self watching info and i don´t know where its my start point :slight_smile:
Code Day 2

#include <Control_Surface.h>  //Program--include library-- then select "control surface" library..Vamos a programar el codigo con la librería Control Surface
USBMIDI_Interface usbmidi;    //initializes device as usb_midi interface...see other examples like hardwareserial,hairles etc

Bank<2> bank(3); // A bank with three channels, and 2 bank settings..creamos dos bancos con dos ajustes distintos..el intervalo de cambio entre los valores sera de +-3



CCPotentiometer potentiometer6 = { A5, {42, CHANNEL_6} };
CCPotentiometer potentiometer7 = { A6, {43, CHANNEL_7} };
CCPotentiometer potentiometer8 = { A7, {44, CHANNEL_8} };
CCPotentiometer potentiometer9 = { A8, {45, CHANNEL_9} };
CCPotentiometer potentiometer10 = { A9, {46, CHANNEL_10} };
CCPotentiometer potentiometer11 = { A10, {47, CHANNEL_11} };
CCPotentiometer potentiometer12 = { A11, {48, CHANNEL_12} };
CCPotentiometer potentiometer13 = { A12, {49, CHANNEL_13} };
CCPotentiometer potentiometer14 = { A13, {50, CHANNEL_14} };
CCPotentiometer potentiometer15 = { A14, {51, CHANNEL_15} };
CCPotentiometer potentiometer16 = { A15, {MIDI_CC::Channel_Volume, CHANNEL_16} };

CCButtonLatched buttons[] {  
 {5, 90},
 {6, 91},   
};

CCButton button3 = { 7, {MIDI_CC::General_Purpose_Controller_3, CHANNEL_3}, };   
CCButton button4 = { 8, {MIDI_CC::General_Purpose_Controller_4, CHANNEL_4}, };
CCButton button5 = { 9, {MIDI_CC::General_Purpose_Controller_5, CHANNEL_5}, };   
CCButton button6 = { 10, {MIDI_CC::General_Purpose_Controller_6, CHANNEL_6}, }; 
CCButton button7 = { 21, {MIDI_CC::General_Purpose_Controller_7, CHANNEL_7}, };    
CCButton button8 = { 22, {MIDI_CC::General_Purpose_Controller_8, CHANNEL_8}, };

Bankable::CCPotentiometer pots[] = {
  
  {bank, A0, 67},
  {bank, A1, 68},
  {bank, A2, 69},
  };


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

Thanks Pieter :slightly_smiling_face:

chichiforever:
But my problem was moving potentiometers…i think there was more performed movement for the pots before…
moving the pot, when i reach the end … or moving to zero… i see strange things happens! i see this on the amplitube screen pot.

What kind of strange things? Neither Control Surface nor Controller.h does anything special near zero or near the end, so I can’t really explain that, and I’ve never noticed anything like that myself.

You could try the AnalogReadSerial example that comes with the Arduino IDE. Connect your potentiometer to pin A0 and open the serial plotter (or serial monitor) in the IDE. See if you get the same weird effects near the edges of the range. If so, then it’s almost definitely a hardware issue.

chichiforever:
But otherwise i got one big problem trying to understand the library info
For example the selector…
do you think i must build a new tab and copy and paste the IncrementSelector.hpp from your website?

No, the IncrementSelector.hpp file is already included with the library, don’t add it as a tab. All you have to do is include <Control_Surface.h>, and then you have access to the IncrementSelector class.

What you should do next is have to look at the constructor documentation to know how to construct an IncrementSelector object.
You can see that the first argument is the selectable, i.e. the thing that can be selected, the bank in this case. The second argument is a button. You can simply initialize the button by giving it the pin number that the button is connected to. The number between the angle brackets (< >) is the number of banks.
For example:

IncrementSelector<2> selector {
  bank,  // selectable
  2,     // button pin number
};

Of course i am very interested on increment selector but i don´t understand how to use it on a CCButtonLatched or a CCButton.

Do you understand the CCButton example?
It should be really easy to use, you just specify the button pin and the MIDI CC number. Control Surface handles everything else for you.
CCButtonLatched is almost exactly the same as CCButton, the only difference is that it latches the button presses to imitate a toggle switch.

CCButton button {
  5,  // Push button on pin number
  99, // MIDI controller number
};

The bankable variants (Bankable::CCButton and Bankable::CCButtonLatched) require an extra argument, which is the bank to add them to.

Bankable::CCButton button {
  bank,
  5,  // Push button on pin number
  99, // MIDI controller number
};

Bankable::CCButtonLatched requires you to specify the number of banks (because it has to know how many toggled states to remember):

Bankable::CCButtonLatched<2> button {
  bank,
  5,  // Push button on pin number
  99, // MIDI controller number
};

If you’re having trouble with your code, I’d recommend simplifying it first. In the first testing phase, there’s no need to have multiple potentiometers and buttons, simply test a single button or a single potentiometer at a time.

My problem it´s understanding the code and how to use it..
Its awesome the analoginout serial arduino example .. but its hard to me understanding everything... but in this example i have learned a few things.ok thanks..
so i have looked the monitor serial and i can see the "outputvalue" variable constant from 0-255..
and the sensor (its the sensorValue variable constant number from analogread) brings me values from 0-1023 .
i think it´s ok when i move pot.

if i stop moving potentiometer maybe sometimes 0-1023 sensor values jump one number ..i.e 667 and 668 changes quickly but i think my hardware its ok..

I will hope to start to understand some things about coding..

Do you understand the CCButton example?
It should be really easy to use, you just specify the button pin and the MIDI CC number. Control Surface handles everything else for you.
CCButtonLatched is almost exactly the same as CCButton, the only difference is that it latches the button presses to imitate a toggle switch.

Yes this its a perfect example how easy its this library.. but if i change this

CCButton button = { 5, {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}, };

And select this data PIN5 for 71 CC on Channel or midicable 1

CCButton button = { 5, {71 , CHANNEL_1}, };

i don´t understand pretty well the general purpose controller number, i think doesnt care at all change this number , i think every potentiometer attached to the first instruction will be the same CC and everything..

Yep trying to figure out some things..thanks for your help.

I find it very difficult to understand your reply. What "outputvalue" are you talking about? “Variable constant” sounds like a contradictio in terminis.

MIDI_CC::General_Purpose_Controller_1 is simply a constant integer, there's no magic involved. There is no difference between writing CCButton button { 5, {16, CHANNEL_1} } and CCButton button { 5, {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1} }.
If you look at the documentation, you can see the definition of the constant:

constexpr uint8_t General_Purpose_Controller_1 = 0x10;

You'll have to get familiar with these concepts from a C++ tutorial, book or course, that's not something I can explain to you in a forum post.

Sorry i was trying to explain this sketch

// These constants won't change. They're used to give names to the pins used:
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to. Declarar una constante con numeros enteros llamada analogInPin y establecerla en el pin de entrada analogica A0
const int analogOutPin = 9; // Analog output pin that the LED is attached to. Declarar una constante que tiene numeros enteros llamada AnalogOutPin y establecerla en el pin 9 que es un pin de salida OUTPUT PWM

int sensorValue = 0;        // value read from the pot..establecemos el nombre "sensorValue" a todos los valores de numeros enteros que traera la constante "analogInPin" y establecemos el primer valor de esta constante como cero (el primer valor que tendra la constante del potenciometro en A0 sera cero)
int outputValue = 0;        // value output to the PWM (analog out)establecemos el nombre "outputValue" a todos los valores de numeros enteros que traera la constante "analogOutPin" y establecemos el primer valor de esta constante como cero (el primer valor que tendra la constante del led en PIN 9 sera cero)

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);  //la constante sensorValue será igual al valor (numeros enteros) que traiga analogRead en el pin A0  (analogInPin)..lee el potenciometro y devuelve el valor en numeros enteros a sensorValue
  // map it to the range of the analog out:  
  outputValue = map(sensorValue, 0, 1023, 0, 255);  //la constante outputValue será igual al valor (numeros enteros) que traiga sensorValue en (analogInPin) los valores seran entre 0-1023;0-255
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);  // devuelve el valor del potenciometro y lo escribe en el pin 9 y en outputValue

  // print the results to the Serial Monitor:
  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t output = ");
  Serial.println(outputValue);

  // wait 2 milliseconds before the next loop for the analog-to-digital
  // converter to settle after the last reading:
  delay(2);
}

On serial monitor screen i get the values 0 to 1023 on "sensorValue"
and 0 to 255 on "outputValue.

Ok thanks for your help i need some time

Thank you Pieter, i got everything working perfect…
this is my code

#include <Control_Surface.h>  //Program--include library-- then select "control surface" library..Vamos a programar el codigo con la librería Control Surface
USBMIDI_Interface usbmidi;    //initializes device as usb_midi interface...see other examples like hardwareserial,hairles etc

Bank<2> bank(3); // A bank with three channels, and 2 bank settings..creamos dos bancos con dos ajustes distintos..el intervalo de cambio entre los valores sera de +-3



CCPotentiometer potentiometer6 = { A4, {42, CHANNEL_6} };
CCPotentiometer potentiometer7 = { A5, {43, CHANNEL_7} };
CCPotentiometer potentiometer8 = { A6, {44, CHANNEL_8} };
CCPotentiometer potentiometer9 = { A7, {45, CHANNEL_9} };
CCPotentiometer potentiometer10 = { A8, {46, CHANNEL_10} };
CCPotentiometer potentiometer11 = { A9, {47, CHANNEL_11} };
CCPotentiometer potentiometer12 = { A10, {48, CHANNEL_12} };
CCPotentiometer potentiometer13 = { A11, {49, CHANNEL_13} };
CCPotentiometer potentiometer14 = { A12, {50, CHANNEL_14} };
CCPotentiometer potentiometer15 = { A13, {51, CHANNEL_15} };
CCPotentiometer potentiometer16 = { A14, {MIDI_CC::Channel_Volume, CHANNEL_16} };

CCButtonLatched buttons[] {  
 {5, 90},
 {6, 91},   
};

CCButton button3 = { 7, {30, CHANNEL_1}, };   
CCButton button4 = { 8, {31, CHANNEL_1}, };
CCButton button5 = { 9, {32, CHANNEL_1}, };   
CCButton button6 = { 10, {33, CHANNEL_1}, }; 
CCButton button7 = { 11, {MIDI_CC::General_Purpose_Controller_7, CHANNEL_1}, };    
CCButton button8 = { 12, {MIDI_CC::General_Purpose_Controller_8, CHANNEL_1}, };

Bankable::CCPotentiometer pots[] = {
  
  {bank, A0, 67},
  {bank, A1, 68},
  {bank, A2, 69},
  };
IncrementSelector<2> selector { bank, 2, };

Bankable::CCButtonLatched<2> button { bank, 2, 99, };

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

It´s incredible so easy… :o :o …thanks

Glad to hear you got it working!

One thing that looks odd to me is that you’re using the same pin for the bank selector and for a button that’s controlled by that bank selector:

IncrementSelector<2> selector { bank, 2, };
Bankable::CCButtonLatched<2> button { bank, 2, 99, };

I can’t really imagine that working correctly.

Yes Pieter…you are right…my past code not so perfect…
I was very happy about banks and changing pedals…and my code was the first step…

Let me put my new code…its perfect for changing pedals on DAWs.
You can control every pedal o the board with only four potentiometer and two buttons.
Buttons 7 and 8 are not MIDI and are use them for change pedal…
Now i want to add leds but it´s difficult to me…sorry about my english.
Thank you very much Pieter

#include <Control_Surface.h>
USBMIDI_Interface usbmidi;

Bank<6> bank(4); // A bank with three channels, and 6 bank settings..creamos 6 bancos con 6 ajustes posibles distintos con tres canales..el intervalo de cambio entre los valores sera de +-3, Cada vez que cambiemos de un banco a otro sumara o decrecera +-3 MIDI CC

#include <Adafruit_NeoPixel.h>
#include <avr/power.h>

//Designamos nuestro pin de datos
#define PIN 40
//Designamos cuantos pixeles tenemos en nuestra cinta led RGB
#define NUMPIXELS      6

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

CCPotentiometer potentiometer4 = { A4, {42, CHANNEL_6} };  //establecemos el pin analogico A4 para un potenciometro analogico 10k al que llamaremos potentiometer4..la salida analogica A4 mandara mensajes MIDI 42 CC en el canal 6
CCPotentiometer potentiometer5 = { A5, {43, CHANNEL_6} };
CCPotentiometer potentiometer6 = { A6, {44, CHANNEL_6} };
CCPotentiometer potentiometer7 = { A7, {45, CHANNEL_6} };
CCPotentiometer potentiometer8 = { A8, {46, CHANNEL_10} };
CCPotentiometer potentiometer9 = { A9, {47, CHANNEL_11} };
CCPotentiometer potentiometer10 = { A10, {48, CHANNEL_12} };
CCPotentiometer potentiometer11 = { A11, {49, CHANNEL_13} };
CCPotentiometer potentiometer12 = { A12, {50, CHANNEL_14} };
CCPotentiometer potentiometer13 = { A13, {51, CHANNEL_15} };
CCPotentiometer potentiometer14 = { A14, {MIDI_CC::Channel_Volume, CHANNEL_16} };

CCButtonLatched button9 = { 9, {32, CHANNEL_1}, };   
CCButtonLatched button10 = { 10, {33, CHANNEL_1}, }; 
CCButtonLatched button22 = { 22, {37, CHANNEL_1}, }; 
CCButtonLatched button23 = { 23, {38, CHANNEL_1}, }; 
CCButtonLatched button24 = { 24, {39, CHANNEL_1}, }; 
CCButtonLatched button25 = { 25, {60, CHANNEL_1}, }; 
CCButtonLatched button26 = { 26, {61, CHANNEL_1}, }; 
CCButtonLatched button27 = { 27, {62, CHANNEL_1}, }; 
CCButtonLatched button28 = { 28, {63, CHANNEL_1}, }; 
CCButtonLatched button29 = { 29, {64, CHANNEL_1}, }; 
CCButtonLatched button30 = { 30, {65, CHANNEL_1}, }; 
CCButtonLatched button31 = { 31, {15, CHANNEL_1}, }; 
CCButtonLatched button32 = { 32, {14, CHANNEL_1}, }; 
CCButtonLatched button33 = { 33, {13, CHANNEL_1}, }; 
CCButtonLatched button34 = { 34, {12, CHANNEL_1}, }; 
CCButtonLatched button35 = { 35, {11, CHANNEL_1}, }; 

Bankable::CCPotentiometer pots[] = {    //los potenciometros conectados A0;A1 y A2 empiezan en 67,68 y 69 respectivamente de CC y cada vez que pulsemos el boton 8 incrementaran un valor de CC hasta 4 veces (el potenciometro con CC 67 llegara al  CC 71 y luego volvera a 67 en la siguiente pulsacion del boton 8)
  
  {bank, A0, 66},
  {bank, A1, 67},
  {bank, A2, 68},
  {bank, A3, 69}
  };

Bankable::CCButtonLatched<6> button5 { bank, 5, 90, };   //los botones de los pines 5 y 6 empiezan en 90 y 91 respectivamente de CC y cada vez que pulsemos el boton 8 incrementaran un valor de CC hasta 4 veces (el 90 llegara al 94 y luego volvera a 90 en la siguiente pulsacion del boton 8).el boton 7 es lo contrario del 8
Bankable::CCButtonLatched<6> button6 { bank, 6, 91, };

IncrementDecrementSelector<6> selector { bank, {7, 8}};  //establecemos los pines 7 y 8 como los pines para crecer o decrecer el banco configurado (cuatro ajustes distintos para ese banco configurado)





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

}

void loop() {
  Control_Surface.loop();
 
   uint32_t rojo = pixels.Color(150,0,0);
  
 pixels.setPixelColor(0, rojo); // Brillo moderado en rojo en el pixel numero 1 de nuestra tira de 6 leds

 pixels.show();   // Mostramos y actualizamos el color del pixel de nuestra cinta led RGB

 }

As i have explained You press 7 or 8 and you increase or decrease the pedal…
Potentiometers A0 to A3 change CC values and increase 4 numbers on every 7 or 8 press
The same for 5 and 6 button (increases or dicreases 4 numbers on every press
so if you got 68 CC for one potentiometer then will be 72CC.

Bank<6> bank(4); allows you to press 6 times (you can increase 6 times and dicrease the same 6 times) and the number four it´s for add 4 CC numbers. So you can select between 6 pedals

Thanks!

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