Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conect 2 or more buttons to a single led #97

Open
sincos5 opened this issue Oct 25, 2019 · 19 comments
Open

Conect 2 or more buttons to a single led #97

sincos5 opened this issue Oct 25, 2019 · 19 comments

Comments

@sincos5
Copy link

sincos5 commented Oct 25, 2019

I dont know how to do it without making a mess with my signals.

@tttapa
Copy link
Owner

tttapa commented Oct 25, 2019

The MIDI Controller library doesn't support this, Control Surface does.

What do you want the LED to do?

@sincos5
Copy link
Author

sincos5 commented Oct 25, 2019

Just turn on and off whenever a button is pressed

@tttapa
Copy link
Owner

tttapa commented Oct 26, 2019

You could do something like this:

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

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

using namespace MIDI_Notes;

// Instantiate an array of NoteButton objects
Array<NoteButton, 3> buttons = {{
  // Push button on pin 5, note C4 (middle C) on MIDI channel 1
  {5, {note(C, 4), CHANNEL_1}},
  // Push button on pin 6, note D4 on MIDI channel 1
  {6, {note(D, 4), CHANNEL_1}},
  // etc.
  {7, {note(E, 4), CHANNEL_1}},
}};

constexpr pin_t ledPin = LED_BUILTIN;

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

/// Return true if the predicate evaluates to true for at least one of the elements of the iterable
template<class Iterable, class Predicate> bool any_of(const Iterable &iterable, const Predicate &pred) {
  for (auto iterator = iterable.begin(); iterator != iterable.end(); ++iterator)
    if (pred(*iterator))
      return true;
  return false;
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
  
  // If any of the push buttons is pressed
  bool pressed = any_of(buttons, [](const NoteButton &button) { 
    return button.getButtonState() == Button::Pressed;
  });
  // Turn on the LED
  digitalWrite(ledPin, pressed);
}

I don't have any hardware to test it at the moment, but it seems to compile without problems.

@sincos5
Copy link
Author

sincos5 commented Nov 2, 2019

Bussy week, today was the day i had to try this!
Works grate, just one last doubt,
i didnt understood how this part of the code is working
could you explain to me, or sendme a link where i can find the explenation please?

/// Return true if the predicate evaluates to true for at least one of the elements of the iterable
template<class Iterable, class Predicate> bool any_of(const Iterable &iterable, const Predicate &pred) {
  for (auto iterator = iterable.begin(); iterator != iterable.end(); ++iterator)
    if (pred(*iterator))
      return true;
   return false;
}

**im sory i dont know how to comment with code

@tttapa
Copy link
Owner

tttapa commented Nov 2, 2019

You can use the following to format the code:

```cpp
// Your code here
```

The any_of function takes in an array or other collection, and a function (predicate). It loops over the array, and calls the function on each element. If the function returns true for all elements, any_of returns true. If there's at least one element for which the function returns false, any_of returns false as well.

It is roughly based on the standard library std::any_of function: https://en.cppreference.com/w/cpp/algorithm/all_any_none_of

@panakronic
Copy link

panakronic commented Dec 10, 2019

Hi there,

I am trying to connect digital 16 buttons to a single led and have the led turn on and off whenever any of the 16 button is pressed. I have tried adding control_surface mentioned above but is having hard time getting it to work.

I'm not expert in coding, just wondering if anyone can help me out a bit?
Thank you in advanced. My code below is what I have so far with no control surface added:

Mega-Control-Control-Final.zip


#include <MIDI_Controller.h> // Include the library

// Create a two new instances of the class 'Analog', on pins A0 and A1,
// that send MIDI messages with controller 7 (channel volume) on channels 1 and 2
Analog potentiometer1(A0, MIDI_CC::Channel_Volume, 1);
Analog potentiometer2(A1, MIDI_CC::Channel_Volume, 2); // uncomment to use in sketch
Analog potentiometer3(A2, MIDI_CC::Sound_Controller_3, 3);
Analog potentiometer4(A3, MIDI_CC::Sound_Controller_4, 4); // uncomment to use in sketch
Analog potentiometer5(A4, MIDI_CC::Sound_Controller_5, 5);
Analog potentiometer6(A5, MIDI_CC::Sound_Controller_6, 6);
Analog potentiometer7(A6, MIDI_CC::Effects_1, 7);
Analog potentiometer8(A7, MIDI_CC::Effects_2, 8);
Analog potentiometer9(A8, MIDI_CC::Effects_3, 9);
Analog potentiometer10(A9, MIDI_CC::Effects_4, 10);
Analog potentiometer11(A10, MIDI_CC::Effect_Control_1, 11);
Analog potentiometer12(A11, MIDI_CC::Effect_Control_2, 12);



