Midi Library Code - Beginner Question

Hi,

my Sketch should connect up to 6 Buttons with 6 LEDs (actually 2 in use).
It is my first Sketch and i had some trouble to get to this point :slight_smile:

The Code is working, but if someone has ideas for change, im happy to implement it.

Question now:

  midiOut.sendControlChange(param1[val],velo1[val],channel1[val]); 

You see i was able to make the variables in the brackets right.
I would like to change "sendControlChange" to a variable, so i can choose.
Is this possible?
Thanks in advance, Arduino is great :slight_smile:

EDIT: I updated the code once again, now 2 dimension for arrays, less code.

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>


int LEDPins[6] = {13, 12,9,8};                               // create Array of LED Pins according to Buttons, max 6
int ButtonPins[6] =  {10, 11,7,6,5,4};                          // create Array of Button Pins, max 6
bool ButtonStates[6] = {true, true};                   // create Array of Buttons States (true = on, false = off)
unsigned long startMillis[12];                       // create Array of Start Times for Buttons
unsigned long currentMillis[12];                    // create Array of Current Times for Buttons
int inputdebounce[6] = {10, 10, 10, 10, 10, 10};    // create Array of Input debounce Times, so every button can be debounced seperatly
int holdtime[6] = {250, 250, 250, 250, 250, 250};  // create Array of Input Hold Times, so every button can be set seperatly

const byte param[3][6] = {{14,81},                   // Variables for 3 on and 3 off control changes, called in functions buttonon and buttonoff
                          {19},
                          {31}};
const byte velo[3][6] = {{127,127},
                         {0},
                         {127}};
const byte channel[3][6] = {{2,2},
                            {2},
                            {2}};

const byte paramoff[3][6] = {{14,81},
                             {19,},
                             {31,}};
const byte velooff[3][6] = {{0,0},
                            {127},
                            {0}};
const byte channeloff[3][6] = {{2,2},
                               {2},
                               {2}};


MIDI_CREATE_DEFAULT_INSTANCE();   // create a MIDI object called midiOut

void setup() {

  for (int thisPin = 0; thisPin < (sizeof(LEDPins) / sizeof(LEDPins[0])); thisPin++) {      // Pin Modes for LED
    pinMode(LEDPins[thisPin], OUTPUT);
  }

  for (int thisButton = 0; thisButton < (sizeof(ButtonPins) / sizeof(ButtonPins[0])); thisButton++) {     // Pin Modes for Buttons
    pinMode(ButtonPins[thisButton], INPUT);
  }
  for ( int thisstartMillis = 0; thisstartMillis < (sizeof(startMillis) / sizeof(startMillis[0])); thisstartMillis++) {     // set Start Times for Buttons to current millis
    startMillis[thisstartMillis] = millis();
  }
  Serial.begin(31250); // setup MIDI output
  
}


void loop() {


  for (int thisButton = 0; thisButton < (sizeof(ButtonPins) / sizeof(ButtonPins[0])); thisButton++) {     // for going through every element of ButtonPins[] and checking Input

    if (digitalRead (ButtonPins[thisButton]) == LOW && ButtonStates[thisButton] == true) {                // MIDI ON read, check button state Input and State per Button

      currentMillis[thisButton] = millis();                                                               //get the current millis per Button
      if (currentMillis[thisButton] - startMillis[thisButton] >= inputdebounce[thisButton]) {             //test whether the input debounce has elapsed
        buttonon(thisButton);                                                                          // function for MIDI Output, Opens switch case for every Button
        digitalWrite (LEDPins[thisButton], HIGH);                                                         // writes LED high, according to Button
        currentMillis[thisButton] = millis();                                                             // sets current timer to millis
        startMillis[thisButton] = currentMillis[thisButton];                                              // sets start millis to current millis
        startMillis[thisButton + 6] = currentMillis[thisButton];                                          // set start millis to current millis, used for button hold function
        ButtonStates[thisButton] = false  ;                                                               // sets button state
      }
      else {
        startMillis[thisButton] = millis();                                                               // sets start millis to millis, to get debounce go again
      }
    }


    if (digitalRead (ButtonPins[thisButton]) == LOW && ButtonStates[thisButton] == false) {               // MIDI OFF, same if loop as above but inverted
      currentMillis[thisButton] = millis();
      if (currentMillis[thisButton] - startMillis[thisButton] >= inputdebounce[thisButton]) {
        buttonoff(thisButton);
        digitalWrite (LEDPins[thisButton], LOW);
        startMillis[thisButton] = currentMillis[thisButton];
        ButtonStates[thisButton] = true;
      }
      else {
        startMillis[thisButton] = millis();
      }
    }



    if (digitalRead (ButtonPins[thisButton]) == HIGH && ButtonStates[thisButton] == false ) {         // MIDI HOLD, depending on second timer block [thisButton +6]
      currentMillis[thisButton + 6] = millis();
      if ( currentMillis[thisButton + 6] - startMillis[thisButton + 6] >= holdtime[thisButton]) {
        buttonoff(thisButton);
        digitalWrite (LEDPins[thisButton], LOW);
        ButtonStates[thisButton] = true;
      }
      else {
        startMillis[thisButton + 6] = millis();
      }
    }
  }


}

void buttonon (int val) {     //midi function for button on control per button on click
  
      MIDI.sendControlChange(param[0][val],velo[0][val],channel[0][val]); // send a MIDI CC
      MIDI.sendControlChange(param[1][val],velo[1][val],channel[1][val]); // send a MIDI CC
      MIDI.sendControlChange(param[2][val],velo[2][val],channel[2][val]); // send a MIDI CC
      
    
  }

void buttonoff (int val) {   //midi function for button off control per button on click
      MIDI.sendControlChange(paramoff[0][val],velooff[0][val],channeloff[0][val]); // send a MIDI CC
      MIDI.sendControlChange(paramoff[1][val],velooff[1][val],channeloff[1][val]); // send a MIDI CC
      MIDI.sendControlChange(paramoff[2][val],velooff[2][val],channeloff[2][val]); // send a MIDI CC
}


I recommend that you write a function that takes all the same arguments as MIDI.sendControlChange plus one to indicate which midi function you want to call.

void midiFunc(int function, int param, int velo, int channel)
{
    switch (function)
    {
    case SendControl:
        MIDI.sendControlChange(param,velo,channel); 
        break;
    case SendNote:
        MIDI.sendNote(param,velo,channel); 
        break;
    }
}

Simple and effektive, thank you :slight_smile:

I changed my Code according your input. Works right, i think.

is there any thing im doing wrong with my code? ideas? complains?

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>


int LEDPins[6] = {13, 12,9,8};                               // create Array of LED Pins according to Buttons, max 6
int ButtonPins[6] =  {10, 11,7,6,5,4};                          // create Array of Button Pins, max 6
bool ButtonStates[6] = {true, true};                   // create Array of Buttons States (true = on, false = off)
unsigned long startMillis[12];                       // create Array of Start Times for Buttons
unsigned long currentMillis[12];                    // create Array of Current Times for Buttons
int inputdebounce[6] = {10, 10, 10, 10, 10, 10};    // create Array of Input debounce Times, so every button can be debounced seperatly
int holdtime[6] = {250, 250, 250, 250, 250, 250};  // create Array of Input Hold Times, so every button can be set seperatly

const byte param[3][6] = {{14,81},                   // Variables for 3 on and 3 off control changes, called in functions buttonon and buttonoff
                          {19},
                          {31}};
const byte velo[3][6] = {{127,127},
                         {0},
                         {127}};
const byte channel[3][6] = {{2,2},
                            {2},
                            {2}};


const byte paramoff[3][6] = {{14,81},
                             {19,},
                             {31,}};
const byte velooff[3][6] = {{0,0},
                            {127},
                            {0}};
const byte channeloff[3][6] = {{2,2},
                               {2},
                               {2}};

const byte function[3][6] = {{4,4},
                             {4},
                             {4}};


MIDI_CREATE_DEFAULT_INSTANCE();   // create a MIDI object called midiOut

void setup() {

  for (int thisPin = 0; thisPin < (sizeof(LEDPins) / sizeof(LEDPins[0])); thisPin++) {      // Pin Modes for LED
    pinMode(LEDPins[thisPin], OUTPUT);
  }

  for (int thisButton = 0; thisButton < (sizeof(ButtonPins) / sizeof(ButtonPins[0])); thisButton++) {     // Pin Modes for Buttons
    pinMode(ButtonPins[thisButton], INPUT);
  }
  for ( int thisstartMillis = 0; thisstartMillis < (sizeof(startMillis) / sizeof(startMillis[0])); thisstartMillis++) {     // set Start Times for Buttons to current millis
    startMillis[thisstartMillis] = millis();
  }
  Serial.begin(31250); // setup MIDI output
  
}


void loop() {


  for (int thisButton = 0; thisButton < (sizeof(ButtonPins) / sizeof(ButtonPins[0])); thisButton++) {     // for going through every element of ButtonPins[] and checking Input

    if (digitalRead (ButtonPins[thisButton]) == LOW && ButtonStates[thisButton] == true) {                // MIDI ON read, check button state Input and State per Button

      currentMillis[thisButton] = millis();                                                               //get the current millis per Button
      if (currentMillis[thisButton] - startMillis[thisButton] >= inputdebounce[thisButton]) {             //test whether the input debounce has elapsed
        for (int i = 0; i < 3;i++){
          buttonon(function[i][thisButton], thisButton, i); // function for MIDI Output, Opens switch case for every Button   // function for MIDI Output, Opens switch case for every Button
        }                                                                         
        digitalWrite (LEDPins[thisButton], HIGH);                                                         // writes LED high, according to Button
        currentMillis[thisButton] = millis();                                                             // sets current timer to millis
        startMillis[thisButton] = currentMillis[thisButton];                                              // sets start millis to current millis
        startMillis[thisButton + 6] = currentMillis[thisButton];                                          // set start millis to current millis, used for button hold function
        ButtonStates[thisButton] = false  ;                                                               // sets button state
      }
      else {
        startMillis[thisButton] = millis();                                                               // sets start millis to millis, to get debounce go again
      }
    }


    if (digitalRead (ButtonPins[thisButton]) == LOW && ButtonStates[thisButton] == false) {               // MIDI OFF, same if loop as above but inverted
      currentMillis[thisButton] = millis();
      if (currentMillis[thisButton] - startMillis[thisButton] >= inputdebounce[thisButton]) {
        for (int i = 0; i < 3;i++){
          buttonoff(function[i][thisButton], thisButton, i);     // function for MIDI Output, Opens switch case for every Button
        }
        digitalWrite (LEDPins[thisButton], LOW);
        startMillis[thisButton] = currentMillis[thisButton];
        ButtonStates[thisButton] = true;
      }
      else {
        startMillis[thisButton] = millis();
      }
    }



    if (digitalRead (ButtonPins[thisButton]) == HIGH && ButtonStates[thisButton] == false ) {         // MIDI HOLD, depending on second timer block [thisButton +6]
      currentMillis[thisButton + 6] = millis();
      if ( currentMillis[thisButton + 6] - startMillis[thisButton + 6] >= holdtime[thisButton]) {
        for (int i = 0; i < 3;i++){
          buttonoff(function[i][thisButton], thisButton, i);    // function for MIDI Output, Opens switch case for every Button
        }
        
        digitalWrite (LEDPins[thisButton], LOW);
        ButtonStates[thisButton] = true;
      }
      else {
        startMillis[thisButton + 6] = millis();
      }
    }
  }


}

void buttonon (int function, int thisButton, int i) {     //midi function for button on control per button on click
  
    switch (function)
    {
    case 4:
        MIDI.sendControlChange(param[i][thisButton],velo[i][thisButton],channel[i][thisButton]); // send a MIDI CC
        break;
    case 1:
        MIDI.sendNoteOn(param[i][thisButton],velo[i][thisButton],channel[i][thisButton]); // send a MIDI CC
        break;
    case 2:
        MIDI.sendNoteOff(param[i][thisButton],velo[i][thisButton],channel[i][thisButton]); // send a MIDI CC
        break;  
    case 3:
        break;
    
    }
}

void buttonoff (int function,int thisButton,int i) {  

    switch (function)
    {
    case 4:
        MIDI.sendControlChange(paramoff[i][thisButton],velooff[i][thisButton],channeloff[i][thisButton]); // send a MIDI CC
        break;
    case 1:
        MIDI.sendNoteOn(paramoff[i][thisButton],velooff[i][thisButton],channeloff[i][thisButton]); // send a MIDI CC
        break;
    case 2:
        MIDI.sendNoteOff(paramoff[i][thisButton],velooff[i][thisButton],channeloff[i][thisButton]); // send a MIDI CC
        break;  
    case 3:
        break;
    
    }
}