USB Midi Foot Controller Help

Just some quick info on my knowledge.

In the past I have built several button boxes using button matrix,encoders,and pots for gaming and various other programs. Ive only used the Nano once, several Pro Micro's and a UNO once for force feedback for my racing sim setup.
I have not ever done the programming side of Arduino, I used MMJOY as it was adequate for my needs.

Now what Im trying to do is make a midi foot controller to use with my DAW and Amp/pedal sims for guitar thru USB.

My plans are to 10 momentary foot switches with LEDS only for 7 of the switches to show activated switch or off and 1 pot for an expression pedal.I plan to also use the Pro Micro since I already have it extra. Plus another on/off/on switch for switching layers.(used the way Ill show in example)

But for now Im having trouble trying to understand how I need to wire all this up with the amount of controls I want, meaning Im not sure if I have enough inputs. Trying to keep it budget since so far I already have the parts from the parts box so as of now cost is $0.

I was looking at this example from github,easy to understand diagrams and such but like I said cant figure out how to count for the extra buttons I was wanting to add.

Please some info,links any help would be appreciative.

Example Diagram from github: Also github link for the what I want but just more switches than the author is using.

Well first off do you know you can use the analogue inputs as normal digital pins. Just use A0 and so on in the digitalRead and write and in the pinMode call.

I have a MIDI foot switch project at:- http://www.thebox.myzen.co.uk/Hardware/MIDI_Footsteps.html

That uses an analogue multiplexer to read many sensors.

The thing is you have two problems:-

  1. How to get more inputs
  2. How to use those inputs for MIDI.

So search first for how to get more inputs.
There are several solutions to this:-

  1. Using one or more shift registers for more inputs. This is like the more normal using shift registers for more outputs but uses a different type of shift register.

  2. Multiplex them. You can use either digital or analogue multiplexers to feed many inputs into one input, digital or analogue. These multiplexers have address lines with control what input gets switched to the output.

  3. Port expanders. Chips like the MSP23017 and MSP23S17 can give you 16 extra input / output pins. MCP23017 - i2c 16 input/output port expander : ID 732 : $6.95 : Adafruit Industries, Unique & fun DIY electronics and kits
    Or you can buy boards with these already on:-
    Expansion Board

easy to understand diagrams

What you posted is not a circuit diagram or schematic. It is physical layout diagram, otherwise known as a piece of Fritzing crap. They are not much use apart from blindly making a copy of something without thinking at all. Learning to read real schematics will serve you well in this game.

In the physical layout diagram you posted you will find that 10K will make the LEDs look dim and using 0.5W resistors is extreme overkill, normal quarter watt or eighth watt will be way more than you need. So it is best to assume the people who produced that, don't know what they are doing.

Thanks for the info.
I will be looking into your info more.

As for the diagram and link,i posted it as to show that it is how i wanted my setup to work. Since im very new to the music abilities of arduino it was simple to get an idea for me to know how and what i might need to do. As i mentioned i have no experience programming arduinos. I have made some fairly extensive button and control boxes but i used mmjoy as its a graphical interface for that purpose to use for flight sims etc.

But after looking at my project a bit more, i realised that i dont need as many buttons as mentioned above.

The project is actually only 8 switches of which only 7 will have led and 1 pot. For some reason i kept counting 2 extra switches that im not using.
So if im looking at things correct just the single pro micro would be enough.

As far as what you posted about leds and resistors,yes i am aware as i have a stock pile of the 1/4 watt that i use in other projects.

As for schematics i have an ok understanding of them since i use them normally for my other projects. Im just trying to keep my current one simple,not overly complicated so i thought the linked project would be good start.

Im just hobbiest and i learn what i need to as i work on whatever project i may be attempting,so far i havent failed at any with very minimal help from others,just read alot on what i need.

Im sure ill have another question as i plan this out more but i do like to figure things out for myself, its the way my dad taught me auto mechanics.

Also please forgive my reply grammar, im using a tablet to reply with at the moment.

