Midi Controller help needed, "On" and "Off" preset

musicgit

Member
Hi I am new in the forum and new to coding. Bought a 6 button midi controller and was trying to code. Manage to add 2 different midi channel into the code.

The mid controller works in way that when I switch on button 1, I need to off button 1 in order not the mess up the PC number.

How can I switch on a random preset (e.g. button 3) without needing to off it.

For e.g. When I switch to button 4, button 3 will off it and button 4 preset will come right up.

Any help appreciated.

Thanks!

Code:
//************LIBRARIES USED**************
// 'include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle'
#include <MIDI.h>
#include <Bounce.h> 
//'usbMIDI.h library is added automatically when code is compiled as a MIDI device'

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);

// ******CONSTANT VALUES******** 


//********** PIN DEFINITIONS
const int D_PINS = 5; // number of Digital PINS in main group (excl tap/bank)
const int DIGITAL_PINS[D_PINS] = {0,1,2,3,4}; // pins to switchs 
const int RED_LED_PINS[D_PINS] = {6,22,10,17,19};
const int GREEN_LED_PINS[D_PINS] = {24,9,16,18,20};
const int MODE_TAP_PIN = 5;  // momentary switch to set tempo and select bank
const int MODE_TAP_LED_PIN = 15; // pin to LED for tempo/bank indicator

//Alan
const int RED_LED_PINS1[D_PINS] = {6}; // pins to switchs RED
const int RED_LED_PINS2[D_PINS] = {22}; // pins to switchs RED
const int RED_LED_PINS3[D_PINS] = {10}; // pins to switchs RED
const int RED_LED_PINS4[D_PINS] = {17}; // pins to switchs RED
const int RED_LED_PINS5[D_PINS] = {19}; // pins to switchs RED

const int GREEN_LED_PINS6[D_PINS] = {24}; // pins to switchs GREEN
const int GREEN_LED_PINS7[D_PINS] = {9}; // pins to switchs GREEN
const int GREEN_LED_PINS8[D_PINS] = {16}; // pins to switchs GREEN
const int GREEN_LED_PINS9[D_PINS] = {18}; // pins to switchs GREEN
const int GREEN_LED_PINS10[D_PINS] = {20}; // pins to switchs GREEN

const int DIGITAL_PINS0[D_PINS] = {0}; // pins to switchs 
const int DIGITAL_PINS1[D_PINS] = {1}; // pins to switchs 
const int DIGITAL_PINS2[D_PINS] = {2}; // pins to switchs 
const int DIGITAL_PINS3[D_PINS] = {3}; // pins to switchs 
const int DIGITAL_PINS4[D_PINS] = {4}; // pins to switchs 



       //********** MIDI DEFINITIONS*************
// MODIFY THIS SECTION TO CUSTOMISE YOUR MIDISTOMP SIX 

const int firstchannel = 1; // MIDI channel for USB MIDI
const int secondchannel = 2; // MIDI channel for TRS MIDI
const int thirdchannel = 3; // MIDI channel for TRS MIDI

const int MODE_COUNT = 2; // number of rows of banks
const int MODE_COUNT2 = 2; // number of rows of banks

//CC configuration matrix!! TIMELINE
const int MIDI_PC_NUMS[MODE_COUNT][D_PINS] = { //rows are banks up to MODE_COUNT
    {60,61,62,63,64},
    {65,66,67,68,69}
};

// BIGSKY
const int MIDI_PC_NUMS2[MODE_COUNT2][D_PINS] = { //rows are banks up to MODE_COUNT
    {60,60,62,63,64},
    {60,60,60,60,60}
};
const int TAP_CC = 93;

//const int TAP_CC_DOWN = 80+82;
//const int TAP_CC_UP = 82+81;

const int ON_Value = 127; // note-one velocity sent from buttons (should be 65 to  127)


//********** PHYSICAL DEFINITIONS 
const int BOUNCE_TIME = 30; // 5 ms is usually sufficient
const int modeThreshold = 800; // how long to hold before mode changes
const int flashOnTime = 150; // how long flashed LED is on
const int flashOffTime = 250; // how long flashed LED is off
const bool LED_ON = LOW; // LOW for active LOW wiring
const bool LED_OFF = HIGH; // HIGH for active LOW wiring
const int onClocks = 4; // number of clock messages with LED on for tempo flash
const int waitflash = 2; // number of dark flash cylces after bank change before tempo flash resumes

