tttapa / Control-Surface

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

Пример CCIncrementDecrementButtons.ino #988

Closed Alexandr010360 closed 8 months ago

Alexandr010360 commented 9 months ago

Hello! Thank you for the amazing library with which I can create my own MIDI system project for the accordion! But I ran into one problem! I need a midi channel volume control function using two buttons, as shown in the CCIncrementDecrementButtons example.ino Pressing the minus button gives a result of one and pressing the plus button gives a maximum value of 127. There are no intermediate values! Everything works fine with the encoder class, but not with the buttons! I can't understand the reason! Please help me!`

include // Include the Control Surface library

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

// Instantiate a CCIncrementDecrementButtons object CCIncrementDecrementButtons buttons { {2, 3}, // Button pins: 2 increments, 3 decrements {MIDI_CC::Channel_Volume, CHANNEL_3}, };

void setup() { // Use the Mackie Control protocol for sending relative MIDI CC messages. RelativeCCSender::setMode(TWOS_COMPLEMENT);

Control_Surface.begin(); // Initialize Control Surface Serial.begin(57600); }

void loop() { Control_Surface.loop(); // Update the control surface }`

tttapa commented 9 months ago

Hi, please open one discussion per issue.

The CCIncrementDecrementButtons class is intended for use with relative controls. A value of 1 should be interpreted as +1 and a value of 127 as -1. See relativeCCmode for details.

If you want the buttons to send absolute values, you'll need to keep track of the absolute value somehow. I'd recommend having a look at the Custom-MIDI-Output-Element.ino example. You can use the implementation of MIDIIncrementDecrementButtons as inspiration.

Alexandr010360 commented 9 months ago

Good afternoon! Thanks for the advice! I'll try to figure it out using other examples...

Alexandr010360 commented 9 months ago

Hello! Could you add an example sketch of how to use buttons to send absolute values, as is done in the example with an absolute encoder? I can't do anything with the implementation of MIDIIncrementDecrementButtons...

Alexandr010360 commented 9 months ago

При компиляции пишет ошибку exit status 1 invalid use of template-name 'CS::MIDIIncrementDecrementButtons' without an argument list

laps78 commented 9 months ago

Александр010360, у вас синтаксическая ошибка в коде - вызов сущности (метода?) без обязательных аргументов. КурИте документацию. Возможно, вы считаете, что ошибка не в Вашем коде, а в коде библиотеки?

tttapa commented 9 months ago

You could do something like this:

#include <Control_Surface.h>

BEGIN_CS_NAMESPACE

class CCAbsoluteIncrDecrButtons : public MIDIOutputElement {
 public:
  CCAbsoluteIncrDecrButtons(const AH::IncrementDecrementButtons &buttons,
                            MIDIAddress address, uint8_t initial_value = 0,
                            uint8_t multiplier = 1)
    : buttons(buttons), address(address), initial_value(initial_value),
      multiplier(multiplier) {}

 public:
  // Initialize: enable the pull-up resistors for the buttons
  // This method is called once by `Control_Surface.begin()`.
  void begin() final override { buttons.begin(); }

  // Update: read the buttons and send MIDI messages when appropriate.
  // This method is called continuously by `Control_Surface.loop()`.
  void update() final override {
    using IncrDecrButtons = AH::IncrementDecrementButtons;
    switch (buttons.update()) {
        case IncrDecrButtons::Nothing: break;
        case IncrDecrButtons::IncrementShort: // fallthrough
        case IncrDecrButtons::IncrementLong:  // fallthrough
        case IncrDecrButtons::IncrementHold:
            if (value <= 0x7F - multiplier) {
              value += multiplier;
              Control_Surface.sendControlChange(address, value);
            }
            break;
        case IncrDecrButtons::DecrementShort: // fallthrough
        case IncrDecrButtons::DecrementLong:  // fallthrough
        case IncrDecrButtons::DecrementHold:
            if (value >= multiplier) {
              value -= multiplier;
              Control_Surface.sendControlChange(address, value);
            }
            break;
        case IncrDecrButtons::Reset:
            if (value != initial_value) {
              value = initial_value;
              Control_Surface.sendControlChange(address, value);
            }
            break;
        default: break;
    }
  }

 private:
  AH::IncrementDecrementButtons buttons;
  const MIDIAddress address;
  const uint8_t initial_value;
  const uint8_t multiplier;
  uint8_t value = initial_value;
};

END_CS_NAMESPACE

// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //

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

// Instantiate a CCAbsoluteIncrDecrButtons object
CCAbsoluteIncrDecrButtons buttons {
  {2, 3},                  // Push buttons on pins 2 and 3
  MIDI_CC::Channel_Volume, // Controller
  0x40,                    // Initial value
};

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

void loop() {
  Control_Surface.loop(); // Update the Control Surface (calls buttons.update())
}
Alexandr010360 commented 8 months ago

Александр010360, у вас синтаксическая ошибка в коде - вызов сущности (метода?) без дополнительных аргументов. КурИте документацию. Возможно, вы считаете, что ошибка не в вашем коде, а в кодовой библиотеке?

Нет я не считаю что ошибка в библиотеке! Для моего случая нет готового кода из коробки! Для отправки абсолютных значений нужно самому написать соответствующий код. Или создать свой класс. Есть примеры и инструкции как расширить библиотеку. В чём я сейчас и разбираюсь. Но у меня недостаточно опыта для этого. Нужно время чтобы разобраться. Поэтому и попросил помощи у автора библиотеки Петера П.

laps78 commented 8 months ago

Александр010360, у вас синтаксическая ошибка в коде - вызов сущности (метода?) без дополнительных аргументов. КурИте документацию. Возможно, вы считаете, что ошибка не в вашем коде, а в кодовой библиотеке?

Нет я не считаю что ошибка в библиотеке! Для моего случая нет готового кода из коробки! Для отправки абсолютных значений нужно самому написать соответствующий код. Или создать свой класс. Есть примеры и инструкции как расширить библиотеку. В чём я сейчас и разбираюсь. Но у меня недостаточно опыта для этого. Нужно время чтобы разобраться. Поэтому и попросил помощи у автора библиотеки Петера П.

Александр, Ваша позиция ясна. Насколько я понимаю, библиотека это не Фреймворк. Т. е. Вы пишете свой проект и можете взять уже написанный код из библиотеки, чтобы не изобретать велосипед. С фреймворком иначе - Вы берете Фреймворк, а затем в его окружении пишете свой код. Это я к чему?

Следует ли @tttapa (busy) расширять код библиотеки под Ваши задачи - большой философский вопрос. Больше кода => больше багов => сложнее поддержка.

Этот раздел (issues) - для того, чтобы @username сферический в вакууме мог сообщить о баге в коде. Т.е. "issues" != "support".

Исходя из выше изложенного, настоятельно рекомендую самому разобраться в синтаксисе wiring/C, документации к библиотеке или найти профессионального разработчика, который решит задачу.

Следует также сказать спасибо(вы уже) @tttapa за то, что не нужно глубоко погружаться в спецификации MIDI и т.п.

С наилучшими пожеланиями творческих успехов!

Alexandr010360 commented 8 months ago

Peter P. Thank you very much! Everything worked out! You are a genius! I just had to tweak something in the code. For some reason, in the latest release of the library, it does not see the full name of sendControlChange. I had to change it to the abbreviated sendCC. And I also added an additional channel in my code. And I don't need a multiplier. This switching speed is also acceptable.`

include

BEGIN_CS_NAMESPACE

class CCAbsoluteIncrDecrButtons : public MIDIOutputElement { public: CCAbsoluteIncrDecrButtons(const AH::IncrementDecrementButtons &buttons, MIDIAddress address, uint8_t initial_value = 0, uint8_t multiplier = 1) : buttons(buttons), address(address), initial_value(initial_value), multiplier(multiplier) {}

public: // Initialize: enable the pull-up resistors for the buttons // This method is called once by Control_Surface.begin(). void begin() final override { buttons.begin(); }

// Update: read the buttons and send MIDI messages when appropriate. // This method is called continuously by Control_Surface.loop(). void update() final override { using IncrDecrButtons = AH::IncrementDecrementButtons; switch (buttons.update()) { case IncrDecrButtons::Nothing: break; case IncrDecrButtons::IncrementShort: // fallthrough case IncrDecrButtons::IncrementLong: // fallthrough case IncrDecrButtons::IncrementHold: if (value <= 0x7F - multiplier) { value += multiplier; Control_Surface. sendCC(address, value); } break; case IncrDecrButtons::DecrementShort: // fallthrough case IncrDecrButtons::DecrementLong: // fallthrough case IncrDecrButtons::DecrementHold: if (value >= multiplier) { value -= multiplier; Control_Surface. sendCC(address, value); } break; case IncrDecrButtons::Reset: if (value != initial_value) { value = initial_value; Control_Surface. sendCC(address, value); } break; default: break; } }

private: AH::IncrementDecrementButtons buttons; const MIDIAddress address; const uint8_t initial_value; const uint8_t multiplier; uint8_t value = initial_value; };

END_CS_NAMESPACE

// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //

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

// Instantiate a CCAbsoluteIncrDecrButtons object CCAbsoluteIncrDecrButtons buttons { {2, 3}, // Push buttons on pins 2 and 3 {MIDI_CC::Channel_Volume, CHANNEL_3}, // Controller // Initial value };

void setup() { Control_Surface.begin(); // Initialize Control Surface (calls buttons.begin()) Serial.begin(57600); }

void loop() { Control_Surface.loop(); // Update the Control Surface (calls buttons.update()) }

Alexandr010360 commented 8 months ago

Александр010360, у вас синтаксическая ошибка в коде - вызов сущности (метода?) без дополнительных аргументов. КурИте документацию. Возможно, вы считаете, что ошибка не в вашем коде, а в кодовой библиотеке?

Нет, я не считаю эту ошибку в библиотеке! В моем случае нет готового кода из коробки! Для вручения абсолютных оценок необходимо написать соответствующий код. Или создай свой класс. Существуют модели и разработки, связанные с развитием технологии. В чём я сейчас и разбираюсь. Но у меня недостаточно опыта для этого. Нужно время для выяснения. Поэтому и попросил помощи у автора библиотеки Петера П.

Александр, Ваша позиция ясна. Насколько я понимаю, библиотека это не Фреймворк. Т. е. Вы пишете свой проект и можете взять уже написанный код из библиотеки, чтобы не изобретать велосипед. С помощью Фреймворка иначе — вы берете Фреймворк, а затем в его рамках записываете свой код. Это я к чему?

ли@tttapa(занят) расширение кода библиотеки под Ваши задачи - большой философский вопрос. Больше кода => больше багов => сложнее поддержка.

Этот раздел (вопросы) - для того, чтобы @username сферический в вакууме мог сообщить о баге в коде. Т.е. "проблемы" != "поддержка".

Исходя из вышеизложенного, настоятельно рекомендуется разобраться в синтаксисе проводки/C, документации к библиотеке или найти профессионального разработчика, который решит задачу.

Также следует сказать спасибо(вы уже)@tttapaза то, что не нужно глубоко погружаться в особенности MIDI и т.п.

Сформулируйте пожелания творческих успехов!

Благодарю вас за пожелание и совет! Обязательно займусь углублённым изучением языка C++ Пока только учусь программировать в среде ардуино.