Ok I basically built the project mentioned in the OP except instead of 5 switches/leds Im using 7,everything works.

But I have 1 issue for now that I cant seem to figure out,well maybe 2 but one thing at a time.

All the switches seem to function as intended but I cant figure out how to make the led's light when I press a switch, it will only flash once with each press. That goes for all 7 switches/led's.

All I'm wanting this foot controller to do is to be used as a foot controller for amp changes and effects on/off and leave the corresponding led to each switch lit or off depending on state. Some of the software I will use this with would be Reaper DAW,Amplitube,Bias Amp/FX and so forth.

Is what Im wanting the led's to do possible? Remember I am just now learning the coding part of Arduino.

/*
Arduino USB MIDI FootSwitch
by Hecsall (https://github.com/Hecsall)
*/

// https://www.arduino.cc/en/Reference/MIDIUSB
#include "MIDIUSB.h"
#include "variables.h"

// Utility functions

// Event type is hard-coded (0x09 = note on, 0x08 = note off).
// First parameter is the MIDI channel, combined with the note-on/note-off.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Second parameter (pitch) is the note number (48 = middle C).
// Third parameter is the velocity (0 -> 127, 0 = no_sound, 64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
}

// Event type hard-coded (0x0B = control change, aka "MIDI CC").
// First parameter is the channel (0-15), combined with the event type.
// Second parameter is the "control change" number (0-119, see top link to midi.org).
// Third parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
    midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
    MidiUSB.sendMIDI(event);
}

// BPM Counter
void initBPM()
{
    midiEventPacket_t rx;
    do {
        rx = MidiUSB.read();
        //Count pulses and send note
        if (rx.byte1 == 0xF8)
        {
            ++ppqn;
            if (ppqn == 24)
            {
                digitalWrite(10, HIGH);
                delay(80);
                digitalWrite(10, LOW);
                ppqn = 0;
            };
        }
        //Clock start byte
    } while (rx.header != 0);
}

// Button in "Push" mode
void handlePushButton(byte i)
{
    if (digitalRead(button_pins[i]) == LOW && button_states[i] == false)
    {
        controlChange(0, button_layers[current_layer][i], 127);
        MidiUSB.flush();
        button_states[i] = true;
        digitalWrite(led_pins[i], HIGH); // Turn the LED on
        led_states[i] = true;
        delay(15);
    }
    else if (digitalRead(button_pins[i]) == HIGH && button_states[i] == true)
    {
        controlChange(0, button_layers[current_layer][i], 0);
        MidiUSB.flush();
        button_states[i] = false;
        digitalWrite(led_pins[i], LOW); // Turn the LED off
        led_states[i] = false;
        delay(15);
    }
}

// Button in "Toggle" mode
void handleToggleButton(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        if (buttonState == LOW && button_states[i] == false)
        {
            controlChange(0, button_layers[current_layer][i], 127);
            MidiUSB.flush();
            button_states[i] = true;
            digitalWrite(led_pins[i], HIGH); // Turn the LED on
            led_states[i] = true;
        }
        else if (buttonState == LOW && button_states[i] == true)
        {
            controlChange(0, button_layers[current_layer][i], 0);
            MidiUSB.flush();
            button_states[i] = false;
            digitalWrite(led_pins[i], LOW); // Turn the LED off
            led_states[i] = false;
        }
        delay(100);
    }
    lastButtonState = buttonState;
}

// Button "Change" mode
void handleChangeMode(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        // Note: only layer 1 (switch OFF) can be customized
        if (buttonState == LOW && button_modes[1][i] == 0 && millis() - time > debounce)
        {
            button_modes[1][i] = 1;
            digitalWrite(led_pins[i], HIGH); // Turn the LED on
            led_states[i] = true;
            time = millis();
        }
        else if (buttonState == LOW && button_modes[1][i] == 1 && millis() - time > debounce)
        {
            button_modes[1][i] = 0;
            digitalWrite(led_pins[i], LOW); // Turn the LED off
            led_states[i] = false;
            time = millis();
        }
        delay(50);
    }
    lastButtonState = buttonState;
}

