Midi Controller with Channel Change issues - uno. 5pin din

Hi im trying to figure out what im doing wrong. Im a total noob btw. I want to make a midicontroller keyboard for analog midi instruments. In addition to the keyboard for playing notes I also want a set of buttons that change the midi channel im sending to. One button per channel. push the first button, is switches to channel 1. push the second, 2. etc.

Im using an array for the keyboard buttons. Ill eventually use a multiplexer for for inputs.

Im then just using individual buttons to switch the channel.

anyways. doesnt work. the keyboard outputs notes, but the midi channel doesnt change with the button press. any help would be very very appreciated. thanks!

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER
**Arduino UNO ONLY!**
 *************************************************************/
//TESTING OUT ADDING MIDI CHANNEL CHANGE BUTTONS
int channel = 1;

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 3;
//---How many buttons are connected to a multiplexer?---------
byte NUMBER_MUX_BUTTONS = 0;

//************************************************************



//***ANY MULTIPLEXERS? (74HC4067)************************************
//MUX address pins must be connected to Arduino UNO pins 2,3,4,5
//A0 = PIN2, A1 = PIN3, A2 = PIN4, A3 = PIN5
//*******************************************************************
//Mux M1(5, 16, false); //Digital multiplexer on Arduino pin 10
//Mux M2(A5, 8, true); //Analog multiplexer on Arduino analog pin A0

//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

Button BU1(2, 0, 60, channel, 5 );
Button BU2(3, 0, 64, channel, 5 );
Button BU3(4, 0, 67, channel, 5 );
//Button BU4(5, 0, 70, channel, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {&BU1, &BU2, &BU3};
//*******************************************************************


//***DEFINE BUTTONS CONNECTED TO MULTIPLEXER*************************
//Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button MBU1(M1, 0, 0, 70, 1, 5);
//Button MBU2(M1, 1, 1, 71, 1, 5);
//Button MBU3(M1, 2, 2, 72, 1, 5);
//Button MBU4(M1, 3, 0, 73, 1, 5);
//Button MBU5(M1, 4, 0, 74, 1, 5);
//Button MBU6(M1, 5, 0, 75, 1, 5);
//Button MBU7(M1, 6, 0, 76, 1, 5);
//Button MBU8(M1, 7, 0, 77, 1, 5);
//Button MBU9(M1, 8, 0, 78, 1, 5);
//Button MBU10(M1, 9, 0, 79, 1, 5);
//Button MBU11(M1, 10, 0, 80, 1, 5);
//Button MBU12(M1, 11, 0, 81, 1, 5);
//Button MBU13(M1, 12, 0, 82, 1, 5);
//Button MBU14(M1, 13, 0, 83, 1, 5);
//Button MBU15(M1, 14, 0, 84, 1, 5);
//Button MBU16(M1, 15, 0, 85, 1, 5);
//*******************************************************************
////Add multiplexed buttons used to array below like this->  Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6.....};
Button *MUXBUTTONS[] {};


//*******************************************************************

int buttonState = 0;  
void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
  Serial.begin(9600);
  pinMode(5, INPUT_PULLUP);
}

void loop() {

 buttonState = digitalRead(5);
  Serial.println(buttonState);
   if (buttonState == HIGH) {
    // set midi channel:
    channel = 2;
  }


  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
}


//*****************************************************************
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;
      }
    }
  }
}
//***********************************************************************

want to make a midicontroller keyboard for analog midi instruments

Not sure I understand that.

I also don’t understand your code, it doesn’t help that you don’t use code tags. please read the how to use this forum sticky post to learn how to post code here. Because you didn’t then the forum software has taken some of you code and turned it into a format command. Hence the italics.

Normally you would have a single variable possibly called channel and you would change its value. Then you use that variable in the note on / off messages.

ok. totally great reply. thanks.

I just meant I want to control a hardware synth via 5pin din. I want to have one set of buttons for notes. and another set of buttons to declare which channel the notes are sending to.

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER
**Arduino UNO ONLY!**
 *************************************************************/
//TESTING OUT ADDING MIDI CHANNEL CHANGE BUTTONS
int channel = 1;

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 3;
//---How many buttons are connected to a multiplexer?---------
byte NUMBER_MUX_BUTTONS = 0;

//************************************************************



//***ANY MULTIPLEXERS? (74HC4067)************************************
//MUX address pins must be connected to Arduino UNO pins 2,3,4,5
//A0 = PIN2, A1 = PIN3, A2 = PIN4, A3 = PIN5
//*******************************************************************
//Mux M1(5, 16, false); //Digital multiplexer on Arduino pin 10
//Mux M2(A5, 8, true); //Analog multiplexer on Arduino analog pin A0

//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

Button BU1(2, 0, 60, channel, 5 );
Button BU2(3, 0, 64, channel, 5 );
Button BU3(4, 0, 67, channel, 5 );
//Button BU4(5, 0, 70, channel, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {&BU1, &BU2, &BU3};
//*******************************************************************


//***DEFINE BUTTONS CONNECTED TO MULTIPLEXER*************************
//Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button MBU1(M1, 0, 0, 70, 1, 5);
//Button MBU2(M1, 1, 1, 71, 1, 5);
//Button MBU3(M1, 2, 2, 72, 1, 5);
//Button MBU4(M1, 3, 0, 73, 1, 5);
//Button MBU5(M1, 4, 0, 74, 1, 5);
//Button MBU6(M1, 5, 0, 75, 1, 5);
//Button MBU7(M1, 6, 0, 76, 1, 5);
//Button MBU8(M1, 7, 0, 77, 1, 5);
//Button MBU9(M1, 8, 0, 78, 1, 5);
//Button MBU10(M1, 9, 0, 79, 1, 5);
//Button MBU11(M1, 10, 0, 80, 1, 5);
//Button MBU12(M1, 11, 0, 81, 1, 5);
//Button MBU13(M1, 12, 0, 82, 1, 5);
//Button MBU14(M1, 13, 0, 83, 1, 5);
//Button MBU15(M1, 14, 0, 84, 1, 5);
//Button MBU16(M1, 15, 0, 85, 1, 5);
//*******************************************************************
////Add multiplexed buttons used to array below like this->  Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6.....};
Button *MUXBUTTONS[] {};


//*******************************************************************

int buttonState = 0;  
void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
  Serial.begin(9600);
  pinMode(5, INPUT_PULLUP);
}

void loop() {

 buttonState = digitalRead(5);
  Serial.println(buttonState);
   if (buttonState == HIGH) {
    // set midi channel:
    channel = 2;
  } 


  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
}


//*****************************************************************
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;
      }
    }
  }
}
//***********************************************************************

Ok, thanks I think I now know what you want to do but the code is still looking a bit odd to me. Did you write this or did you find it somewhere?

I am assuming you have 16 buttons controlling the channel, how many do you have for the notes?

In the embedded world code only means something when you can judge it against the hardware so could you please attach a schematic of what you have. Just a pen and paper drawing is fine, please to don’t post a physical layout diagram like Fritzing produces.

The use of -> is not very common in Arduino code and I think it is not being applied correctly here, but I am not sure as I never use it. Is this a function of the control library? I never use that as i think it makes code a lot more complex that just reading the individual pins.

Also it would help if you distinguished between channel buttons and note buttons by using different names.

What Arduino are you using?

Note that this line

 MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel)

Is odd. What do you think it is doing? It is not setting the channel if that is what you think. Setting a channel is nothing to do with MIDI CC messages.

The Control Surface library has a bank functionality that allows you to change the channel of the buttons. It also has support for multiplexers.

For example:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color] [color=#434f54]// Include the Control Surface library[/color]
 
[color=#434f54]// Instantiate a MIDI over USB interface.[/color]
[b][color=#d35400]USBMIDI_Interface[/color][/b] [color=#00979c]midi[/color][color=#000000];[/color]

[color=#434f54]// Instantiate four Banks, with one track per bank. [/color]
[b][color=#d35400]Bank[/color][/b][color=#434f54]<[/color][color=#000000]4[/color][color=#434f54]>[/color] [color=#000000]bank[/color][color=#000000]([/color][color=#000000]1[/color][color=#000000])[/color][color=#000000];[/color]
[color=#434f54]//   │       └───── number of tracks per bank[/color]
[color=#434f54]//   └───────────── number of banks[/color]

[color=#434f54]// Instantiate a Bank selector to control which one of the four Banks is active.[/color]
[b][color=#d35400]ManyButtonsSelector[/color][/b][color=#434f54]<[/color][color=#000000]4[/color][color=#434f54]>[/color] [color=#000000]selector[/color] [color=#434f54]=[/color] [color=#000000]{[/color]
    [color=#000000]bank[/color][color=#434f54],[/color]         [color=#434f54]// bank to manage[/color]
    [color=#000000]{[/color][color=#000000]6[/color][color=#434f54],[/color] [color=#000000]7[/color][color=#434f54],[/color] [color=#000000]8[/color][color=#434f54],[/color] [color=#000000]9[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#434f54]// push button pins[/color]
[color=#000000]}[/color][color=#000000];[/color]

[color=#434f54]// Instantiate an array of Bankable NoteButton objects[/color]
[b][color=#d35400]Bankable[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][b][color=#d35400]NoteButton[/color][/b] [color=#000000]buttons[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color]
  [color=#000000]{[/color][color=#000000]{[/color][color=#000000]bank[/color][color=#434f54],[/color] [b][color=#d35400]BankType[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]CHANGE_CHANNEL[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#000000]2[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]60[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
  [color=#434f54]// │              │                │   │       └──────── MIDI base channel[/color]
  [color=#434f54]// │              │                │   └──────────────── MIDI note number[/color]
  [color=#434f54]// │              │                └──────────────────── button pin number[/color]
  [color=#434f54]// │              └───────────────────────────────────── bank affects channel (not note number)[/color]
  [color=#434f54]// └──────────────────────────────────────────────────── bank that changes the channel[/color]
  [color=#000000]{[/color][color=#000000]{[/color][color=#000000]bank[/color][color=#434f54],[/color] [b][color=#d35400]BankType[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]CHANGE_CHANNEL[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#000000]3[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]64[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
  [color=#000000]{[/color][color=#000000]{[/color][color=#000000]bank[/color][color=#434f54],[/color] [b][color=#d35400]BankType[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]CHANGE_CHANNEL[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#000000]4[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]67[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
[color=#000000]}[/color][color=#000000];[/color]
 
[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Initialize Control Surface[/color]
[color=#000000]}[/color]
 
[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Update the Control Surface[/color]
[color=#000000]}[/color]

See also Getting Started and the Bank example.

Pieter

Your code creates three buttons with the same channel, you then later change the variable used earlier to initialize the buttons, that doesn't affect the buttons though.

When you want to change channel you'll have to change all the Buttons' channels explicitly I think.

Yes OK. So first off this is mostly code i didnt write. Ive tried to simplify it for working out the functionality.

Right now only three buttons are functioning as notes. and one buttons trying to change the channel variable to channel 2 later.

the multiplexer buttons arent doing anything atm. the code is just there and blanked out for later use.

So what i need to do is change the 'channel' variable that was initialized in the earlier buttons.

i need to dig into the control surface function. that looks very promising.

im writing this for an UNO.

I know PeterP is a strong proponent of the control surface library, but in my opinion it is good for getting something working without understanding much about what you are doing. In other words you learn how to use the library but you will get no "transferable skills". A lot of libraries are in fact opportunities to learn deniers.

MIDI is one of those not trivial but not very difficult tasks that allow you a good opportunity to learn. In fact I wrote a book about sound and MIDI is covered in some detail starting from the ground up.

Chapter 5 contains the Spoon-o-phone which is very close to what you want. However it does work on a fixed channel.

Right now only three buttons are functioning as notes. and one buttons trying to change the channel variable to channel 2 late

I notice that you change the channel variable to 2 but you have nothing to change it back. That means you have to have a reset the Arduino to get the original code defined channel back.

This is some code that fires off a random note and changes the instrument for each note.

/* Midi note fire 3 - Mike Cook
 *
 * send MIDI serial data, automatically for a test
 * Use pin 2 to set output channel to 2
 * Use pin 3 to set output channel to 1
 * Wire push buttons between pin and ground
*/
char midiChannel = 0;

void setup() {
 //  Setup serial
  Serial.begin(31250);  // MIDI speed
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
}

void loop() {
  int val;
  if(digitalRead(2) == LOW) midiChannel = 1;
  if(digitalRead(3) == LOW) midiChannel = 0;
  for(int ins=0; ins<127; ins++){ // one note from all the instruments
  voiceChange(ins); 
  val = random(20,100);
    noteSend(0x90, val, 127); // note on
    delay(200);
    noteSend(0x80, val, 127); // note off
   delay(800);
    } // end loop function
}

// sends voice change message
  void voiceChange(int i){
     Serial.write(0xC0 | midiChannel); // program change message
     Serial.write(i); 
  }
//  plays a MIDI note
 void noteSend(char cmd, char data1, char data2) {
  cmd = cmd | midiChannel;  // merge channel number and command
  Serial.write(cmd);
  Serial.write(data1);
  Serial.write(data2);
}

Note how no libraries are used. Read the notes at the start of the code for how to wire up the two channel change numbers. MIDI channel 1 is actually channel 0 in code but because musicians can't cope with the number zero we present this to them as one and this results in all the channel numbers being moved up by one to give channels 1 to 16. Where as they are actually channels 0 to 15. This will explain why the buttons change the channel between 0 and 1 and not 1 and 2.

This code is for the UNO and so uses the baud rate of 31250 which is the MIDI speed. As the serial monitor will not work at this rate you can not use Serial.print to debug / confirm any variable values, if you drop the speed to something you can use Serial.print with then it will not work as MIDI. If you had the Arduino Micro or Leonardo then you would be able to use Print and MIDI at the same time.

Hi all thanks for all that input. Sorry, work started back up and ive been too busy to finish this project but getting back into it now.

Mike, thank you for all of that. I AM interested in learning more eventually so will spend more time with that. thanks for your input.

Pieter - I started at the control surface route and do find it to be much easier to wrap my head around. i got a working 6 button prototype using your control surface code above.

Could you help me with how i would use that same code but with several CD74HC4051 multiplexers?

Ive seen this, but cant figure out how to integrate the mux inputs with the banks and buttons in the example above.

https://tttapa.github.io/Control-Surface/Doc/Doxygen/d9/d42/2_8DigitalReadSerial_8ino-example.html

if you could help that would be very excellent.
thanks!

kodiakkodiak:
Pieter - I started at the control surface route and do find it to be much easier to wrap my head around. i got a working 6 button prototype using your control surface code above.

Could you help me with how i would use that same code but with several CD74HC4051 multiplexers?

Ive seen this, but cant figure out how to integrate the mux inputs with the banks and buttons in the example above.

https://tttapa.github.io/Control-Surface/Doc/Doxygen/d9/d42/2_8DigitalReadSerial_8ino-example.html

if you could help that would be very excellent.
thanks!

There's a step by step guide here. Basically you just create the multiplexer object, let's say with a variable name mux. Then when you declare the push buttons or other objects that expect a pin number, you pass it mux.pin(n), where n is the index of the multiplexer's input pin you wish to use (counting from 0).

like this?

#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface.
HardwareSerialMIDI_Interface midi(Serial, MIDI_BAUD);

// Instantiate a multiplexer
CD74HC4067 mux = {
  2,               // input pin
  {3, 4, 5, 6}, // Address pins S0, S1, S2, S3
  7, // Optionally, specify the enable pin
};

// Instantiate four Banks, with one track per bank.
Bank<4> bank(1);
//   │       └───── number of tracks per bank
//   └───────────── number of banks

// Instantiate a Bank selector to control which one of the four Banks is active.
ManyButtonsSelector<4> selector = {
    bank,         // bank to manage
    {7, 8, 9, 10}, // push button pins
};

// Instantiate an array of Bankable NoteButton objects
Bankable::NoteButton buttons[] = {
  {{bank, BankType::CHANGE_CHANNEL}, mux.pin(0), {60, CHANNEL_1}},
  // │              │                │   │       └──────── MIDI base channel
  // │              │                │   └──────────────── MIDI note number
  // │              │                └──────────────────── button pin number
  // │              └───────────────────────────────────── bank affects channel (not note number)
  // └──────────────────────────────────────────────────── bank that changes the channel
  {{bank, BankType::CHANGE_CHANNEL}, mux.pin(1), {64, CHANNEL_1}},
  {{bank, BankType::CHANGE_CHANNEL}, mux.pin(2), {67, CHANNEL_1}},
};
 
void setup() {
  mux.begin();                  // Initialize multiplexer
  Control_Surface.begin(); // Initialize Control Surface
}
 
void loop() {
  Control_Surface.loop(); // Update the Control Surface
}

kodiakkodiak:
like this?

That looks alright.
The mux.begin() in the setup is not strictly necessary, the multiplexer will automatically be initialized when you call Control_Surface.begin().