// Create a two new instances of the class 'Digital', on pins 2 and 3,
// that send MIDI messages with note numbers 0x10 and 0x11 on MIDI channel 1
Digital muteButton_A(13, 0x14, 1);
Digital muteButton_B(12, 0x15, 1);
Digital muteButton_C(11, 0x16, 1);
Digital muteButton_D(10, 0x17, 1);

Digital muteButton_E(9, 0x18, 1);
Digital muteButton_F(8, 0x19, 1);
Digital muteButton_G(7, 0x1A, 1);
Digital muteButton_H(6, 0x1B, 1);

Digital muteButton_I(5, 0x1C, 1);
Digital muteButton_J(4, 0x1D, 1);
Digital muteButton_K(3, 0x1E, 1);
Digital muteButton_L(2, 0x1F, 1);

Digital muteButton_M(14, 0x20, 1);
Digital muteButton_N(15, 0x21, 1);
Digital muteButton_O(16, 0x22, 1);
Digital muteButton_P(17, 0x23, 1);


Digital muteButton_Q (18, 0x33, 2);
Digital muteButton_R (19, 0x34, 2);





// Create a new bank that has two tracks per bank
Bank bank(16);

// Create a new bank selector that changes the bank setting of the bank we just created
// It has pushbuttons connected to pins 11 and 12 that increment or decrement the bank setting,
// and 4 LEDs to pins 4, 5, 6 and 7 that display the current bank setting.
BankSelector bankSelector(bank, { 21, 20 }, {46, 48, 50, 52 } );

/* Alternatively, you can use arrays for the pin numbers:

   const pin_t buttonPins[] = { 11, 12 };
   const pin_t ledPins[] = { 4, 5, 6, 7 };

   BankSelector bankSelector(bank, buttonPins, ledPins);
*/

/*_______________________________________________________________________________________________________________________________________*/

void setup() {
  // Add the created objects to the bank
  bank.add(potentiometer1, Bank::CHANGE_CHANNEL); // When the bank setting is changed, change the channel of the potentiometer
  bank.add(potentiometer2, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer3, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer4, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer5, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer6, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer7, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer8, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer9, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer10, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer11, Bank::CHANGE_CHANNEL);
  bank.add(potentiometer12, Bank::CHANGE_CHANNEL);


  bank.add(muteButton_A, Bank::CHANGE_ADDRESS); // When the bank setting is changed, change the address (note number) of the mute button
  bank.add(muteButton_B, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_C, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_D, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_E, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_F, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_G, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_H, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_I, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_J, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_K, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_L, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_M, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_N, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_O, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_P, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_Q, Bank::CHANGE_ADDRESS);
  bank.add(muteButton_R, Bank::CHANGE_ADDRESS);
}

/*_______________________________________________________________________________________________________________________________________*/

void loop() {
  // Refresh the MIDI controller (check whether the inputs have changed since last time, if so, send the new value over MIDI)
  // It also refreshes the bank selector
  MIDI_Controller.refresh();
}


tttapa added a commit to tttapa/Control-Surface that referenced this issue Dec 10, 2019
tttapa added a commit to tttapa/Control-Surface-doc that referenced this issue Dec 10, 2019
@tttapa
Copy link
Owner

tttapa commented Dec 10, 2019

I added an example to Control Surface. See https://tttapa.github.io/Control-Surface-doc/Doxygen/de/d26/MIDI_controller-97_8ino-example.html

I haven't tested it, since I don't have an Arduino Mega, but it compiles fine.

@panakronic
Copy link

panakronic commented Dec 13, 2019 via email

tttapa added a commit to tttapa/Control-Surface that referenced this issue Dec 13, 2019
@tttapa
Copy link
Owner

tttapa commented Dec 13, 2019

It looks like I forgot to add a MIDI interface to the example I posted earlier, my apologies.

It should be fixed now.

@panakronic
Copy link

panakronic commented Dec 13, 2019 via email

@tttapa
Copy link
Owner

tttapa commented Dec 13, 2019

Well, that's unfortunate, it's a bug in the compiler.
You could try installing the Arduino IDE from the Arduino website, not from the Windows store.

@panakronic
Copy link

This is what I though too. I will try reinstall Arduino IDE.
I will for sure get back to you on the progress. Once again, thank you!!!
:)

@tttapa
Copy link
Owner

tttapa commented Dec 13, 2019

It seems to work on Linux using the Arduino IDE 1.8.9 and AVR Core version 1.8.1.

@panakronic
Copy link

panakronic commented Dec 13, 2019

Hi tttapa,

It's working!!!