// Turn off all LEDs
void poweroffLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        digitalWrite(led_pins[i], LOW);
        led_states[i] = false;
    }
}

// Turn on all the current mode LEDs
void showModeLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        if (button_modes[1][i] == 1)
        {
            digitalWrite(led_pins[i], HIGH);
            led_states[i] = true;
        }
    }
}

// Check and set which layer is active
void setLayer()
{
    if (digitalRead(switch_pins[0]) == LOW && digitalRead(switch_pins[1]) == HIGH && current_layer != 0)
    {
        current_layer = 0; // Switch UP
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == HIGH && current_layer != 1)
    {
        current_layer = 1; // Switch OFF
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == LOW && current_layer != 2)
    {
        current_layer = 2; // Switch DOWN
    }
}

// Actual logic
void setup()
{
    Serial.begin(115200);
    // Button Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(button_pins[i], INPUT_PULLUP);
    }
    // LED Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(led_pins[i], OUTPUT);
    }
    // Switch Pins
    for (uint8_t i = 0; i < 2; i++)
    {
        pinMode(switch_pins[i], INPUT_PULLUP);
    }
    // Set currently active Layer
    setLayer();
}

void loop()
{
    initBPM(); // Blinking BPM LED - needs to be enabled in your DAW
    setLayer(); // Set which Layer we are using

    // Button operations based on current_layer
    for (uint8_t i = 0; i < 7; i++)
    {
        if (current_layer < 2) // Only layers 0 and 1 are normal operational layers
        {
            poweroffLeds();
            if (button_modes[current_layer][i] == 0)
            {
                handlePushButton(i);
            }
            else if (button_modes[current_layer][i] == 1)
            {
                handleToggleButton(i);
            }
        }
        else if (current_layer == 2) // Layer 2 is the "settings" layer
        {
            showModeLeds();
            handleChangeMode(i);
        }
    }
}

Also my variables file

Variables

/*
Arduino USB MIDI FootSwitch
by Hecsall (https://github.com/Hecsall)
*/

// https://www.arduino.cc/en/Reference/MIDIUSB
#include "MIDIUSB.h"
#include "variables.h"

// Utility functions

// Event type is hard-coded (0x09 = note on, 0x08 = note off).
// First parameter is the MIDI channel, combined with the note-on/note-off.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Second parameter (pitch) is the note number (48 = middle C).
// Third parameter is the velocity (0 -> 127, 0 = no_sound, 64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
}

// Event type hard-coded (0x0B = control change, aka "MIDI CC").
// First parameter is the channel (0-15), combined with the event type.
// Second parameter is the "control change" number (0-119, see top link to midi.org).
// Third parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
    midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
    MidiUSB.sendMIDI(event);
}

// BPM Counter
void initBPM()
{
    midiEventPacket_t rx;
    do {
        rx = MidiUSB.read();
        //Count pulses and send note
        if (rx.byte1 == 0xF8)
        {
            ++ppqn;
            if (ppqn == 24)
            {
                digitalWrite(10, HIGH);
                delay(80);
                digitalWrite(10, LOW);
                ppqn = 0;
            };
        }
        //Clock start byte
    } while (rx.header != 0);
}

// Button in "Push" mode
void handlePushButton(byte i)
{
    if (digitalRead(button_pins[i]) == LOW && button_states[i] == false)
    {
        controlChange(0, button_layers[current_layer][i], 127);
        MidiUSB.flush();
        button_states[i] = true;
        digitalWrite(led_pins[i], HIGH); // Turn the LED on
        led_states[i] = true;
        delay(15);
    }
    else if (digitalRead(button_pins[i]) == HIGH && button_states[i] == true)
    {
        controlChange(0, button_layers[current_layer][i], 0);
        MidiUSB.flush();
        button_states[i] = false;
        digitalWrite(led_pins[i], LOW); // Turn the LED off
        led_states[i] = false;
        delay(15);
    }
}

// Button in "Toggle" mode
void handleToggleButton(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        if (buttonState == LOW && button_states[i] == false)
        {
            controlChange(0, button_layers[current_layer][i], 127);
            MidiUSB.flush();
            button_states[i] = true;
            digitalWrite(led_pins[i], HIGH); // Turn the LED on
            led_states[i] = true;
        }
        else if (buttonState == LOW && button_states[i] == true)
        {
            controlChange(0, button_layers[current_layer][i], 0);
            MidiUSB.flush();
            button_states[i] = false;
            digitalWrite(led_pins[i], LOW); // Turn the LED off
            led_states[i] = false;
        }
        delay(100);
    }
    lastButtonState = buttonState;
}

// Button "Change" mode
void handleChangeMode(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        // Note: only layer 1 (switch OFF) can be customized
        if (buttonState == LOW && button_modes[1][i] == 0 && millis() - time > debounce)
        {
            button_modes[1][i] = 1;
            digitalWrite(led_pins[i], HIGH); // Turn the LED on
            led_states[i] = true;
            time = millis();
        }
        else if (buttonState == LOW && button_modes[1][i] == 1 && millis() - time > debounce)
        {
            button_modes[1][i] = 0;
            digitalWrite(led_pins[i], LOW); // Turn the LED off
            led_states[i] = false;
            time = millis();
        }
        delay(50);
    }
    lastButtonState = buttonState;
}

// Turn off all LEDs
void poweroffLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        digitalWrite(led_pins[i], LOW);
        led_states[i] = false;
    }
}

// Turn on all the current mode LEDs
void showModeLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        if (button_modes[1][i] == 1)
        {
            digitalWrite(led_pins[i], HIGH);
            led_states[i] = true;
        }
    }
}

// Check and set which layer is active
void setLayer()
{
    if (digitalRead(switch_pins[0]) == LOW && digitalRead(switch_pins[1]) == HIGH && current_layer != 0)
    {
        current_layer = 0; // Switch UP
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == HIGH && current_layer != 1)
    {
        current_layer = 1; // Switch OFF
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == LOW && current_layer != 2)
    {
        current_layer = 2; // Switch DOWN
    }
}

// Actual logic
void setup()
{
    Serial.begin(115200);
    // Button Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(button_pins[i], INPUT_PULLUP);
    }
    // LED Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(led_pins[i], OUTPUT);
    }
    // Switch Pins
    for (uint8_t i = 0; i < 2; i++)
    {
        pinMode(switch_pins[i], INPUT_PULLUP);
    }
    // Set currently active Layer
    setLayer();
}

void loop()
{
    initBPM(); // Blinking BPM LED - needs to be enabled in your DAW
    setLayer(); // Set which Layer we are using

    // Button operations based on current_layer
    for (uint8_t i = 0; i < 7; i++)
    {
        if (current_layer < 2) // Only layers 0 and 1 are normal operational layers
        {
            poweroffLeds();
            if (button_modes[current_layer][i] == 0)
            {
                handlePushButton(i);
            }
            else if (button_modes[current_layer][i] == 1)
            {
                handleToggleButton(i);
            }
        }
        else if (current_layer == 2) // Layer 2 is the "settings" layer
        {
            showModeLeds();
            handleChangeMode(i);
        }
    }
}

Is what Im wanting the led's to do possible?

Yes.
Try replacing

 digitalWrite(led_pins[i], HIGH); // Turn the LED on

With

 digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on

And do exactly the same in the else if clause for turning the LED off.

I can’t fine the definition of the button_states array, it needs to be boolean to work.
When he told you on the GitHub page he was not a programmer he wasn’t joaking. It is best to try and learn from good code. The code seems to have the turning on and off of the LEDs in two places, the code and the so called variables file, this is utter madness, I have no idea why he did this. You need to make those changes in both places to be sure the right one is being used.

Grumpy_Mike:
Yes.
Try replacing

 digitalWrite(led_pins[i], HIGH); // Turn the LED on

With

 digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on

And do exactly the same in the else if clause for turning the LED off.

I can’t fine the definition of the button_states array, it needs to be boolean to work.
When he told you on the GitHub page he was not a programmer he wasn’t joaking. It is best to try and learn from good code.

Thanks for the help.

Just so im clear, anywhere its says what i have,replace with what you have said in all sections of code?

Once i get the leds working correct , then i have to figure out how to add and expression pedal and ill be set.
I have the pots wired to pro micro,just cant really figure out coding to add and where im suppose to put it in my current sketch.

Honestly i wouldnt know good from bad code. I was just wanting a basic foot controller to work with my music software,im no fan of coding.

Now ive built several projects but the are basically joysticks. Ive built from scratch a couple joysticks,throttle, a few button boxes, an led display that works simhub, and rumble motors to my racing pedals.
But i did all this using mmjoy2 of which is all graphical interface and really simplifies things,no coding.

Id rather just found a sketch that fit my needs but the current one is all i found.

All i want is usb midi foot controller with an expression pedal,7 buttons w/led on each,a shift switch to make the switches read another line of midi commands.

After my issues tonight with uploaded sketch connection issues im almost ready to give up and i never give up, drives my wife crazy...lol

I tried your suggestion for the leds, they didnt work at all afterwards. I might look into them more tomorrow.
But for now I want to figure out how to the expression pedal coded in of which I havent any idea yet.

But Im off to bed for now

Thanks for the help and anymore help.

If I were doing this, I would use the Control_Surface library. It would be pretty straightforward.

Only one part might be tricky:

All I'm wanting this foot controller to do is to be used as a foot controller for amp changes and effects on/off and leave the corresponding led to each switch lit or off depending on state. Some of the software I will use this with would be Reaper DAW,Amplitube,Bias Amp/FX and so forth.

This. Having the LED toggle when you click a switch is easy.
But do you want it to toggle if you change the state via Mouse, though? Of course you do. If you want it to follow the ~actual state~, not just if you toggle the switch.. then you got some twiddling to do, I think.

I tried your suggestion for the leds, they didnt work at all afterwards.

So what you should do on this forum is to post your latest code and say exactly what it did do. Then we can see if you got it right.

But for now I want to figure out how to the expression pedal coded in of which I havent any idea yet.

Almost trivial, read the pot and if it has changed since last time you read it then send out the reading divided by 8 to the appropriate CC channel number.

If I were doing this, I would use the Control_Surface library.

Maybe but that code is a lot more "software intense" requiring newcomers to know more software techniques than they normally do when asking these sorts of questions. In the end you give them advice about what to change but they don't actually learn anything and they are stuck in a dependent state. The whole point in answering questions here in my opinion is to teach something that can be built upon.

cameron206:
Only one part might be tricky:

This. Having the LED toggle when you click a switch is easy.
But do you want it to toggle if you change the state via Mouse, though? Of course you do. If you want it to follow the ~actual state~, not just if you toggle the switch.. then you got some twiddling to do, I think.

OK so that never really crossed my mind, something to think about but for me one thing at a time. I'm just starting to get some kind of grasp on this.

Grumpy_Mike:
So what you should do on this forum is to post your latest code and say exactly what it did do. Then we can see if you got it right.
Almost trivial, read the pot and if it has changed since last time you read it then send out the reading divided by 8 to the appropriate CC channel number.

Maybe but that code is a lot more "software intense" requiring newcomers to know more software techniques than they normally do when asking these sorts of questions. In the end you give them advice about what to change but they don't actually learn anything and they are stuck in a dependent state. The whole point in answering questions here in my opinion is to teach something that can be built upon.

Yes I realise now I should have posted the code here after my changes,I was tired and not really thinking to clearly which didnt help either.

I should have researched the software side more since I know nothing at all.Im more a hardware type and dont have much problems building things.

I may work on this some today but health issues keeping me down today.

Thank you everyone for all the help. Still not done but its close.

Grumpy_Mike:
The whole point in answering questions here in my opinion is to teach something that can be built upon.

I totally agree, in principal.
But I also feel the pain (being a non-coder myself), of facing a huge learning curve for something I might only do once or twice.

It was not until I'd made maybe 6 controllers that I felt like learning actual language :slight_smile:

But you are NOT wrong.

cameron206:
I totally agree, in principal.
But I also feel the pain (being a non-coder myself), of facing a huge learning curve for something I might only do once or twice.

It was not until I'd made maybe 6 controllers that I felt like learning actual language :slight_smile:

But you are NOT wrong.

Ok so you feel about the same as I do. Ive built alot of arduino game based controllers but didnt need to code anything,I am quiet comfortable with it.
But for this midi stuff it looks like coding is required and is the main reason I have put this off for so long since most likely this will just be a once or twice thing for me.

Now I looked into the Control Surface and a couple examples, to me it actually looks easier to use and get a handle on. I do much better when things are more straight forward.

As for this I have been looking for example code that will show me what I want so that I could implement it into my project. But most of the examples I have looked at are more a mixer type board.
Its my learning process, I look at examples that shows what I need then try to add/modify/learn for my needs.

I'm not asking anyone to sit and do the code for me, but I do have a question concerning Control Surface library:

what I want my pedal project to do is:
7 switches each with own led. leds to light on/off depending if the switch is on/off.
Have 6 of those switches bankable.
Have 1 expression pedal.
Be USB

Now Ive seen the array setups and such in the code and thats why this looks much easier to code and edit.

I read that I would need the midiusb control surface library, correct?

could I either get a basic generic code example or a link to one that will show those basic things I mention so can try learning this? Remember I am a total noob so I dont know all the places to look or really what I'm looking at,I barely understand this coding stuff.

Sorry for long post.

Grumpy_Mike:
Yes.
Try replacing

 digitalWrite(led_pins[i], HIGH); // Turn the LED on

With

 digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on

And do exactly the same in the else if clause for turning the LED off.

I can’t fine the definition of the button_states array, it needs to be boolean to work.
When he told you on the GitHub page he was not a programmer he wasn’t joaking. It is best to try and learn from good code. The code seems to have the turning on and off of the LEDs in two places, the code and the so called variables file, this is utter madness, I have no idea why he did this. You need to make those changes in both places to be sure the right one is being used.

Ok so I tried what you said again. I seem to be missing something here.
All lights still work,but they just give a single flash with each button push.

Also only 1 switch only lights every other switch push but in my amp sim software when testing it it reads every switch push.

/*
Arduino USB MIDI FootSwitch
by Hecsall (https://github.com/Hecsall)
*/

// https://www.arduino.cc/en/Reference/MIDIUSB
#include "MIDIUSB.h"
#include "variables.h"

// Utility functions

// Event type is hard-coded (0x09 = note on, 0x08 = note off).
// First parameter is the MIDI channel, combined with the note-on/note-off.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Second parameter (pitch) is the note number (48 = middle C).
// Third parameter is the velocity (0 -> 127, 0 = no_sound, 64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity)
{
    midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
    MidiUSB.sendMIDI(noteOff);
}

// Event type hard-coded (0x0B = control change, aka "MIDI CC").
// First parameter is the channel (0-15), combined with the event type.
// Second parameter is the "control change" number (0-119, see top link to midi.org).
// Third parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value)
{
    midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
    MidiUSB.sendMIDI(event);
}



// Button in "Push" mode
void handlePushButton(byte i)
{
    if (digitalRead(button_pins[i]) == LOW && button_states[i] == false)
    {
        controlChange(0, button_layers[current_layer][i], 127);
        MidiUSB.flush();
        button_states[i] = true;
        digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on
        led_states[i] = true;
        delay(15);
    }
    else if (digitalRead(button_pins[i]) == HIGH && button_states[i] == true)
    {
        controlChange(0, button_layers[current_layer][i], 0);
        MidiUSB.flush();
        button_states[i] = false;
        digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED off
        led_states[i] = false;
        delay(15);
    }
}

