tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.26k stars 140 forks source link

button toggle and momentary + LED #235

Closed lmeucchi closed 2 years ago

lmeucchi commented 4 years ago

Hi how are you? I have 9 buttons and 9 leds, of which 8 are connected to mux 4051 ..... the button that remains is connected directly to the arduino, each button has a led. Looking for examples and answers I was able to make this code, which I would use to make a pedalboard for Guitar Rig. My question is that when I change CCButtonLatched to CCButton it gives me this error "class CS :: CCButton 'has no member named' getState"

What is the correct way to write the code to be able to choose if I need a toggle or common button at any time?

Thank you very much


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

// Create two MIDI interfaces
USBMIDI_Interface usbmidi;
HardwareSerialMIDI_Interface serialmidi = {Serial1, MIDI_BAUD};

// Instantiate a MIDI Interface to use
//USBMIDI_Interface midi;

// Instantiate a MIDI Debug interface at 115200 baud.
//USBDebugMIDI_Interface midi = 115200;

// Instantiate a CCAbsoluteEncoder object
CCAbsoluteEncoder enc = {
  {2, 3},       // pins
  MIDI_CC::Foot_Controller, // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};

// Instantiate an analog multiplexer
CD74HC4051 mux = {
//  A0,       // Analog input pin
    4,        //Digital input pin
  {5, 6, 7} // Address pins S0, S1, S2
};

//Instantiate a shift register 8 bits
SPIShiftRegisterOut<8> sreg = {
  10,       // Latch pin (ST_CP)
  MSBFIRST, // Byte order
};

CCButtonLatched BotonesMux[] = {
  {mux.pin(0), {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}},
  {mux.pin(1), {MIDI_CC::General_Purpose_Controller_2, CHANNEL_1}},
  {mux.pin(2), {MIDI_CC::General_Purpose_Controller_3, CHANNEL_1}},
  {mux.pin(3), {MIDI_CC::General_Purpose_Controller_4, CHANNEL_1}},
  {mux.pin(4), {MIDI_CC::General_Purpose_Controller_5, CHANNEL_1}},
  {mux.pin(5), {MIDI_CC::General_Purpose_Controller_6, CHANNEL_1}},
  {mux.pin(6), {MIDI_CC::General_Purpose_Controller_7, CHANNEL_1}},
  {mux.pin(7), {MIDI_CC::General_Purpose_Controller_8, CHANNEL_1}},

};

CCButtonLatched Botones = {
  8, {MIDI_CC::Damper_Pedal, CHANNEL_1}
};

// Instantiate a CCPotentiometer object
CCPotentiometer Potenciometros[] = {
  {A0, MIDI_CC::Modulation_Wheel},
  {A1, MIDI_CC::Breath_Controller},
  {A2, MIDI_CC::Channel_Volume},
  {A3, MIDI_CC::Balance},
  {A4, MIDI_CC::Pan},
  {A5, MIDI_CC::Portamento_Time},
};

const pin_t LedPedal = 9;

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

   pinMode(LedPedal, OUTPUT);

}

// Update the Control Surface
void loop() {
  Control_Surface.loop();

  uint8_t i = 0;
  for (CCButtonLatched &button : BotonesMux)
    sreg.digitalWrite(i++, button.getState());

static bool ledState = LOW;
  // Read the digital input, debounce the signal, and check the state of
  // the button:
  if (Botones.getButtonState() == Button::Falling) {
    ledState = !ledState; // Invert the state of the LED
    // Update the LED with the new state
    digitalWrite(LedPedal, ledState ? HIGH : LOW);
  }

}
tttapa commented 4 years ago

I don't really understand what you mean. CCButton doesn't really have an internal state, so it doesn't have a getState method. It does have a getButtonState, which returns the state of the button (see Button::State).

What is the correct way to write the code to be able to choose if I need a toggle or common button at any time?

Do you mean any time at run-time or any time at compile-time?
If you want to switch between toggle or normal mode at run-time, you have to create one CCButton and one CCButtonLatched for each pin. Then at the end of the setup, you disable all CCButtonLatched elements (see CCButtonLatched::disable()). In your loop, to switch from normal mode to latched mode, you disable all CCButton elements and you enable all CCButtonLatched elements (using the enable and disable methods).
At the same time, you'll have to switch to different LED code, depending on which mode is active.

Something like this, perhaps (untested):

#include <Control_Surface.h>

// Instantiate a MIDI Interface to use
USBMIDI_Interface midi;

CD74HC4051 mux = {
  4,        // Digital input pin
  {5, 6, 7} // Address pins S0, S1, S2
};

SPIShiftRegisterOut<8> sreg = {
  10,       // Latch pin (ST_CP)
  MSBFIRST, // Byte order
};

CCButton botonesMux[] = {
  {mux.pin(0), {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}},
  {mux.pin(1), {MIDI_CC::General_Purpose_Controller_2, CHANNEL_1}},
  {mux.pin(2), {MIDI_CC::General_Purpose_Controller_3, CHANNEL_1}},
  {mux.pin(3), {MIDI_CC::General_Purpose_Controller_4, CHANNEL_1}},
  {mux.pin(4), {MIDI_CC::General_Purpose_Controller_5, CHANNEL_1}},
  {mux.pin(5), {MIDI_CC::General_Purpose_Controller_6, CHANNEL_1}},
  {mux.pin(6), {MIDI_CC::General_Purpose_Controller_7, CHANNEL_1}},
  {mux.pin(7), {MIDI_CC::General_Purpose_Controller_8, CHANNEL_1}},
};

CCButtonLatched botonesMuxLatched[] = {
  {mux.pin(0), {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}},
  {mux.pin(1), {MIDI_CC::General_Purpose_Controller_2, CHANNEL_1}},
  {mux.pin(2), {MIDI_CC::General_Purpose_Controller_3, CHANNEL_1}},
  {mux.pin(3), {MIDI_CC::General_Purpose_Controller_4, CHANNEL_1}},
  {mux.pin(4), {MIDI_CC::General_Purpose_Controller_5, CHANNEL_1}},
  {mux.pin(5), {MIDI_CC::General_Purpose_Controller_6, CHANNEL_1}},
  {mux.pin(6), {MIDI_CC::General_Purpose_Controller_7, CHANNEL_1}},
  {mux.pin(7), {MIDI_CC::General_Purpose_Controller_8, CHANNEL_1}},
};

// Switch between normal and latched mode using push button on pin 2:
Button modeSwitch = 2;
bool latchedMode = false;

// Led to display normal/latched mode
const pin_t ledPedal = 9;

void setup() {
  Control_Surface.begin();
  modeSwitch.begin();
  pinMode(ledPedal, OUTPUT);
  CCButtonLatched::disable(botonesMuxLatched);
}

void loop() {
  Control_Surface.loop();

  if (modeSwitch.update() == Button::Falling) {
    latchedMode = !latchedMode;
    if (latchedMode) {
      CCButton::disable(botonesMux);
      CCButtonLatched::enable(botonesMuxLatched);
    } else {
      CCButtonLatched::disable(botonesMuxLatched);
      CCButton::enable(botonesMux);
    }
    digitalWrite(ledPedal, latchedMode ? HIGH : LOW);
  }

  if (latchedMode) {
    uint8_t i = 0;
    for (CCButtonLatched &button : botonesMuxLatched)
      sreg.digitalWrite(i++, button.getState());
  } else {
    uint8_t i = 0;
    for (CCButton &button : botonesMux)
      sreg.digitalWrite(i++, button.getButtonState() == Button::Released ? LOW : HIGH);
  }
}
ravedya commented 4 years ago

Is there a way to make ten button through mux since the General_Purpose_Controller are only 8?

tttapa commented 4 years ago

You can use any valid MIDI control change address: https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2

lmeucchi commented 4 years ago

Yes!!!...It Works

Thank you

ravedya commented 4 years ago

Thank you man!

ghufronmasum commented 4 years ago

How could I change the behaviour of the latched mode so it could delete the previous state of the button by pressing the other button?

tttapa commented 4 years ago

I'm not sure what you mean. A latched button is always in one of two states, it's either enabled or disabled, you cannot delete the state.
Please describe what you actually want to do.

ghufronmasum commented 4 years ago

I wanted that If there's another button pressed, it turns the other button's led off and turn on the led of the button I pressed.

tttapa commented 4 years ago

In that case, CCButtonLatched is probably not the right class to use. See https://github.com/tttapa/Control-Surface/issues/136#issuecomment-602193421.