You were absolutely correct with the Arduino IDE error, all I did was update the Arduino IDE to the newest version and problem solved.

See it work here: https://youtu.be/o1qB8_DQy-U

I have made some modification on the potentiometer part from change_channel to change_address.
Here is my final script:

/**
 * <https://github.com/tttapa/MIDI_controller/issues/97#issuecomment-564247602>
 * 
 * Many bankable potentiometers and buttons. Bank selector displays bank setting
 * using LEDs.  
 * If any of the buttons is pressed, the LED on pin 22 is turned on.
 * 
 * @boards  Mega
 */
 
#include <Control_Surface.h>
 
#include <AH/STL/algorithm> // std::any_of
 
USBMIDI_Interface midi; // MIDI Interface to use
 
Bank<4> bank(16);
 
// Create a new bank selector that changes the bank setting of the bank we just
// created.
// It has push buttons connected to pins 21 and 20 that increment or decrement
// the bank setting, and 4 LEDs to pins 46, 48, 50, 52 that display the current
// bank setting.
IncrementDecrementSelectorLEDs<4> bankSelector = {
  bank,
  {21, 20},         // button pins
  {46, 48, 50, 52}, // LED pins
};
 
using namespace MIDI_CC;
Bankable::CCPotentiometer potentiometers[] = {
  {bank,  A0, {0x46, CHANNEL_2}},
  {bank,  A1, {0x47, CHANNEL_2}},
  {bank,  A2, {0x48, CHANNEL_2}},
  {bank,  A3, {0x49, CHANNEL_2}},
  {bank,  A4, {0x4A, CHANNEL_2}},
  {bank,  A5, {0x4B, CHANNEL_2}},
  {bank,  A6, {0x4C, CHANNEL_2}},
  {bank,  A7, {0x4D, CHANNEL_2}},
  {bank,  A8, {0x4E, CHANNEL_2}},
  {bank,  A9, {0x4F, CHANNEL_2}},
  {bank,  A10, {0x50, CHANNEL_2}},
  {bank,  A11, {0x51, CHANNEL_2}},
};
 
Bankable::NoteButton muteButtons[] = {
  {bank, 13, 0x14},
  {bank, 12, 0x15},
  {bank, 11, 0x16},
  {bank, 10, 0x17},
  {bank, 9, 0x18},
  {bank, 8, 0x19},
  {bank, 7, 0x1A},
  {bank, 6, 0x1B},
  {bank, 5, 0x1C},
  {bank, 4, 0x1D},
  {bank, 3, 0x1E},
  {bank, 2, 0x1F},
  {bank, 14, 0x20},
  {bank, 15, 0x21},
  {bank, 16, 0x22},
  {bank, 17, 0x23},
  {bank, 18, {0x33, CHANNEL_2}},
  {bank, 19, {0x34, CHANNEL_2}},
  
  {bank, 49, {0x35, CHANNEL_2}},
  {bank, 51, {0x36, CHANNEL_2}},
  {bank, 53, {0x37, CHANNEL_2}},

};
 
constexpr pin_t ledPin = 22;
 
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
 
void setup() {
  Control_Surface.begin();
  pinMode(ledPin, OUTPUT);
}
 
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
 
void loop() {
  Control_Surface.loop();
 
  // Function that checks if a given button is pressed
  auto checkButtonPressed = [](const Bankable::NoteButton &button) {
    return button.getButtonState() == Button::Pressed;
  };
  // If any of the push buttons is pressed
  bool pressed = std::any_of(std::begin(muteButtons), std::end(muteButtons),
                             checkButtonPressed);
  // Turn on the LED
  digitalWrite(ledPin, pressed);
}

@tttapa
Copy link
Owner

tttapa commented Dec 13, 2019

Glad to hear!

@panakronic
Copy link

panakronic commented Dec 14, 2019 via email

@tttapa
Copy link
Owner

tttapa commented Dec 14, 2019

You can use the CCRotaryEncoder class.

There's no example yet, but you can find the arguments on the documentation page.

#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library.
#include <Control_Surface.h> // Include the Control Surface library

CCRotaryEncoder enc = {{2, 3}, {MCU::V_POT_1, CHANNEL_1}};

@panakronic
Copy link

panakronic commented Oct 16, 2020

Hi there,

I have a question regarding "Connecting 2 or more buttons to a single LED"

I am trying to use matrix buttons alongside regular buttons. Is there a way to make the matrix buttons to work with constexpr pin_t ledPin = 10; ?

This is what I have so far:


