Creating usbMIDI "Banks"

Hello this is literally my first time coding.. I am basically following what I can find on Arduino forums and PJRC's MIDI section.

What I am looking to build is a usbMIDI device with:

16 arcade buttons

4 "Top Bank Buttons" that will change the MIDI Notes of all 16 arcade buttons

3 "Left side bank buttons" (MIDI Notes stay the same regardless of what "Top bank button" is activated)

3 "Right side bank buttons" (MIDI Notes stay the same regardless of what "Top bank button" is activated)

2 10k Pots

2 10k Faders

The best way I can explain what I mean is using this image provided by DJTechTools for the MIDI FIGHTER 3D

This is the code I have so far (please be gentle its my first ever!) The thought of how to implement this popped in my head as I was copy pasting the basics (or at least the basics from what I understand)

//----------------------------------------------
//------------------START-----------------------
//----------------------------------------------

// Bounce library makes button change detection easy
#include <Bounce.h>

//debugging will print out in serial instead of midi
boolean debugging=false;
boolean traktorrr=false;

//Channel For Midi Messages -
//If, const int channel = 3; doesnt work
//use, int midiChannel=3;
const int channel = 3;

Bounce button1 = Bounce (1, 5) // Bounce (Button#, 5ms debounce)
Bounce button2 = Bounce (2, 5) // 5ms debounce is appropriate for good
Bounce button3 = Bounce (3, 5) // quality mechanical pushbuttons
Bounce button4 = Bounce (4, 5)
Bounce button5 = Bounce (5, 5)
Bounce button6 = Bounce (6, 5)
Bounce button7 = Bounce (7, 5)
Bounce button8 = Bounce (8, 5)
Bounce button9 = Bounce (9, 5)
Bounce button10 = Bounce (10, 5)
Bounce button11 = Bounce (11, 5)
Bounce button12 = Bounce (12, 5)
Bounce button13 = Bounce (13, 5)
Bounce button14 = Bounce (14, 5)
Bounce button15 = Bounce (15, 5)
Bounce button16 = Bounce (16, 5)
Bounce button17 = Bounce (17, 5)
Bounce button18 = Bounce (18, 5)
Bounce button19 = Bounce (19, 5)
Bounce button20 = Bounce (20, 5)
Bounce button21 = Bounce (21, 5)
Bounce button22 = Bounce (22, 5)
Bounce button23 = Bounce (23, 5)
Bounce button24 = Bounce (24, 5)
Bounce button25 = Bounce (25, 5)
Bounce button26 = Bounce (26, 5)
//SKIP PINS 0 & 6 !!!
void setup() {
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  pinMode(19, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  pinMode(21, INPUT_PULLUP);
  pinMode(22, INPUT_PULLUP);
  pinMode(23, INPUT_PULLUP);
  pinMode(24, INPUT_PULLUP);
  pinMode(25, INPUT_PULLUP);
  pinMode(26, INPUT_PULLUP);
  pinMode(27, INPUT_PULLUP);
}

void loop() {
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update(); // "BANK 1" -- 0 = C-1
  button18.update(); // "BANK 2" -- 1 = C#-1
  button19.update(); // "BANK 3" -- 2 = D-1
  button20.update(); // "BANK 4" -- 3 = D#-1
  button21.update(); // "LSIDE 1" - 22 = A#0
  button22.update(); // "LSIDE 2" - 21 = A0
  button23.update(); // "LSIDE 3" - 20 = G#0
  button24.update(); // "RSIDE 1" - 25 = C#1
  button25.update(); // "RSIDE 2" - 24 = C1
  button26.update(); // "RSIDE 3" - 23 = B0
    // Note On messages when each button is pressed
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
  }
  if (button4.fallingEdge()) {
    usbMIDI.sendNoteOn(63, 99, channel);  // 63 = D#4
  }
  if (button5.fallingEdge()) {
    usbMIDI.sendNoteOn(64, 99, channel);  // 64 = E4
  }
  if (button6.fallingEdge()) {
    usbMIDI.sendNoteOn(65, 99, channel);  // 65 = F4
  }
  if (button7.fallingEdge()) {
    usbMIDI.sendNoteOn(66, 99, channel);  // 66 = F#4
  }
  if (button8.fallingEdge()) {
    usbMIDI.sendNoteOn(67, 99, channel);  // 67 = G4
  }
  if (button9.fallingEdge()) {
    usbMIDI.sendNoteOn(68, 99, channel);  // 68 = G#4
  }

ok so i have gotten a little further i think any way haha, i have a general idea how to implement "banks" in to this controller.. here is what i have come up with so far.. any help would be great!

//BUTTONS x16
int buttons[16]= {
1, 5, 10, 14,
2, 7, 11, 15,
3, 8, 12, 16,
4, 9, 13, 17
};

// FORMAT <---->  //"BTN#" "NOTE"\\ Taken from MIDI FIGHTER 3D
//----------------------------------------------------------
//   BANK 1      BANK 2       BANK 3       BANK 4
//   *C-1*       *C#-1*       *D-1*        *D#-1*
//----------------------------------------------------------
// 1 - C3    |  1 - E4    |   1 - G#5   |   1 - C7 
// 2 - G#2   |  2 - C4    |   2 - E5    |   2 - G#6
// 3 - E2    |  3 - G#3   |   3 - C5    |   3 - E6 
// 4 - C2    |  4 - E3    |   4 - G#4   |   4 - C6 
// 5 - C#3   |  5 - F4    |   5 - A5    |   5 - C#7
// 6 - A2    |  6 - C#4   |   6 - F5    |   6 - A6
// 7 - F2    |  7 - A3    |   7 - C#5   |   7 - F6 
// 8 - C#2   |  8 - F3    |   8 - A4    |   8 - C#6 
// 9 - D3    |  9 - F#4   |   9 - A#5   |   9 - D7
//10 - A#2   | 10 - D4    |  10 - F#5   |  10 - A#6 
//11 - F#2   | 11 - A#3   |  11 - D5    |  11 - F#6
//12 - D2    | 12 - F#3   |  12 - A#4   |  12 - D6
//13 - D#3   | 13 - G4    |  13 - B5    |  13 - D#7 
//14 - B2    | 14 - D#4   |  14 - G5    |  14 - B6
//15 - G2    | 15 - B3    |  15 - D#5   |  15 - G6 
//16 - D#2   | 16 - G3    |  16 - B4    |  16 - D#6 

//SIDE BUTTONS NEVER CHANGE
//TLEFT - A#0  
//MLEFT - A0
//BLEFT - G#0
//
//TRIGHT - C#1
//MRIGHT - C1
//BRIGHT - B0


//TOPBANKS x4
int topbanks[4]= {
  18, 19, 20, 21
};

//SIDEBANKS x6
int sidebanks[6]= {
  22, 23, 24, 25, 26, 27
};

//KNOBS x4
int knobs[4]= {
  A0, A1, A2, A3
};
//
//FADERS x4
int faders[4]= {
  A4, A5, A6, A7
};

Bounce button1 = Bounce (1, 5) // Bounce (Button#, 5ms debounce)
Bounce button2 = Bounce (2, 5) // 5ms debounce is appropriate for good
Bounce button3 = Bounce (3, 5) // quality mechanical pushbuttons
Bounce button4 = Bounce (4, 5)
Bounce button5 = Bounce (5, 5)
Bounce button6 = Bounce (6, 5)
Bounce button7 = Bounce (7, 5)
Bounce button8 = Bounce (8, 5)
Bounce button9 = Bounce (9, 5)
Bounce button10 = Bounce (10, 5)
Bounce button11 = Bounce (11, 5)
Bounce button12 = Bounce (12, 5)
Bounce button13 = Bounce (13, 5)
Bounce button14 = Bounce (14, 5)
Bounce button15 = Bounce (15, 5)
Bounce button16 = Bounce (16, 5)
Bounce button17 = Bounce (17, 5)
Bounce button18 = Bounce (18, 5)
Bounce button19 = Bounce (19, 5)
Bounce button20 = Bounce (20, 5)
Bounce button21 = Bounce (21, 5)
Bounce button22 = Bounce (22, 5)
Bounce button23 = Bounce (23, 5)
Bounce button24 = Bounce (24, 5)
Bounce button25 = Bounce (25, 5)
Bounce button26 = Bounce (26, 5)

void setup() {               //"LABEL"   "CC"  "NOTE"
  //SKIP PIN 0               // SKIP THIS PIN (FOR EASE)
  pinMode(1, INPUT_PULLUP);  // "BTN 1"
  pinMode(2, INPUT_PULLUP);  // "BTN 2
  pinMode(3, INPUT_PULLUP);  // "BTN 3
  pinMode(4, INPUT_PULLUP);  // "BTN 4
  pinMode(5, INPUT_PULLUP);  // "BTN 5
  //SKIP PIN 6               // SKIP THIS PIN (ONBOARD LED PIN)
  pinMode(7, INPUT_PULLUP);  // "BTN 6
  pinMode(8, INPUT_PULLUP);  // "BTN 7
  pinMode(9, INPUT_PULLUP);  // "BTN 8
  pinMode(10, INPUT_PULLUP); // "BTN 9
  pinMode(11, INPUT_PULLUP); // "BTN 10
  pinMode(12, INPUT_PULLUP); // "BTN 11
  pinMode(13, INPUT_PULLUP); // "BTN 12
  pinMode(14, INPUT_PULLUP); // "BTN 13
  pinMode(15, INPUT_PULLUP); // "BTN 14
  pinMode(16, INPUT_PULLUP); // "BTN 15
  pinMode(17, INPUT_PULLUP); // "BTN 16
  pinMode(18, INPUT_PULLUP); // "BANK 1" -- 0 = C-1
  pinMode(19, INPUT_PULLUP); // "BANK 2" -- 1 = C#-1
  pinMode(20, INPUT_PULLUP); // "BANK 3" -- 2 = D-1
  pinMode(21, INPUT_PULLUP); // "BANK 4" -- 3 = D#-1
  pinMode(22, INPUT_PULLUP); // "LSIDE 1" - 22 = A#0
  pinMode(23, INPUT_PULLUP); // "LSIDE 2" - 21 = A0
  pinMode(24, INPUT_PULLUP); // "LSIDE 3" - 20 = G#0
  pinMode(25, INPUT_PULLUP); // "RSIDE 1" - 25 = C#1
  pinMode(26, INPUT_PULLUP); // "RSIDE 2" - 24 = C1
  pinMode(27, INPUT_PULLUP); // "RSIDE 3" - 23 = B0
}

void loop() {
  button1.update();
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  button6.update();
  button7.update();
  button8.update();
  button9.update();
  button10.update();
  button11.update();
  button12.update();
  button13.update();
  button14.update();
  button15.update();
  button16.update();
  button17.update(); // "BANK 1" -- 0 = C-1
  button18.update(); // "BANK 2" -- 1 = C#-1
  button19.update(); // "BANK 3" -- 2 = D-1
  button20.update(); // "BANK 4" -- 3 = D#-1
  button21.update(); // "LSIDE 1" - 22 = A#0
  button22.update(); // "LSIDE 2" - 21 = A0
  button23.update(); // "LSIDE 3" - 20 = G#0
  button24.update(); // "RSIDE 1" - 25 = C#1
  button25.update(); // "RSIDE 2" - 24 = C1
  button26.update(); // "RSIDE 3" - 23 = B0

hello again arduino world, have made some more revisions to the code for my midi controller, i am trying to label everything as best i can to make it a bit easier for others wanting to create a basic midi controller.

I am still having trouble wrapping my head around how to change the note values of the 16 arcade buttons with 1 of 4 bank buttons as seen in fig 1.

Fig.1

// BANK 1 BANK 2 BANK 3 BANK 4
// C-1 C#-1 D-1 D#-1
//----------------------------------------------------------
// 1 - C3 | 1 - E4 | 1 - G#5 | 1 - C7
// 2 - G#2 | 2 - C4 | 2 - E5 | 2 - G#6

im having some errors as well not too sure what they mean though.. so i will also include the error report.

75: error: redefinition of 'int topbanks [4]'
34: error: 'int topbanks [4]' previously defined here
.ino: In function 'void setup()':
89: error: 'usbMIDI' was not declared in this scope
89: error: 'myNoteOn' was not declared in this scope
90: error: 'myNoteOff' was not declared in this scope
100: error: 'topbanksVal' was not declared in this scope
.ino: In function 'void loop()':
141: error: expected ',' or ';' before ':' token
200: error: expected primary-expression at end of input
200: error: expected ;' at end of input 200: error: expected primary-expression at end of input 200: error: expected )' at end of input
200: error: expected statement at end of input
200: error: expected `}' at end of input

Here is what i have so far for code, if you can see any thing that needs changing please let me know :smiley:

//Teensy Code for Midi Controller
//RobTapps
//This Controller Consists of UP TO 26 digital and 8 analog I/O
//**MUX may come later for more I/O**
//----------------------------------------------
//------------------START-----------------------
//----------------------------------------------

#include <Bounce.h>        // Bounce library makes button change detection easy

boolean debugging=false;   // Debugging will print out in serial instead of midi
boolean traktorrr=false;

const int channel = 3;     // Channel For Midi Messages -
                           // If, const int channel = 3; doesnt work
                           // use, int midiChannel=3;
                           
// Pin Numbers for Parts

//LED's x3
int leds[3]= {
                     // ADD PIN(S) BEFORE COMPILE
};

// BUTTONS x16
int buttons[16]= {
  1, 5, 10, 14,
  2, 7, 11, 15,
  3, 8, 12, 16,
  4, 9, 13, 17
};

// TOPBANKS x4
int topbanks[4]= {
  18, 19, 20, 21
};

// TOP BUTTONS NEVER CHANGE
// BANK 1 - Pin 18 - C-1
// BANK 2 - Pin 19 - C#-1
// BANK 3 - Pin 20 - D-1
// BANK 4 - Pin 21 - D#-1

// SIDEBANKS x6                
int sidebanks[6]= {
  22, 23, 24, 25, 26, 27
};

// SIDE BUTTONS NEVER CHANGE
// TLEFT - Pin 24 - A#0  
// MLEFT - Pin 23 -  A0
// BLEFT - Pin 22 - G#0
//
// TRIGHT - Pin 27 - C#1
// MRIGHT - Pin 26 - C1
// BRIGHT - Pin 25 - B0

// KNOBS x4                   // Enables all 4 "knob Pins".
int knobs[4]= {               // This means you CAN use them all
  A0, A1, A2, A3              // but dont have to if you dont want to.
};

// FADERS x4                  // Enables all 4 "fader Pins".
int faders[4]= {              // This means you CAN use them all
  A4, A5, A6, A7              // but dont have to if you dont want to.
};

// Variables to Store Vlues
Bounce *buttonState[16];       // Bounce All Pad Buttons?  // Denote if needed
Bounce *tobbuttonState[4];     // Bounce All Bank Buttons? // Denote if needed
Bounce *sidebuttonState[6];    // Bounce All Side Buttons? // Denote if needed
int knobVal[4];                // Save Knob CC Values
int faderVal[4];               // Save Fader CC Values
int sidebanksVal[6];           // Save SideButton CC Values
int topbanks[4];               // Save Topbutton CC Values
boolean ledState[3];  //fix before compile

int comboState=0;              // State of current "Combo" in this case 0 = NO COMBO
int temp;

void setup() {                 // Initializes values and sets modes

  if (debugging) {             // Starts DEBUG MODE
    Serial.begin(9600);        // Opens  serial port
  }  
  
  else {
    Serial.begin(31250);       // Opens Midi
    usbMIDI.setHandleNoteOn(myNoteOn);
    usbMIDI.setHandleNoteOff(myNoteOff);
  }
  
  for (int i=0;i<16;i++) {                     // Arcade Buttons
    pinMode(buttons[i], INPUT_PULLUP);         // Sets pinMode for all Arcade Buttons
    buttonState[i]= new Bounce(buttons[i], 5); // All Arcade Buttons 5ms debounce
  }
  
  for (int i=0;i<4;i++) {                      // Top Bank Buttons
    pinMode(topbanks[i], INPUT_PULLUP);        // Sets pinMode for all Top Bank Buttons
    topbanksVal[i]=0;
  }
  
  for (int i=0;i<6;i++) {                      // Side Bank Buttons
    pinMode(sidebanks[i], INPUT_PULLUP);       // Sets pinMode for all Side Bank Buttons
    sidebanksVal[i]=0;
  }
  
  for (int i=0;i<16;i++) {                   // LED's
    pinMode(leds[i], OUTPUT);                // Sets pinMode for all LED's
    digitalWrite(leds[i], HIGH);             // Tells Teensy "LED # OFF"
    delay(50);                               // Tells Teensy "DELAY 50ms"
    digitalWrite(leds[i], LOW);              // Tells Teensy "LED # ON"
  }
  
  for (int i=0;i<10;i++) {                   // Switch to "Traktor Mode" LED's will flash, To switch hold LOWER LEFT and LOWER RIGHT Arcade Buttons while device is booting
    digitalWrite(leds[0], HIGH);             // Tells Teensy "LED # OFF"
    delay(100);                              // Tells Teensy "DELAY 100ms"
    digitalWrite(leds[0], LOW);              // Tells Teensy "LED # ON"
    delay(100);                              // Tells Teensy "DELAY 100ms"

    if ((buttonState[0]->read()==LOW)&&(buttonState[3]->read()==LOW)) { 

      traktorrr=true;
      
      for (int i=0;i<10;i++) { 
        digitalWrite(leds[0], HIGH);             // Tells Teensy "LED # OFF"
        digitalWrite(leds[1], HIGH);             // Tells Teensy "LED # OFF"
        digitalWrite(leds[2], HIGH);             // Tells Teensy "LED # OFF"
        delay(50);                              // Tells Teensy "DELAY 50ms"
        digitalWrite(leds[0], LOW);              // Tells Teensy "LED # ON"
        digitalWrite(leds[1], LOW);              // Tells Teensy "LED # ON"
        digitalWrite(leds[2], LOW);              // Tells Teensy "LED # ON"
        delay(50);                              // Tells Teensy "DELAY 50ms"
      }
      break;
    }
  }
}

void loop() {                                    // Reads Arcade Buttons
  for (int i=0:1<16:i++) {
    if (buttonstate[i]->update()) {              // Arcade Button State Changed
     if (buttonstate[i]->read()==LOW) {          // Arcade Button is PRESSED
      midiNoteOnOff(true, 1+36+bank*16);
     }
     else {
       midiNoteOnOff(false, i+36+bank*16);
     }
   }
 }                                               // Ends Loop
 
 for (int i=0,i<4;i++) {                         // Reads Knobs
   temp=map(analogRead(knobs[i]), 0, 1023, 127);
   
   if (temp!=knobVal[i]) {                       // Value Changed
    midiCC(temp, knobVal[i], i*2+16+bank*17);
  }
  knobVal[i]=temp;
}                                                // Ends Loop

 for (int i=0;i<4:1++) {                         // Reads Faders
   temp=map(analogRead(faders[i]), 0, 1023, 0, 127); 
   
   if (temp!=faderVal[i]) {                      // Value Changed
     midiCC(temp, faderVal[i], i*2+24+bank*17);
   } 
 }                                               // Ends Loop
 
 switch(bank) {                                  // Switching Banks, ledState shows what LED is ON or OFF
 case 0:
    ledState[0]=false;
    ledState[1]=false;
    ledState[2]=false;
    break;
  case 1:
    ledState[0]=true;
    ledState[1]=false;
    ledState[2]=false;
    break;
  case 2:
    ledState[0]=true;
    ledState[1]=true;
    ledState[2]=false;
    break;
  case 3:
    ledState[0]=true;
    ledState[1]=true;
    ledState[2]=true;
    break;
  }

  for (int i=0;i<3;i++) {               // Updates LED's
    digitalWrite(leds[i], ledState[i]);
  }

  //recieve MIDI messages
  if (!debugging) {
    usbMIDI.read();
  }
int topbanks[4]= {[color=#222222][/color]
  18, 19, 20, 21[color=#222222][/color]
};

defines a variable.
You do not need to redefine it

int topbanks[4];               // Save Topbutton CC Values

is redefining it and is what is causing your error. "Saving" a variable will give a error. It is already saved as long as it has been declared.

just looking at the part of your code which sends pot or fader movements ONLY when the values change. You are on the right lines with: -

if (temp!=faderVal*)*
which obviously would mean that if the new value is different to the stored value then send message. however, if you have any trouble with noisy pots or faders (which is very common) then the slight fluctuations caused by the noise will result in data being send more than you want it to. Grumpy_mike showed me this approach a few weeks ago and it works a lot better: -
if( abs(temp - faderVal*) > 4) {*
so what this means is it will subtract 'faderVal*' from 'temp' and then if the result is less than 4 it won't send data but if it is above 4 it will begin to transmit. This gives you a noise margin. And what's nice is that if you increase the value of '< 4' you increase the noise immunity but the further you increase the lower the resolution of the sensor becomes.*
ANyway... keep posting your results as I'm working on a very similar project and it's good to exchange ideas. Good luck

Hi, did you do it?