//******VARIABLES***********
// a data array to remember the current state of each switch
boolean state[MODE_COUNT][D_PINS];
elapsedMillis modeTimer,flashTimer;
boolean modeSelectActive = false;
int bank = 0 ; 
int flashcount= (-1*waitflash); // default is effective sequence stop of flash counter
int shiftUp; // keeps track of whether the mode change needs to be handled (true) or was (false)
int modeLED; // keeps track of whether LED is on without testing it..
int ClockCount; // for tempo tracking
boolean tempoFlashOn = true;// tempo flash defaults to on

//************INITIALIZE LIBRARY OBJECTS**************

// initialize the bounce objects 
Bounce digital[] =   {
    Bounce(DIGITAL_PINS[0],BOUNCE_TIME), 
    Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
    Bounce(DIGITAL_PINS[2], BOUNCE_TIME),
    Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
    Bounce(DIGITAL_PINS[4], BOUNCE_TIME)
}; 
Bounce modeTap = Bounce(MODE_TAP_PIN, BOUNCE_TIME);

//************SETUP**************
void setup() {
  MIDI.begin(MIDI_CHANNEL_OMNI);
  
  //'set a handle for returning control change messages'
  usbMIDI.setHandleProgramChange(OnProgramChange);
  usbMIDI.setHandleSongPosition(onSongPosition);
  usbMIDI.setHandleClock(onClock);
  usbMIDI.setHandleStart(onStart);
  //'loop to configure input pins and internal pullup resisters for digital section'
  for (int i=0;i<D_PINS;i++){
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
    pinMode(RED_LED_PINS[i], OUTPUT);
    pinMode(GREEN_LED_PINS[i], OUTPUT);
  }
  pinMode(MODE_TAP_PIN, INPUT_PULLUP);
  pinMode(MODE_TAP_LED_PIN, OUTPUT);
  digitalWrite(MODE_TAP_LED_PIN, LED_OFF);

  for (int i=0;i<D_PINS;i++){
    digitalWrite(GREEN_LED_PINS[i], LED_OFF);   // - GREEN OFF
    digitalWrite(RED_LED_PINS[i], LED_ON);   // - RED ON
  }
}

//************LOOP**************
void loop() {
  getMain();
  getModeTap();
  flasher();
  while (usbMIDI.read()) {
    //' controllers must call .read() to keep the queue clear even if they are not responding to MIDI'
  }
    while (MIDI.read()){

  }
}


//************DIGITAL SECTION**************
void getMain(){
  for (int i=0;i<D_PINS;i++){
    digital[i].update();
    if (digital[i].fallingEdge() || digital[i].risingEdge() ) {
      if (state[bank][i]) {
        usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel); 

                MIDI.sendProgramChange(MIDI_PC_NUMS2[bank][i], thirdchannel); 

       digitalWrite(RED_LED_PINS[i], LED_ON);
              digitalWrite(GREEN_LED_PINS[i], LED_OFF);

      }else {
       usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
        MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel);  

                 MIDI.sendProgramChange(MIDI_PC_NUMS2[bank][i], thirdchannel); 

        digitalWrite(RED_LED_PINS[i], LED_OFF);
               digitalWrite(GREEN_LED_PINS[i], LED_ON);

      }
      state[bank][i] = !state[bank][i] ;

    }
  }
}



//************MODE/TAP SECTION**************
void getModeTap(){
  modeTap.update();
  if (modeTap.fallingEdge()) {
    usbMIDI.sendControlChange(TAP_CC, ON_Value, firstchannel);
    MIDI.sendControlChange(TAP_CC, ON_Value, secondchannel); 
    modeTimer = 0;
    shiftUp = true;
    tempoFlashOn = false; 
    flashcount = 0; // is this error or magic?
    Serial.println("suspend tempo on tap");
  }    
  if (modeTap.risingEdge()){
    shiftUp = false;
    if (modeTimer<modeThreshold){
      tempoFlashOn = true; 
    Serial.println("resume tempo no mode change");
    }
  }
  if (modeTimer>modeThreshold && shiftUp) {
    shiftUp = false;
    bank++;
    bank = bank%MODE_COUNT;
    for (int i = 0; i < D_PINS ; i++){
      digitalWrite(GREEN_LED_PINS[i], !state[bank][i]);
      digitalWrite(RED_LED_PINS[i], state[bank][i]); 
    }
    // set counter of flashes 'owed' -- count them down after main part
    flashcount = bank + 1;
    flashTimer = 0 ; // is this needed?
  }
}

void flasher(){
  if (flashcount>= -1*waitflash){
    if (flashcount> 0){
      if (flashTimer>(flashOnTime+flashOffTime)){ 
        flashcount-- ;// decrement flashcount
        flashTimer = 0;
        if (modeLED){
          modeLED = false;
          digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
        }
      }else{
        if (modeLED == false && flashTimer>flashOnTime){
          modeLED = true;
          digitalWrite(MODE_TAP_LED_PIN, LED_ON);
        }
      }
    }else{
      if (flashTimer>(flashOnTime+flashOffTime)){ 
        flashcount-- ;// decrement flashcount
        flashTimer = 0;
      }
    }
  }else{
    if (!tempoFlashOn){
      tempoFlashOn = true;
      Serial.println(flashcount);
      Serial.println("resume tempo after bank select");
    }
  }
}

void OnProgramChange(byte rcvChannel, byte controller, byte value) {
  if (rcvChannel == firstchannel){
    for (int i = 0; i < D_PINS ; i++){
      if (MIDI_PC_NUMS[bank][i] == controller) {
        if (value >= 64) {
          digitalWrite(GREEN_LED_PINS[i], LED_ON);
          digitalWrite(RED_LED_PINS[i], LED_OFF); //'receiving >64 turns green on and red off'
          state[bank][i] = true;
        }else{
          digitalWrite(GREEN_LED_PINS[i], LED_OFF);
          digitalWrite(RED_LED_PINS[i], LED_ON); //'receiving <64 turns red on and green off'
          state[bank][i] = false;
        } // 'if not the controller for i then skip this loop'    
      }
    }
  }
}

void onClock() {
  if (tempoFlashOn){
    if (ClockCount<=onClocks){
      digitalWrite(MODE_TAP_LED_PIN, LED_ON);
    }else{
      digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
    }
  }
  ClockCount = (ClockCount+1)%24;
}

void onStart(){
  ClockCount = 0;
}


void onSongPosition(uint16_t semiQ){
  ClockCount= semiQ*6 ; 
}
 
Bought a 6 button midi controller and was trying to code.

Can you show us photos and details of the hardware you're actually using?

This code is complex and honestly, I can't follow what is it doing and I can't understand your explanation of what you want to accomplish when I don't even have any idea of what this hardware even looks like.
 
No... reading again it sounds like you want selection of a new CC value as ON to send OFF for the previous CC?

Edit
...just noticed it's sending program changes and not CC...
 
Hi all, firstly thanks for the respond. Let me try to explain what I want to achieve.

IMG_7384.jpg
This is the state of the midi controller when I on it. The red colour buttons represent "OFF"

IMG_7385.jpg
This is the state of the midi controller when I on it., The button becomes green which represent "ON"

Each button represent a PC which it will send to my guitar effects, calling out the present.
Right now every time I "ON" the button I need to switch it off so that there won't be error message. Error Messages meaning the PC numbers will go haywire, it will keep sending random PC to my guitar effects. My guitar effects will keep running random preset continuously.

IMG_7386.jpg
This is the state when I "ON" 2 buttons and it will have error message

IMG_7387.jpg
My ideal solution to this is that how can I "ON" the second button (the middle button) and the first one (extreme right) will be switch off automatically. Just like how the picture is right now. When I "ON" the middle button, the extreme right button will "OFF" automatically.

So sorry if my explanation is bad, I tried my best wanting to explain how to get it to work. Thank you so much for spending time and effort to come up with solution. Appreciate that alot.
 
No... reading again it sounds like you want selection of a new CC value as ON to send OFF for the previous CC?

Edit
...just noticed it's sending program changes and not CC...

I think that is the person whom I bought the midi controller from. He does a few profiles for his midi controller. But the hassle to " OFF" the preset and then "ON" another one its not helping if I am playing live guitar when the change of preset must be immediate and accurate.

Not wanting them to be momentary. Each button now has 2 state. "ON" and "OFF" Green and Red. Can I only make it in 1 state?

"ON" only. But if I press a second button, the first button will be "OFF". So at any one time only 1 button will on "ON"

So sorry, totally noob. Thanks for replying
 
hallo, for my hx stomp and midistomp, I put into the profile this:
Code:
//************DIGITAL SECTION**************
void getMain(){
  for (int i=3;i<D_PINS;i++){ //ML:messo i di start a 3 perche' i pulsanti con indice 0,1,2 li gestisco qui sotto per inviare i CC
    digital[i].update();
    if (digital[i].fallingEdge() || digital[i].risingEdge()) {
      if (state[bank][i]) {
        usbMIDI.sendControlChange(MIDI_CC_NUMS[bank][i], 0, firstchannel);
        MIDI.sendControlChange(MIDI_CC_NUMS[bank][i], 0, secondchannel);  
        digitalWrite(RED_LED_PINS[i], LED_ON);
        digitalWrite(GREEN_LED_PINS[i], LED_OFF);
      }else{
        usbMIDI.sendControlChange(MIDI_CC_NUMS[bank][i], ON_Value, firstchannel);
        MIDI.sendControlChange(MIDI_CC_NUMS[bank][i], ON_Value, secondchannel);
        digitalWrite(RED_LED_PINS[i], LED_OFF);
        digitalWrite(GREEN_LED_PINS[i], LED_ON);
      }
      state[bank][i] = !state[bank][i] ;
    }
  }

 //gestione pulsante 1: invia sempre valore zero per il CC69
  digital[0].update(); //lettura stato pulsante 1 (pin digitale 0)
    if (digital[0].fallingEdge() || digital[0].risingEdge()) {
      digitalWrite(GREEN_LED_PINS[0], LED_ON); //faccio un 'flash' sul led verde durante l'invio del CC perche' in questo caso non ha senso tenerlo acceso
      usbMIDI.sendControlChange(69, valore_pulsante1, firstchannel); //invio CC su usb e midi
      MIDI.sendControlChange(69, valore_pulsante1, secondchannel);       
      digitalWrite(GREEN_LED_PINS[1], LED_OFF); //spegnimento flash 2...
      digitalWrite(GREEN_LED_PINS[2], LED_OFF); //spegnimento flash 3...
      
    }

//gestione pulsante 2: invia  valore 1 o 0 (alternati) per il CC69
  digital[1].update(); //lettura stato pulsante 2 (pin digitale 1)
    if (digital[1].fallingEdge() || digital[1].risingEdge()) {
      digitalWrite(GREEN_LED_PINS[1], LED_ON); //faccio un 'flash' sul led verde durante l'invio del CC perche' in questo caso non ha senso tenerlo acceso
      usbMIDI.sendControlChange(69, valore_pulsante2, firstchannel); //invio CC su usb e midi
      MIDI.sendControlChange(69, valore_pulsante2, secondchannel);       
      digitalWrite(GREEN_LED_PINS[0], LED_OFF); //spegnimento flash 1...
      digitalWrite(GREEN_LED_PINS[2], LED_OFF); //spegnimento flash 3...
      
    }
//gestione pulsante 3: invia  valore 2 o 0 (alternati) per il CC69
  digital[2].update(); //lettura stato pulsante 3 (pin digitale 2)
    if (digital[2].fallingEdge() || digital[2].risingEdge()) {
      digitalWrite(GREEN_LED_PINS[2], LED_ON); //faccio un 'flash' sul led verde durante l'invio del CC perche' in questo caso non ha senso tenerlo acceso
      usbMIDI.sendControlChange(69, valore_pulsante3, firstchannel); //invio CC su usb e midi
      MIDI.sendControlChange(69, valore_pulsante3, secondchannel);       
      digitalWrite(GREEN_LED_PINS[0], LED_OFF); //spegnimento flash 1...
      digitalWrite(GREEN_LED_PINS[1], LED_OFF); //spegnimento flash 2...
      
    }
  
}
the stomp 1 exit with CC69 value 0, the stomp 2 exit with CC69 value 1, the stomp 3 exit with CC69 value 2.
every stomp put ON his (green) led and put OFF other two (red) led
 
Back
Top