/**
 * @example Ex.11.Button-Matrix.ino
 *
 * This is an example of the ButtonMatrix class of the Control_Surface library.
 *
 * Connect a 4 × 3 matrix of buttons with the rows to pins 2, 3, 4 and 5,
 * and the columns to pins 6, 7 and 8.  
 * Pull-up resistors are not necessary, because the internal ones will be used.
 *
 * If you want to be able to press multiple buttons at once, add a diode
 * in series with each button, as shown in the following schematic:
 *
 * @image html Button-matrix.svg
 *
 * The note numbers are specified in the `addresses` array.  
 * Map accordingly in your DAW or DJ software.
 *
 * Written by tttapa, 24/09/2017  
 * https://github.com/tttapa/Control-Surface
*/

#include <Control_Surface.h>
 // Custom callback to handle output for a selector.
class MySelectorCallback {
  public:
    // Constructor
    MySelectorCallback(pin_t redLED, pin_t greenLED, pin_t blueLED)
      : redLED(redLED), greenLED(greenLED), blueLED(blueLED) {}

    // Begin function is called once by Control Surface.
    // Use it to initialize everything.
    void begin() {
      pinMode(redLED, OUTPUT);
      pinMode(greenLED, OUTPUT);
      pinMode(blueLED, OUTPUT);
      show(0);
    }

    // Update function is called continuously by Control Surface.
    // Use it to implement things like fading, blinking ...
    void update() {}

    // Update function with arguments is called when the setting
    // changes.
    // Use it to update the LEDs.
    void update(setting_t oldSetting, setting_t newSetting) {
      (void) oldSetting; // unused in this example
      show(newSetting);
    }

  private:
    // Show the color of the given setting.
    void show(setting_t setting) {
      uint8_t color = getColor(setting);
      digitalWrite(redLED, color & 0b001 ? HIGH : LOW);
      digitalWrite(greenLED, color & 0b010 ? HIGH : LOW);
      digitalWrite(blueLED, color & 0b100 ? HIGH : LOW);
    }

    // Convert the given setting to a 3-bit RGB color value.
    static uint8_t getColor(setting_t setting) {
      switch (setting) {
        case 0: return 0b011;
        case 1: return 0b010;
        case 2: return 0b101;
        case 3: return 0b110;
        default: return 0b001;
      }
    }

  private:
    // Member variables to remember the pin numbers of the LEDs.
    pin_t redLED, greenLED, blueLED;
};
 
#include <AH/STL/algorithm> // std::any_of
 
USBMIDI_Interface midi;
Bank<4> bank = {16}; // 4 banks, 6 addresse per banks


  GenericIncrementDecrementSelector<4, MySelectorCallback> selector = {
  bank,         // bank to manage
  {11, 12, 13}, // red, green, blue LED pins 
                // (this is the MySelectorCallback constructor defined above)
  {8, 9},       // incr/decr button pins
  Wrap::Wrap,   // wrap around when reaching setting 6
};

 
AddressMatrix<4, 4> notes = {{
  {1, 2, 3, 4},
  {5, 6, 7, 8},
  {9, 10, 11, 12},
  {13, 14, 15, 16}
}};
 
Bankable::NoteButtonMatrix<4, 4> buttons = {
  bank,  
  {14, 15, 16, 17},    // row pins (outputs, driven low-Z low !)
  {18, 19, 20, 21}, // column pins (inputs, hi-Z)
 notes,     // address matrix
  CHANNEL_1, //
};


using namespace MIDI_CC;
Bankable::CCPotentiometer potentiometers[] = {
{bank,  A0, {0x46, CHANNEL_2}},


}; 
Bankable::NoteButton muteButtons[] = {

  
  {bank, 23, 0x20},
  {bank, 25, 0x21},




};
 
constexpr pin_t ledPin = 10;
 
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
 
void setup() {
  Control_Surface.begin();
  pinMode(ledPin, OUTPUT);
}
 
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
 
void loop() {
  Control_Surface.loop();
 
  // Function that checks if a given button is pressed
  auto checkButtonPressed = [](const Bankable::NoteButton &button) {
    return button.getButtonState() == Button::Pressed;
  };
  // If any of the push buttons is pressed
  bool pressed = std::any_of(std::begin(muteButtons), std::end(muteButtons),
                             checkButtonPressed);

                             
  // Turn on the LED
  digitalWrite(ledPin, pressed);
}



@tttapa
Copy link
Owner

tttapa commented Oct 17, 2020

I am trying to use matrix buttons alongside regular buttons. Is there a way to make the matrix buttons to work with constexpr pin_t ledPin = 10; ?

I'm not sure what you mean by that. A button matrix reads buttons, what does it have to do with a ledPin constant?

If you want to use matrix buttons as "regular" buttons, you have two options: inherit from the ButtonMatrix class, or implement the ExtendedIOElement interface for a scanning matrix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants