Control-Surface icon indicating copy to clipboard operation
Control-Surface copied to clipboard

Incrément Button

Open anoat opened this issue 4 years ago • 7 comments

bonjour, je tiens tout d'abord a te remercier pour cette fabuleuse librairie. Parmi plusieurs controle midi je souhaite utiliser un switch momentary pour incrementer un CC midi de 35 valeurs. Au debut value = 0 , puis lorsque jappuie une premiere fois value=35, une deuxieme fois value=70, une troisième fois value= 105, une quatrième fois retour à value= 0.

j'imagine que cela est possible mais je ne vois pas comment proceder, peut-être que tu aurais quelques piste ?

merci beaucoup hello, first of all I want to thank you for this fabulous bookstore. Among several midi controls I want to use a momentary switch to increment a midi CC of 35 values. At the beginning value = 0, then when I press for the first time value = 35, a second time value = 70, a third time value = 105, a fourth time return to value = 0.

I imagine that this is possible but I do not see how to proceed, maybe you would have some leads?

thank you so much

anoat avatar Jun 17 '21 05:06 anoat

A possible approach would be to use something similar to the CCSelection class introduced here: https://github.com/tttapa/Control-Surface/issues/136#issuecomment-602223025

#include <Control_Surface.h>

template<setting_t N>
class CCValueSelection : public Selectable<N> {
public:
  CCValueSelection(MIDIAddress address, uint8_t delta = 1, uint8_t base = 0)
    : address{ address }, delta{ delta }, base{ base } {}

  void select(setting_t setting) override {
    setting = Selectable<N>::validateSetting(setting);
    Control_Surface.sendCC(address, base + setting * delta);
  }

private:
  MIDIAddress address;
  uint8_t delta, base;
};

CCValueSelection<4> ccsel{ MIDI_CC::Channel_Volume, 35, 0 };
IncrementSelector<4> incbtn{ ccsel, 2 }; // pin number

USBDebugMIDI_Interface midi;

void setup() {
  Control_Surface.begin();
}

void loop() {
  Control_Surface.loop();
}

tttapa avatar Jun 17 '21 15:06 tttapa

Thank you for your quick reply,

the code is compiling, I will try it for real soon. I have several incremental buttons, 2 with 4 values ​​and 10 with 3 values. For the 3 value buttons I tried to set up a "for" loop with arrays, but the code does not compile.

I have another question, I have several potentiometers which I want to put in 14 bits, I used "CC14Potentiometer" (issues # 202). To generate the 14bits at noon is sent on 2 control change 1-31, 2-32, 3-33, ...?

#include "Adafruit_TLC5947.h"
#include <Control_Surface.h>

#define NUM_TLC5974 4
#define data   11
#define clock   13
#define latch   10
#define oe  -1

Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);

char incSEL3[2] = {incbtn3, incbtn4};
char SEL3[2] = {selx, selxx};


constexpr size_t numbuttons = 13;
uint8_t tlcpins[numbuttons] = {5,  24, 25, 23,
                               3, 15, 22, 19,
                               6, 4, 3, 23, 0
                              };

CD74HC4067 mux1  = { A0,   {20, 21, 22, 23},};
CD74HC4067 mux7  = { A15,  {20, 21, 22, 23},};
CD74HC4067 mux8  = { A16,  {20, 21, 22, 23},};

class CC14Potentiometer : public MIDIFilteredAnalog<ContinuousCCSender14<10>> {
  public:
    CC14Potentiometer(pin_t analogPin, MIDIAddress address)
      : MIDIFilteredAnalog(analogPin, address, {}) {}
};