// Button in "Toggle" mode
void handleToggleButton(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        if (buttonState == LOW && button_states[i] == false)
        {
            controlChange(0, button_layers[current_layer][i], 127);
            MidiUSB.flush();
            button_states[i] = true;
            digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on
            led_states[i] = true;
        }
        else if (buttonState == LOW && button_states[i] == true)
        {
            controlChange(0, button_layers[current_layer][i], 0);
            MidiUSB.flush();
            button_states[i] = false;
            digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED off
            led_states[i] = false;
        }
        delay(100);
    }
    lastButtonState = buttonState;
}

// Button "Change" mode
void handleChangeMode(byte i)
{
    buttonState = digitalRead(button_pins[i]);
    if (buttonState != lastButtonState){
        // Note: only layer 1 (switch OFF) can be customized
        if (buttonState == LOW && button_modes[1][i] == 0 && millis() - time > debounce)
        {
            button_modes[1][i] = 1;
            digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED on
            led_states[i] = true;
            time = millis();
        }
        else if (buttonState == LOW && button_modes[1][i] == 1 && millis() - time > debounce)
        {
            button_modes[1][i] = 0;
            digitalWrite(led_pins[i], ! button_states[i]); // Turn the LED off
            led_states[i] = false;
            time = millis();
        }
        delay(50);
    }
    lastButtonState = buttonState;
}

// Turn off all LEDs
void poweroffLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        digitalWrite(led_pins[i], LOW);
        led_states[i] = false;
    }
}

// Turn on all the current mode LEDs
void showModeLeds()
{
    for (uint8_t i = 0; i < 7; i++)
    {
        if (button_modes[1][i] == 1)
        {
            digitalWrite(led_pins[i], HIGH);
            led_states[i] = true;
        }
    }
}

// Check and set which layer is active
void setLayer()
{
    if (digitalRead(switch_pins[0]) == LOW && digitalRead(switch_pins[1]) == HIGH && current_layer != 0)
    {
        current_layer = 0; // Switch UP
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == HIGH && current_layer != 1)
    {
        current_layer = 1; // Switch OFF
    }
    else if (digitalRead(switch_pins[0]) == HIGH && digitalRead(switch_pins[1]) == LOW && current_layer != 2)
    {
        current_layer = 2; // Switch DOWN
    }
}

// Actual logic
void setup()
{
    Serial.begin(115200);
    // Button Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(button_pins[i], INPUT_PULLUP);
    }
    // LED Pins
    for (uint8_t i = 0; i < 7; i++)
    {
        pinMode(led_pins[i], OUTPUT);
    }
    // Switch Pins
    for (uint8_t i = 0; i < 2; i++)
    {
        pinMode(switch_pins[i], INPUT_PULLUP);
    }
    // Set currently active Layer
    setLayer();
}

void loop()
{
    
    // Button operations based on current_layer
    for (uint8_t i = 0; i < 7; i++)
    {
        if (current_layer < 2) // Only layers 0 and 1 are normal operational layers
        {
            poweroffLeds();
            if (button_modes[current_layer][i] == 0)
            {
                handlePushButton(i);
            }
            else if (button_modes[current_layer][i] == 1)
            {
                handleToggleButton(i);
            }
        }
        else if (current_layer == 2) // Layer 2 is the "settings" layer
        {
            showModeLeds();
            handleChangeMode(i);
        }
    }
}

Also I cant find out how to add the expression pedal in the code, no idea how to start.
I really just want it to function as a wah control but Im lost here.
I have looked at examples for other projects but not even sure if it will work or were I would put the code.

I seem to be missing something here.

Did you make the same changes in the variables.h file as well as this code?
You need to post both files due to the absoloutly moronic way this code is written.

EDIT - OK now I am a bit cross. In reply #4 you said:-

Also my variables file

But this was not your variables.h file was it? It was your main file again. I though you were telling me the truth so I assumed that the author had done something absoloutly mad. It now appears that he was not being crazy here.

What you seem to have done is to change the number of LEDs and push buttons you have without updating the size of the arrays in the variables.h file. This means that you are addressing arrays outside the declared bounds and reading and writing at memory locations that have been allocated to something else. This will cause all sorts of strange behavior that is not symptomatic of what is going wrong.

So change the variables.h file to make these arrays bigger.
Note for single variables you don't need to do things like this:-

int button_states[5] = {false, false, false, false, false};

you can use:-

int button_states[] = {false, false, false, false, false, false, false};

and the array will be made big enough to hold all the variables.
In the case of two dimensional arrays you only have to specify the first dimension.

So make these changes and post back both files and say what happens.

Also I cant find out how to add the expression pedal in the code

So I told you how to do this in reply#9. If you do not understand something about that explanation then please ask specifically about what you don't understand.

Ok I made those changes long ago in the variables.h file.
Later when Im home I'll post the files.

So in your reply about the pedal, I will look at it again.

Thanks

NervusTwitch:
OK so that never really crossed my mind, something to think about but for me one thing at a time. I'm just starting to get some kind of grasp on this.

If I were you, I would think about this before you go much further... because it fundamentally changes how you handle the LEDs.

And truly.. outside of the LEDs, your code is trivial. Look at the 'Trasposer' example in the control surface library if you are sending notes.

IN re: the LEDS.. if you want it to reflect the STATE of a condition in your DAW.. you gotta get into callbacks. Maybe emulate a known controller. And this will be very DAW specific.

variables.h file.
I can post the main file but since my post count is low the forum makes me wait a few minutes to post again.
As for what I dont understand about adding the expression pedal, I dont understand any of that. I dont know how to even start to add it in,where or anything. I have looked at a few others projects and tried to figure out what to do but none of it worked,thru out a ton of errors.

Just so I dont seem to dense here...lol I need to clarify. In another post I talked about health issues,well that severe nerve damage that affects everything. That includes brain function and memory. Makes it hard for me at times to absorb and learn new things.

I just dont want to come off as being difficult or not willing.

/ Arduino Pins
const byte button_pins[7] = {1, 2, 3, 4, 5, 6, 7};   // Pins where buttons are connected
const byte switch_pins[2] = {8, 9};            // Pins where the switch is connected
const byte led_pins[7] = {10, 16, 14, 15, 18, 19, 20}; // Pins where LEDs are connected

// Layer: this is the currently select layer (changed by the switch)g
byte current_layer; // 0 = switch up, 1 = switch off, 2 = switch down

// CC values are the numbers in the decimal column of this table
// https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2

const int button_layers[2][7] = {
    /*
    Layer 0 (Switch Up)
    ,----------------------,
    |  49 |  50 | 51  |    |
    |----------------------|
    |  80 |  81 |  82 | 85 |
    `----------------------`
    */
    {
        49, 50, 51,
        80, 81, 82, 85},

    /*
    Layer 1 (Switch Off)
    ,---------------------,
    |  16 |  17 | 18 |    |
    |---------------------|
    |  19 |  20 | 21 | 48 |
    `---------------------`
    */
    {
        16, 17, 18, 
        19, 20, 21, 48}
};

// Button modes: 0 = push button, 1 = toggle button
byte button_modes[2][7] = {
    // Layer 0 (Switch Up)
    {0, 0, 0, 0, 0, 0, 0},

    // Layer 1 (Switch Off)
    {0, 0, 0, 0, 0, 0, 0}
};

int buttonState = 0; 
int lastButtonState = 0; 

// Button states: true = button ON, false = button OFF
int button_states[7] = {false, false, false, false, false, false, false};

long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

// LED states
bool led_states[7] = {false, false, false, false, false, false, false};

byte ppqn = 0; // "Pulse Per Quarter Note"