Hi all, first post here. I'm very new to Arduino and I've built my first midi controller that I'm using to change certain parameters in UAD Console using the UA Midi Control app as middleware since Console does not read MIDI on its own. The box I've built has two separate yet identical sets of controls to control parameters on two separate channel strips for two separate microphones. It seems to me that a more ergonomic solution would be to have just one set of physical controls that I can switch from channel strip to channel strip by changing the midi channel my controller box is sending info to. That way all the controls for the first mic can be on midi channel 1, on mic 2 controls on midi channel 2. So, my question is how do I integrate a button that would change midi channels from 1 to 2 or 2 back to 1?
I'm using this code derived from MusicoNerd below:
/*
// If using with ATmega328 - Uno, Mega, Nano...
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
*/
// If using with ATmega32U4 - Micro, Pro Micro, Leonardo...
#include "MIDIUSB.h" // Download it here: https://github.com/arduino-libraries/MIDIUSB
/////////////////////////////////////////////
// buttons
const int NButtons = 3; //*
const int buttonPin[NButtons] = {2,3,4}; //* the number of the pushbutton pins in the desired not order
int buttonCState[NButtons] = {0}; // stores the button current value
int buttonPState[NButtons] = {0}; // stores the button previous value
//byte pin13index = 3; // put the index of the pin 13 in the buttonPin[] if you are using it, if not, comment lines 68-70
/////////////////////////////////////////////
// debounce
unsigned long lastDebounceTime[NButtons] = {0}; // the last time the output pin was toggled
unsigned long debounceDelay = 13; //* the debounce time; increase if the output flickers
/////////////////////////////////////////////
// potentiometers
const int NPots = 5; //*
int potPin[NPots] = {A0,A1,A2,A3,A5}; //* Pin where the potentiometer is
int potCState[NPots] = {0}; // Current state of the pot
int potPState[NPots] = {0}; // Previous state of the pot
int potVar = 0; // Difference between the current and previous state of the pot
int midiCState[NPots] = {0}; // Current state of the midi value
int midiPState[NPots] = {0}; // Previous state of the midi value
int TIMEOUT = 300; //* Amount of time the potentiometer will be read after it exceeds the varThreshold
int varThreshold = 10; //* Threshold for the potentiometer signal variation
boolean potMoving = true; // If the potentiometer is moving
unsigned long PTime[NPots] = {}; // Previously stored time
unsigned long timer[NPots] = {}; // Stores the time that has elapsed since the timer was reset
/////////////////////////////////////////////
byte midiCh = 1; //* MIDI channel to be used
byte note = 1; //* Lowest note to be used
byte cc = 7; //* Lowest MIDI CC to be used
void setup() {
//Serial.begin(115200); // use if using with ATmega328 (uno, mega, nano...)
for (int i = 0; i < NButtons; i++) {
pinMode(buttonPin[i], INPUT_PULLUP);
}
//pinMode(buttonPin[3], INPUT); //pin 13
}
void loop() {
buttons();
potentiometers();
}
/////////////////////////////////////////////
// BUTTONS
void buttons() {
for (int i = 0; i < NButtons; i++) {
buttonCState[i] = digitalRead(buttonPin[i]);
/*
// Comment this if you are not using pin 13...
if (i == pin13index) {
buttonCState[i] = !buttonCState[i]; //inverts pin 13 because it has a pull down resistor instead of a pull up
}
// ...until here
*/
if ((millis() - lastDebounceTime[i]) > debounceDelay) {
if (buttonPState[i] != buttonCState[i]) {
lastDebounceTime[i] = millis();
if (buttonCState[i] == LOW) {
// use if using with ATmega328 (uno, mega, nano...)
//MIDI.sendNoteOn(note + i, 127, midiCh); // note, velocity, channel
// use if using with ATmega32U4 (micro, pro micro, leonardo...)
noteOn(midiCh, note + i, 127); // channel, note, velocity
MidiUSB.flush();
// Serial.print("button on >> ");
// Serial.println(i);
}
else {
// use if using with ATmega328 (uno, mega, nano...)
//MIDI.sendNoteOn(note + i, 0, midiCh); // note, velocity, channel
// use if using with ATmega32U4 (micro, pro micro, leonardo...)
noteOn(midiCh, note + i, 0); // channel, note, velocity
MidiUSB.flush();
// Serial.print("button off >> ");
// Serial.println(i);
}
buttonPState[i] = buttonCState[i];
}
}
}
}
/////////////////////////////////////////////
// POTENTIOMETERS
void potentiometers() {
for (int i = 0; i < NPots; i++) { // Loops through all the potentiometers
potCState[i] = analogRead(potPin[i]); // Reads the pot and stores it in the potCState variable
midiCState[i] = map(potCState[i], 0, 1023, 0, 127); // Maps the reading of the potCState to a value usable in midi
potVar = abs(potCState[i] - potPState[i]); // Calculates the absolute value between the difference between the current and previous state of the pot
if (potVar > varThreshold) { // Opens the gate if the potentiometer variation is greater than the threshold
PTime[i] = millis(); // Stores the previous time
}
timer[i] = millis() - PTime[i]; // Resets the timer 11000 - 11000 = 0ms
if (timer[i] < TIMEOUT) { // If the timer is less than the maximum allowed time it means that the potentiometer is still moving
potMoving = true;
}
else {
potMoving = false;
}
if (potMoving == true) { // If the potentiometer is still moving, send the change control
if (midiPState[i] != midiCState[i]) {
// use if using with ATmega328 (uno, mega, nano...)
//MIDI.sendControlChange(cc+i, midiCState[i], midiCh);
// use if using with ATmega32U4 (micro, pro micro, leonardo...)
controlChange(midiCh, cc + i, midiCState[i]); // manda control change (channel, CC, value)
MidiUSB.flush();
//Serial.println(midiCState);
potPState[i] = potCState[i]; // Stores the current reading of the potentiometer to compare with the next
midiPState[i] = midiCState[i];
}
}
}
}
/////////////////////////////////////////////
// Arduino (pro)micro midi functions MIDIUSB Library
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);
}
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}