CC14Potentiometer potentiometer[] = {
  {mux1.pin(0), {11, CHANNEL_1}},
  {mux1.pin(4), {10, CHANNEL_1}},
  {mux1.pin(5), {26, CHANNEL_1}},
  {mux1.pin(7), {7, CHANNEL_1}},
  {mux1.pin(8), {9, CHANNEL_1}},
  {mux1.pin(9), {25, CHANNEL_1}},
  {mux1.pin(13), {8, CHANNEL_1}},
  {mux1.pin(14), {23, CHANNEL_1}},

  {mux7.pin(1), {4, CHANNEL_1}},
  {mux7.pin(13), {5, CHANNEL_1}},
  {mux7.pin(15), {6, CHANNEL_1}},

  {mux8.pin(0), {2, CHANNEL_1}},
  {mux8.pin(3), {3, CHANNEL_1}},
  {mux8.pin(6), {22, CHANNEL_1}},
  {mux8.pin(8), {1, CHANNEL_1}},
  {mux8.pin(12), {24, CHANNEL_1}},
  {mux8.pin(15), {0, CHANNEL_1}},

};

template<setting_t N>

class CCValueSelection : public Selectable<N> {
  public:

    CCValueSelection(MIDIAddress address, uint8_t delta = 1, uint8_t base = 0)
      : address{ address }, delta{ delta }, base{ base } {}

    void select(setting_t setting) override {
      setting = Selectable<N>::validateSetting(setting);
      Control_Surface.sendCC(address, base + setting * delta);
    }

  private:
    MIDIAddress address;
    uint8_t delta, base;

};

for (int k = 0; k < 2 ; k++) {
  CCValueSelection<3> SEL3{{82, CHANNEL_1}, (127 / 3), 0 };
  IncrementSelector<3> incSEL3{  SEL3, mux1.pin(3) }; // pin number
}

CCValueSelection<4> cutoff{{112, CHANNEL_1}, (127 / 4), 0 };
IncrementSelector<4> incbtn1{ cutoff, mux1.pin(6) }; // pin number

CCValueSelection<4> bend{{90, CHANNEL_1}, (127 / 4), 0 };
IncrementSelector<4> incbtn2{ bend, mux7.pin(14) }; // pin number


CCButtonLatched button[] = {

  { mux1.pin(1), {111, CHANNEL_1}},
  //  { mux1.pin(3), {82, CHANNEL_1}},39&40,
  //  { mux1.pin(6), {112, CHANNEL_1}}, 34&35&36&37
  { mux1.pin(10), {84, CHANNEL_1}},
  { mux1.pin(12), {106, CHANNEL_1}},
  { mux1.pin(15), {86, CHANNEL_1}},

  // { mux7.pin(0), {92, CHANNEL_1}}, 17&18,
  { mux7.pin(3), {99, CHANNEL_1}},
  { mux7.pin(5), {101, CHANNEL_1}},
  { mux7.pin(8), {98, CHANNEL_1}},
  { mux7.pin(11), {96, CHANNEL_1}},
  // { mux7.pin(14), {90, CHANNEL_1}},20&21

  { mux8.pin(1), {100, CHANNEL_1}},
  { mux8.pin(4), {87, CHANNEL_1}},
  { mux8.pin(5), {83, CHANNEL_1}},
  { mux8.pin(9), {97, CHANNEL_1}},
  { mux8.pin(13), {84, CHANNEL_1}},

};


void setup() {

  tlc.begin();
  Control_Surface.begin();
}

void loop() {

  Control_Surface.loop();

  for (uint8_t i = 0; i < numbuttons; ++i) {
    if (button[i].getButtonState() == Button::Falling) {
      tlc.setPWM(tlcpins[i], 4095 * button[i].getState());
    }
  }
  tlc.write();
}

anoat avatar Jun 18 '21 08:06 anoat

For the 3 value buttons I tried to set up a "for" loop with arrays, but the code does not compile.

You can't use for-loops for declarations. Try this:

CCValueSelection<3> SEL3[] {
  { {82, CHANNEL_1}, 127 / 3, 0 },
  { {83, CHANNEL_1}, 127 / 3, 0 },
  { {84, CHANNEL_1}, 127 / 3, 0 },
};
IncrementSelector<3> incSEL3[] {
  { SEL3[0], mux1.pin(3) },
  { SEL3[1], mux1.pin(4) },
  { SEL3[2], mux1.pin(5) },
};

I have another question, I have several potentiometers which I want to put in 14 bits, I used "CC14Potentiometer" (issues # 202). To generate the 14bits at noon is sent on 2 control change 1-31, 2-32, 3-33, ...?

CC messages only carry 7 bits of data, so if you want 14 bits of precision you have to send 2 CC messages. IIRC, the MIDI standard specifies CC 0-31 for the most significant bits and CC 32-63 for the least significant bits, so you should see CC#1 and CC#33 used together, not CC#1 and CC#31.

at noon

Feel free to answer in French, you don't have to translate it.

tttapa avatar Jun 18 '21 12:06 tttapa

Ca compile ! Merci encore ! Cependant comme le dit le fameux dicton " jamais deux sans trois", il me reste une ultime requête. Le bouton incrémentateur doit allumer et éteindre en fonction de la valeurs MIDI des leds.
led 1= on si value<= 127.1/3 led 2 =on si value> 127.2/1 && <= 127.2/3 led 3 =on si value> 127.2/3

Mon idée initiale était de transférer dans une variable (CUTOFF) l' état du bouton sélecteur ( 0 , 1 , 2 ), puis utilisé cette variable pour sélectionner dans un tableau la sortie correspondante pour mon drivers led. tlc.setPWM(tlc3[CUTOFF], 4095);

J'ai tenté de recupéréer cet état dans plusieurs variable ( SEL3, incSEL3) avec la l'operateur A = CUTOFF, mais ça ne marche pas...

#include "Adafruit_TLC5947.h"
#include <Control_Surface.h>

#define NUM_TLC5974 4
#define data   11
#define clock   13
#define latch   10
#define oe  -1

Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);

byte CUTOFF ;

uint8_t tlc3[3] = {34, 35, 36};

CD74HC4067 mux1  = { A0,   {20, 21, 22, 23},};
CD74HC4067 mux7  = { A15,  {20, 21, 22, 23},};
CD74HC4067 mux8  = { A16,  {20, 21, 22, 23},};

class CC14Potentiometer : public MIDIFilteredAnalog<ContinuousCCSender14<10>> {
  public:
    CC14Potentiometer(pin_t analogPin, MIDIAddress address)
      : MIDIFilteredAnalog(analogPin, address, {}) {}
};

template<setting_t N>

class CCValueSelection : public Selectable<N> {
  public:

    CCValueSelection(MIDIAddress address, uint8_t delta = 1, uint8_t base = 0)
      : address{ address }, delta{ delta }, base{ base } {}

    void select(setting_t setting) override {
      setting = Selectable<N>::validateSetting(setting);
      Control_Surface.sendCC(address, base + setting * delta);

    }

  private:
    MIDIAddress address;
    uint8_t delta, base;
};


CCValueSelection<3> SEL3[] {
  { {82, CHANNEL_1}, 127 / 3, 0 },
  { {92, CHANNEL_1}, 127 / 3, 0 },
};
IncrementSelector<3> incSEL3[] {
  { SEL3[0], mux1.pin(3) },
  { SEL3[1], mux7.pin(0) },
};

void setup() {

  tlc.begin();
  Control_Surface.begin();
}

void loop() {
  Control_Surface.loop();

  tlc.setPWM(tlc3[CUTOFF], 4095);

  tlc.write();

}

anoat avatar Jun 19 '21 06:06 anoat

Re,

Bon, je me suis un peu creusé la tete, et finalement j'ai une piste ( je n'ai pas encore essayé).

#include "Adafruit_TLC5947.h"
#include <Control_Surface.h>

#define NUM_TLC5974 4
#define data   11
#define clock   13
#define latch   10
#define oe  -1

Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);

uint8_t tlc4[4] = {34, 35, 36, 37 };

CD74HC4067 mux1  = { A0,   {20, 21, 22, 23},};
CD74HC4067 mux7  = { A15,  {20, 21, 22, 23},};
CD74HC4067 mux8  = { A16,  {20, 21, 22, 23},};

template<setting_t N>

class CCValueSelection : public Selectable<N> {
  public:

    CCValueSelection(MIDIAddress address, uint8_t delta = 1, uint8_t base = 0)
      : address{ address }, delta{ delta }, base{ base } {}

    void select(setting_t setting) override {
      setting = Selectable<N>::validateSetting(setting);

      Control_Surface.sendCC(address, base + setting * delta);
    }

  private:
    MIDIAddress address;
    uint8_t delta, base;
};

CCValueSelection<4> SEL4[] {

  { {112, CHANNEL_1}, 127 / 4, 0 },
  { {90, CHANNEL_1}, 127 / 4, 0 },
};
IncrementSelector<4> incSEL4[] {

  { SEL4[0], mux1.pin(6) },
  { SEL4[1], mux7.pin(14) },
};

void setup() {

  tlc.begin();
  Control_Surface.begin();
}

void loop() {
  Control_Surface.loop();
  tlc.write();
}

void myControlChange(byte channel, byte control, byte value) {
  for (int i = 0; i < 4; i++) {
    if ( control == 112 && value < 127 / 4 * i && value > 127 / 4 * i - 127 / 4) {
      tlc.setPWM(tlc4[i], 4095);
    }
  }
}

anoat avatar Jun 20 '21 19:06 anoat

It's not entirely clear what you're trying to do, but can't you update the LEDs here? You already have the setting:

void select(setting_t setting) override {
  setting = Selectable<N>::validateSetting(setting);
  // you can update the LEDs here, based on the value of `setting`, which will be 0, 1 or 2
  Control_Surface.sendCC(address, base + setting * delta);
}

tttapa avatar Jun 24 '21 20:06 tttapa

Thank you very much for your help Peter,

By dint of searching I ended up finding the solution. The goal was to light leds according to a midday value. Example: value of CC 82 <32 = led 1 on / led 2 & 3 & 4 = off value of CC 82 <64 & > 32 = led 2 on / led 1 & 3 & 4 = off value of CC 82 <96 & > 64 = led 3 on / led 1 & 2 & 4 = off value of CC 82 > 92 = led 4 on / led 1 & 2 & 3 = off `#include "Adafruit_TLC5947.h" #include <Control_Surface.h> USBMIDI_Interface midi;

#define NUM_TLC5974 2 #define data 11 #define clock 13 #define latch 10 #define oe 3

Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);

byte adressCC = 112 ; byte cutoff;

byte tlc4[4] = {32 , 33, 34, 35 };

CD74HC4067 mux1 = { A0, // analog pin {20, 21, 22, 23}, // Address pins S0, S1, S2, S3 // 13, // Optionally, specify the enable pin };

CD74HC4067 mux7 = { A15, // analog pin {20, 21, 22, 23}, // Address pins S0, S1, S2, S3 // 13, // Optionally, specify the enable pin };

CD74HC4067 mux8 = { A16, // analog pin {20, 21, 22, 23}, // Address pins S0, S1, S2, S3 // 13, // Optionally, specify the enable pin };

template<setting_t N>

class CCValueSelection : public Selectable<N> { public:

CCValueSelection(MIDIAddress address, uint8_t delta = 32, uint8_t base = 0)
  : address{ address }, delta{ delta }, base{ base } {}

void select(setting_t setting) override {
  setting = Selectable<N>::validateSetting(setting);

  Control_Surface.sendCC(address, base + setting * delta);
  for (uint8_t i = 0; i < 3; ++i) {
    if (address == adressCC) {
      cutoff =   setting ;
    }
  }
}

private: MIDIAddress address; uint8_t delta, base; };

CCValueSelection<4> SEL4[] {

{ {112, CHANNEL_1}, 32, 0 }, { {90, CHANNEL_1}, 32, 0 }, { {92, CHANNEL_1}, 32, 0 }, }; IncrementSelector<4> incSEL4[] {

{ SEL4[0], mux1.pin(6) }, { SEL4[1], mux7.pin(14) }, { SEL4[2], mux7.pin(0) }, };

void setup() {

tlc.begin(); if (oe >= 0) { pinMode(oe, OUTPUT); digitalWrite(oe, LOW); Control_Surface.begin(); } }

void loop() { Control_Surface.loop(); tlc.write(); delay(10);

for (uint8_t i = 0; i < 4; ++i) { if (i != cutoff ) { tlc.setPWM(tlc4[i], 0 ); } else tlc.setPWM(tlc4[i], 4092); } }`

anoat avatar Jun 25 '21 18:06 anoat