Saxophone midi controller, need help!

Hi everyone,
I’m really new to arduino coding, so i really need help.
My project is really simple, a Chinese micro atmega32u4 and two KC11B04 4X1 AD KEYPAD.
so schematics are really simple, one KC11B04 on pin A0 the other on pin A1, all grounded and vcc.
My first try of code is ok for return numbers of each button trough serial monitor, and I really don’t know how to code the midi part for control changes. My goal is to have a thumb controller on my sax to only control change the presets of my helix (I’m a disabled person so i can’ use my feet) and with my hands i can’t control change within playing.
here’s my first sample of code (not working) and there’s so much documentation, I don’t know what to read … (I don’t want neither to be a super-coder)

#include <MIDIUSB.h>

int AD_PIN1 = A0;
int AD_PIN2 = A1;

void setup() {
Serial.begin(115200);
}

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

}
void loop() {

int adValue = analogRead(AD_PIN1);
Serial.println(buttonFromValue(adValue));
int adValue2 = analogRead(AD_PIN2);
Serial.println(buttonFromValue2(adValue2));
int boutons1 = (buttonFromValue);
int boutons2 = (buttonFromValue2);
}

// Returns the button number based on the analog value
byte buttonFromValue(int adValue) {

if (adValue > 300 && adValue < 500) {
return 1;
}

if (adValue > 500 && adValue < 700) {
return 2;
}

if (adValue > 700 && adValue < 900) {
return 3;
}

if (adValue > 900) {
return 4;
}

return 0;

}
byte buttonFromValue2(int adValue2) {

if (adValue2 > 300 && adValue2 < 500) {
return 5;
}

if (adValue2 > 500 && adValue2 < 700) {
return 6;
}

if (adValue2 > 700 && adValue2 < 900) {
return 7;
}

if (adValue2 > 900) {
return 8;
}

return 0;

}

while (buttonFromValue == 1) controlChange (0, 89, 8)
MidiUSB.flush();
delay(500);
}
while (buttonFromValue == 2) controlChange (0, 90, 8)
MidiUSB.flush();
delay(500);

#include <MIDIUSB.h>

If you are using the USB port for sending midi you can not really use it for debug messages
I am not very familiar with this particular library, but it seems fairly straight forward.
You might want to have a look at @PieterP 's Control-surface.h though for your application

thanks for your answer,
i already have control surfaces.h but i can’t really understand how his codes from example are usable for me, because in fact I can’t change the pin number by the buttonfromvalue return …
I know I’m a noob an don’t want to disturb all of you, but i don’t know where to find help …
thanks again

General advice in order to get help more easily.

A correctly posted code is a must :wink:. In the Arduino IDE follow theese steps:

  1. Ctrl + T to indent your code (⌘ Cmd + T on a Mac).

  2. Copy your code Ctrl + C and paste it using this button on the forum post editor: gg (⌘ Cmd + C on a Mac)

  3. In alternative you can right click on the code in the Arduino IDE and select:
    Copy for Forum

  4. Modify your original post.

Good luck :wink:

void loop() {

int adValue = analogRead(AD_PIN1);
Serial.println(buttonFromValue(adValue));
int adValue2 = analogRead(AD_PIN2);
Serial.println(buttonFromValue2(adValue2));
int boutons1 = (buttonFromValue);  
int boutons2 = (buttonFromValue2);
}

Ok, now i am looking at your code, and something i didn’t notice before shows up. Your 'boutons1 & boutons2 variables go out of scope right after they’ve been declared, they are not used for now, but something to pay attention to.

I’m not sure what that means, but i am quite sure that that library enables you to do what you need to do.

Seriously don’t worry about it !

Yes please and

In what way is it not working ?
Personally i would separate the process of getting ‘my code’ to work into 2 parts.

  • Receiving the data from button, sliders, encoders etc And checking that this is happening the way i want it to.
  • Sending the midi commands that i want to send using hardcode values to make sure that the sending and receiving between 2 devices is happening correctly

Then i would combine the 2. This makes it a lot easier to debug.
In a way it doesn’t matter what you do first, but let’s keep the order as it is.
So create a new sketch (or comment out all you don’t need for the first step)
that is the #include <MIDIUSB.h>
the ‘void controlChange()’ function
and this section :

while (buttonFromValue == 1) controlChange (0, 89, 8)
MidiUSB.flush();
delay(500);
}
while (buttonFromValue == 2) controlChange (0, 90, 8)
MidiUSB.flush();
delay(500);

which doesn’t appear to be inside a function at all, which means that it won’t compile as is anyway.
Now add a delay to loop() and print also the value that results directly from the analogRead() like this

void loop() {
delay(1000);  // update the date once per second for now
int adValue = analogRead(AD_PIN1);
Serial.print(adValue, DEC);
Serial.print(",   ");
Serial.println(buttonFromValue(adValue));
int adValue2 = analogRead(AD_PIN2);
Serial.print(adValue2, DEC);
Serial.print(",   ");
Serial.println(buttonFromValue2(adValue2));
}

I actually had to check what they were, but they seem like a perfectly good solution, i make these myself to fit whatever needs i may have actually.
Now anyway open the serial monitor and see what is being printed ?

thanks for all information ! my code is effectively shit … i would re-post soon the code in the good way and into parts…
in serial monitor with the beginning of my code I have written 0, and when pressed 1 2 3 4 5 6 7 8 according to buttons … so for me that was a good start
now my real problem is that in all examples I’ve seen the different buttons are assigned to pins, and i would like to set it to my analogread numbers …

my first code to read the buttons …


int AD_PIN1 = A0;
int AD_PIN2 = A1;

void setup() {
  Serial.begin(115200);
}
void loop() {
  int adValue = analogRead(AD_PIN1);
  Serial.println(buttonFromValue(adValue));
  int adValue2 = analogRead(AD_PIN2);
  Serial.println(buttonFromValue2(adValue2));
}

// Returns the button number based on the analog value
byte buttonFromValue(int adValue) {

  if (adValue > 300 && adValue < 500) {
    return 1;
  }

  if (adValue > 500 && adValue < 700) {
    return 2;
  }

  if (adValue > 700 && adValue < 900) {
    return 3;
  }

  if (adValue > 900) {
    return 4;
  }

  return 0;


}
byte buttonFromValue2(int adValue2) {

  if (adValue2 > 300 && adValue2 < 500) {
    return 5;
  }

  if (adValue2 > 500 && adValue2 < 700) {
    return 6;
  }

  if (adValue2 > 700 && adValue2 < 900) {
    return 7;
  }

  if (adValue2 > 900) {
    return 8;
  }

  return 0;

}

Yes but in way, just make sure you specify what you want it to do and what it does instead.

So basically the buttons work. (what happens when you remove the delay(1000) ? )
Now let’s see if you can get the MIDIUSB to work.
include the MIDIUSB.h again but now **do not ** print to the serial port (let midiusb do it’s thing)

void loop() {
  delay(500);
  controlChange (0, 90, 8);  
  delay(500);
  controlChange (0, 90, 80);
}

Send different values for the same CC with some spacing in between (in your original code you send the same value for a different CC, that might not show up very well.

That should hardly classify as a problem.

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 **Arduino UNO ONLY!**
 *************************************************************/

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 0;


//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );
//Button BU2(3, 0, 61, 1, 5 );
//Button BU3(4, 0, 62, 1, 5 );
//Button BU4(5, 0, 63, 1, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {};
//*******************************************************************

void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
}

in that kind of code which can save me ^^ all different buttons ,

//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );

are assigned to a pin and not to my analog numbers of the previous code …

i know that’ not MIDIUSB but it’s kind ok what i would like :stuck_out_tongue:

No but it can be made to use MIDIUSB instead of midi.h just fine.
I’ve seen that library before but in my opinion control-surface.h is better (and maintained and supported by the author here on the forum)

Well within the updateButton() function, you will find an answer to that question. I don’t have it on hand, but there (or in a sub function) the data that is in that button array is read. Now it is not to complicated to add a field to the struct (which is defined in the library’s .h & .cpp) which holds the analog return value for that specific button that is connected to that pin. Post the complete code of that sample sketch including the .h & .cpp of the library. And i will show you how to do that.

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 **Arduino UNO ONLY!**
 *************************************************************/

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 0;


//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );
//Button BU2(3, 0, 61, 1, 5 );
//Button BU3(4, 0, 62, 1, 5 );
//Button BU4(5, 0, 63, 1, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {};
//*******************************************************************

void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
}


//*****************************************************************
void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }

    //  Button is not pressed
    if (message == 1) {
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}

controller.cpp


#include "Controller.h"


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte command, byte value, byte channel, byte debounce)
{
  _pin = pin;
  pinMode(_pin, INPUT_PULLUP);
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}


byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    if (digitalRead(_pin) == _last) return 2; // If same as last state - exit
  }

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if (digitalRead(_pin) == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;
  }
}

void Button::newValue(byte command, byte value, byte channel)
{
  Bvalue = value;
  Bcommand = command;
  Bchannel = channel;
}

controller.h

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte command, byte value, byte channel, byte debounce);
    Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _value;
    byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};

#endif

all to be adapted to my project of course, but i think there’s not much to do if i can have the numbers of my analogread in place of button pins …

that script come from the guy of the control surface library if i’m not mistaken

thank you so much

The MIDI Controller library has been obsoleted by its successor, the Control Surface library.

It has more features, a better architecture, unit tests, continuous integration, clearer documentation, support for more and newer Arduino boards, etc.
It adds support for MIDI input, SysEx, the Mackie Control Universal protocol, VU meters, LEDs, OLED displays, audio over USB, MIDI over Bluetooth, MIDI routing …

And it is supported by the author, but anyway i think this is created by someone different.

Since you aren’t planning to use a multiplexer, it is fine to use the overloaded function (mind you it seems controller.cpp is not complete the way it is now. (the function for the multiplexer are declared but there is no implementation.
We can add an extra argument to the Button in controller.h, but then the compiler might not be able to keep it apart from the muxButton. Where is the rest of conrtroller.cpp ?
I can’t do this unless you provide me with the full file.

  public:
    Button(byte pin, byte command, byte value, byte channel, byte debounce);
    Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);  // this function
    byte getValue();
    void muxUpdate();  // and this function is missing from Controller.cpp
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

Understand that i anyway have the feeling that i am doing this twice, just a couple of weeks ago i added extra arguments for mapping to the mux-buttons.
This time it’s going to be a bit more tricky, i’ll have a proper check with a clear head in the morning. Understand i didn’t write this code. But i think it’s like this. i’ve put comments where i’ve changed things
Controller.h

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte kcbutton, byte command, byte value, byte channel, byte debounce);  // change this line
    //Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    //void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte buttonFromValue(int adValue);  // add this line
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _kcbutton;  // and this one
    //byte _muxpin;
    //byte _numMuxPins;
    byte _value;
    byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};

#endif

Now in the getvalue() function the pin is read, and now instead of a digitalread() we need to do analogRead() pass that to the buttonFromValue() function, and compare the return value of that to the value that is stored in the new argument kcbutton. I think that works out to be like this

if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) , but that would invert the logic,
keep that in mind.

so now the whole controller.cpp ends up like

#include "Controller.h"


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte kcbutton, byte command, byte value, byte channel, byte debounce)
{
  _pin = pin;
  _kcbutton = kcbutton;    // add this line
  //pinMode(_pin, INPUT_PULLUP);  // remove this line
  pinMode(_pin, INPUT);  // add this line
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

byte buttonFromValue(int adValue) {   // add this whole function
  if (adValue > 300 && adValue < 500) {
    return 1;
  }
  if (adValue > 500 && adValue < 700) {
    return 2;
  }
  if (adValue > 700 && adValue < 900) {
    return 3;
  }
  if (adValue > 900) {
    return 4;
  }
  return 0;
}


byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    
    if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) return 2; // If same as last state - exit
  }       // i think it is like this

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if ((buttonFromValue(analogRead(_pin)) == _kcbutton)  == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;
  }
}

void Button::newValue(byte command, byte value, byte channel)
{
  Bvalue = value;
  Bcommand = command;
  Bchannel = channel;
}

and now you can declare buttons pretty much the same way as it was

//Button (Analog Pin Number, Button From keypad  Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(A0, 1, 0, 60, 1, 5 );
//Button BU2(A0, 2, 0, 61, 1, 5 );
etc.

The updateButtons() functions deals with action to take upon a button being pressed, now we need to invert the logic here as well.

void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 1) {   //   invert the logic here
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }

    //  Button is not pressed
    if (message == 0) {   // and invert it here
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}

Now it should work (but it’s after dinner time, and i haven’t compiled it yet), still it would be easier to start using control-surface.h , it has all these keypad functions built in and more importantly, i wouldn’t have to do the support, Pieter would do it :smile:

You might be mistaken, because I’m not the author of the code you posted :slight_smile:

Control surface supports button matrices, but not analog inputs using resistor ladders.

I’d recommend starting from the code you had in the beginning, using this Controller.h code is too complicated.
Control Surface could come in handy for sending MIDI, but using the MIDIUSB library should work as well.

Hi !
Really sorry for my mistake, I searched a bit and this code is from nerdmusician, and effectively lots of people found his code really heavy, difficult to debug, complicated and so on, so i will work on a cleaner code :wink:
I thank so much Deva_Rishi for his time an goodness :slight_smile:
Probably you are the one who can help me, because i’ve tried so much examples from controsurfaces.h but i think the one i need only is :
CCbutton, which look like what I need, I’m so noob that I don’t know how to change the pin number by my analogread numbers, and poorer I don’t know how to put my lines in a way like :
controlChange (analogread, channel, CC number, velocity)
I’m really impressed how reactive is this forum ^^
I thank you all so much, and will post a begin of the “mixed” code with the CCbutton


#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

// Instantiate a CCButton object
CCButton button = {
  // Push button on pin 5:
  buttonFromValue, buttonFromValue2
  // General Purpose Controller #1 on MIDI channel 1:
  {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1},
};


int AD_PIN1 = A0;
int AD_PIN2 = A1;

void setup() {
  Serial.begin(115200);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
  int adValue = analogRead(AD_PIN1);
  Serial.println(buttonFromValue(adValue));
  int adValue2 = analogRead(AD_PIN2);
  Serial.println(buttonFromValue2(adValue2));
}

// Returns the button number based on the analog value
byte buttonFromValue(int adValue) {

  if (adValue > 300 && adValue < 500) {
    return 1;
  }

  if (adValue > 500 && adValue < 700) {
    return 2;
  }

  if (adValue > 700 && adValue < 900) {
    return 3;
  }

  if (adValue > 900) {
    return 4;
  }

  return 0;


}
byte buttonFromValue2(int adValue2) {

  if (adValue2 > 300 && adValue2 < 500) {
    return 5;
  }

  if (adValue2 > 500 && adValue2 < 700) {
    return 6;
  }

  if (adValue2 > 700 && adValue2 < 900) {
    return 7;
  }

  if (adValue2 > 900) {
    return 8;
  }

  return 0;

}
CCButton buttonFromValue == 1 controlChange(1, 0, 90, 8 ); // for (CCmode,Channel,CCnumber,Velocity)
CCButton buttonFromValue == 2 controlChange(1, 0, 61, 127,);
CCButton buttonFromValue == 3 controlChange(1, 0, 62, 0 );
CCButton buttonFromValue == 4 controlChange(1, 0, 63, 50 );
CCButton buttonFromValue2 == 5 controlChange(1, 0, 64, 45 );
CCButton buttonFromValue2 == 6 controlChange(1, 0, 65, 56 );
CCButton buttonFromValue2 == 7 controlChange(1, 1, 64, 25 );
CCButton buttonFromValue2 == 8 controlChange(1, 2, 64, 70 );

of course it’s not compiling because the line : ```
CCButton button = {
// Push button on pin 5:
buttonFromValue, buttonFromValue2


and of course at the end in () is what I would like and not
 what it does really i think,
sorry for my noobitude, and thank you for your help !

Yeah, now i’ve finally had a proper look in the library, and i actually think that the buttons that you have are not supported in this version of that library, but let’s ask @PieterP
You see what you have is kind of a keypad, but kind of not. The keypads use multiplexers and the small boards you have just contain a few resistors. A very simple system, but they do not allow you to press / take action on multiple button being pressed at once. That said, i doubt if it will be very difficult for the author of the library to add them, but for me it is near-impossible.

thank you for your reply,
just to say that I’ll press only one button at a time (change preset while playing sax)
and if Profile - PieterP - Arduino Forum has time to help me it could be so cool !

Well pending that, I did some mods on the code i worked on yesterday and now it compiles at least (for a micro with native USB support). Maybe you can give that a try.
The .ino

#include <MIDIUSB.h>
#include "Controller.h"

byte NUMBER_BUTTONS = 8;

//Button (Analog Pin, KCButton, CC Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

Button BU1(A0, 1, 90, 8, 1, 5 );
Button BU2(A0, 2, 90, 7, 1, 5 );
Button BU3(A0, 3, 90, 6, 1, 5 );
Button BU4(A0, 4, 90, 5, 1, 5 );
Button BU5(A1, 1, 90, 4, 1, 5 );
Button BU6(A1, 2, 90, 3, 1, 5 );
Button BU7(A1, 3, 90, 2, 1, 5 );
Button BU8(A1, 4, 90, 1, 1, 5 );

//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};

void setup() {
  //Serial.begin(115200);
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
}

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


void updateButtons() {
  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();
    
    if (message == 1) {    //  Button is pressed
      controlChange(BUTTONS[i]->Bcc, BUTTONS[i]->Bvalue, BUTTONS[i]->Bchannel);
      break;
    }

    if (message == 0) {    //  Button is not pressed
      //controlChange(BUTTONS[i]->Bcc, 0, BUTTONS[i]->Bchannel);
    }
  }
}

Controller.h

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte kcbutton, byte cc, byte value, byte channel, byte debounce);  // change this line
    //Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    //void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcc;
    //byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte buttonFromValue(int adValue);  // add this line
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _kcbutton;  // and this one
    //byte _muxpin;
    //byte _numMuxPins;
    byte _cc;
    byte _value;
    //byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};

#endif

Controller.cpp

#include "Controller.h"


//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte kcbutton, byte cc, byte value, byte channel, byte debounce)
{
  _pin = pin;
  _kcbutton = kcbutton;    // add this line
  //pinMode(_pin, INPUT_PULLUP);  // remove this line
  pinMode(_pin, INPUT);  // add this line
  _cc = cc;
  _value = value;
  // _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcc = cc;
  //Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

byte Button::buttonFromValue(int adValue) {   // add this whole function
  if (adValue > 300 && adValue < 500) {
    return 1;
  }
  if (adValue > 500 && adValue < 700) {
    return 2;
  }
  if (adValue > 700 && adValue < 900) {
    return 3;
  }
  if (adValue > 900) {
    return 4;
  }
  return 0;
}


byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    
    if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) return 2; // If same as last state - exit
  }       // i think it is like this

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if ((buttonFromValue(analogRead(_pin)) == _kcbutton) == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;  // invert the logic here. 
  }
}

void Button::newValue(byte command, byte value, byte channel) {  
  Bvalue = value;
  //Bcommand = command;
  Bchannel = channel;
}

I suppose we could still remove the whole ‘pot’ class if you are not going to use that.

thanks I will try that immediately, and sur i don’t need pots nor multiplexers, just my 2 four buttons plates ^^
i will give you the return of that soon

Controller.cpp:5:1: error: prototype for ‘Button::Button(byte, byte, byte, byte, byte)’ does not match any in class ‘Button’

I just got that error in compiling but look in a good way …
:slight_smile: