tttapa / Control-Surface

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

midi control change para note on #161

Open davidgauze opened 4 years ago

davidgauze commented 4 years ago

hello i would like to know how to change control change potentiom to note on, software that work only recognizes midi Note On both button and fader. how do I send these notes to the faders?

davidgauze commented 4 years ago

working with grandMA2 lighting software

tttapa commented 4 years ago

You could use something like this:

#include <Control_Surface.h>

struct ContinuousNoteSender {
    void send(uint8_t value, MIDIAddress address) {
        Control_Surface.sendNoteOn(address, value);
    }  
    static constexpr uint8_t precision() { return 7; }
};

struct NotePotentiometer : MIDIFilteredAnalogAddressable<ContinuousNoteSender> {
    NotePotentiometer(pin_t analogPin, MIDIAddress address)
      : MIDIFilteredAnalogAddressable(analogPin, address, {}) {}
};

USBMIDI_Interface midi;

using namespace MIDI_Notes;
NotePotentiometer pots[] = {
  {A0, note(C, 4)},
  {A1, note(Db, 4)},
  {A2, note(D, 4)},
  {A3, note(Eb, 4)},
};

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

void loop() {
  Control_Surface.loop();
}
davidgauze commented 4 years ago

hello, it didn't work. could write using midi controller library ? use it but fader send crontrol change and not midi

tttapa commented 4 years ago

What doesn't work? Please be more specific. As far as I can see, the code I posted does what you asked for.

When turning the potentiometer, it sends MIDI Note events with the velocity representing the potentiometer position: Screenshot from 2020-04-07 11-31-09

could write using midi controller library?

What do you mean? The MIDI Controller library is no longer supported and has no built-in support for these kinds of things.

davidgauze commented 4 years ago

I'm using arduino UNO, it keeps oscillating values ​​and doesn't recognize, I converted using hyduino and firmaware also didn't work

davidgauze commented 4 years ago

I converted using midi hairless and midi loop but does not send a note is showing infinite values

tttapa commented 4 years ago

What makes you think grandMA2 supports MIDI note input for potentiometers? As far as I can see, it only supports MSC: http://help2.malighting.com/Page/grandMA2/remote_control_msc/en/3.9

You'll have to figure out the required MIDI messages before trying it out with an Arduino.

If the values oscillate, this probably means the resistance of the potentiometers you're using is too high, or there's something wrong with your power supply or wiring.

davidgauze commented 4 years ago

even note on what you recognize, use bome midi translation to convert control change

davidgauze commented 4 years ago

mm

davidgauze commented 4 years ago

this and another controller that I set up sends control change ai use software to convert it into note on

davidgauze commented 4 years ago

For when the fader increases, only the value changes, note that it remains the same

tttapa commented 4 years ago

I don't understand. Why would the note change?

davidgauze commented 4 years ago

dd

as shown in photo V would have to vary from 0 to 127. C is channel and p = it has to change 0 and 1 and n = it has to be a fixed note

davidgauze commented 4 years ago

MIDI Remote The MIDI Remotes tab used received MIDI notes as the input. There are two special columns in this tab. They are called Note and Channel. These are used to set the MIDI note and channel.

If the Type is set to Exec and the Button is set to Fader, then the velocity of the MIDI note is used to set the position of the executor fader. All other inputs are simple triggers.

tttapa commented 4 years ago

The code I posted yesterday changes the velocity of a fixed note.

davidgauze commented 4 years ago

I'm using 1 fader only, I delete the others from the code. should that be a problem?

tttapa commented 4 years ago

No, that shouldn't be a problem.

What is the exact issue you have right now?

davidgauze commented 4 years ago

+5.75 - Warning: got a status byte when we were expecting 2 more data bytes, sending possibly incomplete MIDI message 0x80 ss

davidgauze commented 4 years ago

00

davidgauze commented 4 years ago

value does not change it always remains

tttapa commented 4 years ago

Are you using HairlessMIDI_Interface or USBMIDI_Interface? What baud rate are you using in Hairless? If you modified the code I posted, please include the full sketch.

davidgauze commented 4 years ago

USBMIDI_Interface

davidgauze commented 4 years ago

I haven't changed anything this same thing this USBMIDI_Interface

tttapa commented 4 years ago

If you're using an Arduino Uno, USBMIDI_Interface only works with the right firmware. If you're using Hairless MIDI, you have to use the HairlessMIDI_Interface.

davidgauze commented 4 years ago

got it not low value of 60 now. minimum is 60 and maximum is 127

tttapa commented 4 years ago

The note number should be 60 (0x3C) and the velocity should vary between 0 and 127 (0x7F).
If the velocity value doesn't go all the way to zero, there's probably a problem with the wiring of the potentiometer.

davidgauze commented 4 years ago

I got a friend, thank you very much. question of encoder can I send note on too? I will complement my midi with 16 fader and 45 button and 3 encoder as I do

tttapa commented 4 years ago

Sure, encoders can be made to send notes, but grandMA2 has to know how to interpret it.
Once you know what type of messages it expects for encoders, you can simply turn this into a MIDI Sender and use it with the Control Surface library, like the example code for note potentiometers I posted.

davidgauze commented 4 years ago

yes it works through midi on, example when turning left sends a note and when turning right sends another note you know? so I did another media

tttapa commented 4 years ago

Then all you have to do is write your own RelativeNoteSender class with a send(long delta, MIDIAddress address) function.

You can see how it's done for normal encoders here: https://github.com/tttapa/Control-Surface/blob/367730b4cfdd36adc4c61cf2b56e56f60e4c625b/src/MIDI_Senders/RelativeCCSender.hpp#L93-L103

davidgauze commented 4 years ago

thank you very much for now, i am very grateful, i hope to get here and send me an account for tipped tip as a way to help because rare people in the world like you are difficult

davidgauze commented 4 years ago

friend encoder note for example, error in the sketches that trying to neither accept note together

tttapa commented 4 years ago

I don't understand what you mean. If you want help with a sketch, please post your code.

davidgauze commented 4 years ago

I want to make my encoder send note on, I tried more I couldn't do it

#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

struct ContinuousNoteSender {
    void send(uint8_t value, MIDIAddress address) {
        Control_Surface.sendNoteOn(address, value);
    }  
    static constexpr uint8_t precision() { return 7; }
};

struct NotePotentiometer : MIDIFilteredAnalogAddressable<ContinuousNoteSender> {
    NotePotentiometer(pin_t analogPin, MIDIAddress address)
      : MIDIFilteredAnalogAddressable(analogPin, address, {}) {}
};

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

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

void setup() {
  // Select the correct relative MIDI CC mode.
  // Options:
  //   - TWOS_COMPLEMENT (default)
  //   - BINARY_OFFSET
  //   - SIGN_MAGNITUDE
  // Aliases:
  //   - REAPER_RELATIVE_1
  //   - REAPER_RELATIVE_2
  //   - REAPER_RELATIVE_3
  //   - TRACKTION_RELATIVE
  //   - MACKIE_CONTROL_RELATIVE
  RelativeCCSender::setMode(relativeCCmode::MACKIE_CONTROL_RELATIVE);
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}
tttapa commented 4 years ago

This could be a starting point:

#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

struct RelativeNoteSender {
    static void send(int delta, MIDIAddress address) {
        delta = constrain(delta, -127, 127);
        if (delta > 0) {
          Control_Surface.sendNoteOn(address, delta);
          // Send whatever your software expects
        } else {
          Control_Surface.sendNoteOn(address + 1 /* ??? */, -delta);
          // Send whatever your software expects
        }
    }
};

struct NoteEncoder : MIDIRotaryEncoder<RelativeNoteSender> {
    NoteEncoder(EncoderPinList pins, MIDIAddress address)
      : MIDIRotaryEncoder(pins, address, 1, 4, {}) {}
};

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

NoteEncoder enc = {
  {2, 3}, // pins
  0x01,   // MIDI address (note number + optional channel)
};

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

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

I have no idea how your software implements relative note messages, so you'll have to provide your own implementation for the send function.

davidgauze commented 4 years ago

friend I can't add more encoder where I change to add because button and fader works well wanted by 3 encoder sorry to bother you

#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

const int speedMultiply = 1; // If the jog wheels or other encoders are too slow in your software, increase this value
                             // (it will be multiplied with the actual speed of the encoder, as the name implies.) Default is 1.

struct RelativeNoteSender {
    static void send(int delta, MIDIAddress address) {
        delta = constrain(delta, -127, 127);
        if (delta > 0) {
          Control_Surface.sendNoteOn(address, delta);
          // Send whatever your software expects
        } else {
          Control_Surface.sendNoteOn(address + 1 /* ??? */, -delta);
          // Send whatever your software expects
        }
    }
};

struct NoteEncoder : MIDIRotaryEncoder<RelativeNoteSender> {
    NoteEncoder(EncoderPinList pins, MIDIAddress address)
      : MIDIRotaryEncoder(pins, address, 1, 4, {}) {}
};

struct ContinuousNoteSender {
    void send(uint8_t value, MIDIAddress address) {
        Control_Surface.sendNoteOn(address, value);
    }  
    static constexpr uint8_t precision() { return 7; }
};

struct NotePotentiometer : MIDIFilteredAnalogAddressable<ContinuousNoteSender> {
    NotePotentiometer(pin_t analogPin, MIDIAddress address)
      : MIDIFilteredAnalogAddressable(analogPin, address, {}) {}
};
// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

NoteEncoder enc[] = {
  {2,3, 0x01}, 
  {4,5, 0x02},
  {6,7, 0x03}, 

};
NoteButtonLatching switches[] = {
    {2, 0x10, 1}, // Create a new instance of class 'DigitalLatch' on pin 0, note number 16 (mute) on MIDI channel 1
    {3, 0x11, 1},
    {5, 0x12, 1},
    {7, 0x13, 1},
};

using namespace MIDI_Notes;
NotePotentiometer pots[] = {
  {A1, note(0x4, 1)},
  {A2, note(0x5, 1)},
  {A3, note(0x6, 1)},

};

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

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}
tttapa commented 4 years ago

You forgot a pair of braces around the pins.

NoteEncoder enc[] = {
  {{2,3}, 0x01}, 
  {{4,5}, 0x02},
  {{6,7}, 0x03}, 
};

Keep in mind that only pins 2 and 3 are interrupt pins on an Uno. Using encoders on non-interrupt pins may result in incorrect readings. You can use pin 2 for one encoder and pin 3 for a second encoder, so you have two encoders with interrupts instead of just one.

alejamelissa commented 4 years ago

Hola Pieter, he estado todo el dia tratando de añadirle banco a esta estructura

struct ContinuousNoteSender { void send(uint8_t value, MIDIAddress address) { Control_Surface.sendNoteOn(address, value); }
static constexpr uint8_t precision() { return 7; } };

struct NotePotentiometer : MIDIFilteredAnalogAddressable { NotePotentiometer(pin_t analogPin, MIDIAddress address) : MIDIFilteredAnalogAddressable(analogPin, address, {}) {} };

Hice la prueba con todos los archivos de ccpotentiometer cambiando el continuousccsender por el continuosnotesender y al igual que ccpotentiometer por notepotentiometer pero no me reconoce el NotePotentiometer como parte del bankable, no se si haya que definirlo en otro lugar o si haya que añadir algun texto contenido en algun archivo de la libreria, podrias orientarme un poco. Te lo agradezco.

davidgauze commented 4 years ago

friend noa can put more than 9 pots, I did not do it declared, I already made changes and it did not work, I need a minimum of 10 pots

include // Include the Encoder library.

// This must be done before the Control Surface library.

include // Include the Control Surface library

struct RelativeNoteSender { static void send(int delta, MIDIAddress address) { delta = constrain(delta, -127, 127); if (delta > 0) { Control_Surface.sendNoteOn(address, delta); // Send whatever your software expects } else { Control_Surface.sendNoteOn(address + 1 / ??? /, -delta); // Send whatever your software expects } } };

struct NoteEncoder : MIDIRotaryEncoder { NoteEncoder(EncoderPinList pins, MIDIAddress address) : MIDIRotaryEncoder(pins, address, 1, 4, {}) {} };

struct ContinuousNoteSender { void send(uint8_t value, MIDIAddress address) { Control_Surface.sendNoteOn(address, value); }
static constexpr uint8_t precision() { return 10; } };

struct NotePotentiometer : MIDIFilteredAnalogAddressable { NotePotentiometer(pin_t analogPin, MIDIAddress address) : MIDIFilteredAnalogAddressable(analogPin, address, {}) {} }; // Instantiate a MIDI over USB interface. USBMIDI_Interface midi;

NoteEncoder enc [] = { {{ 36 , 37 }, 0x2F }, {{ 38, 39 }, 0x3F },

};

NoteButton switches[] = { {2, 0x10, 1}, // Create a new instance of class 'DigitalLatch' on pin 0, note number 16 (mute) on MIDI channel 1 {3, 0x11, 1}, {4, 0x12, 1}, {5, 0x13, 1}, {6, 0x14, 1}, {7, 0x15, 1}, {8, 0x16, 1}, {9, 0x17, 1}, {10, 0x18, 1}, {11, 0x19, 1}, {12, 0x20, 1}, {13, 0x21, 1}, {14, 0x22, 1}, {15, 0x23, 1}, {16, 0x24, 1}, {17, 0x25, 1}, {18, 0x26, 1}, {19, 0x27, 1}, {20, 0x28, 1}, {21, 0x29, 1}, {22, 0x30, 1}, {23, 0x31, 1}, {24, 0x32, 1}, {25, 0x33, 1}, {26, 0x34, 1}, {27, 0x35, 1}, {28, 0x36, 1}, {29, 0x37, 1}, {30, 0x38, 1}, {31, 0x39, 1}, {32, 0x40, 1}, {33, 0x41, 1}, {34, 0x42, 1}, {35, 0x43, 1},

};

using namespace MIDI_Notes; NotePotentiometer pots[] = {

{A0, note(0x51, 4)}, {A1, note(0x52, 4)}, {A2, note(0x53, 4)}, {A3, note(0x54, 4)}, {A4, note(0x55, 4)}, {A5, note(0x56, 4)}, {A6, note(0x57, 4)}, {A7, note(0x58, 4)}, {A8, note(0x59, 4)}, {A9, note(0x60, 4)},

};

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

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

tttapa commented 4 years ago

What doesn't work? What error are you getting?

davidgauze commented 4 years ago

exit status 1 'A8' was not declared in this scope

he does not accept that I put more than 7 potentiometer, I already made a change in the return I put 10 instead of 7 that counts even so it does not recognize

davidgauze commented 4 years ago

put 10 potentiometer from A7 not accepted

using namespace MIDI_Notes; NotePotentiometer pots [] = {

{A0, note (0x51, 4)}, {A1, note (0x52, 4)}, {A2, note (0x53, 4)}, {A3, note (0x54, 4)}, {A4, note (0x55, 4)}, {A5, note (0x56, 4)}, {A6, note (0x57, 4)}, {A7, note (0x58, 4)}, {A8, note (0x59, 4)}, {A9, note (0x60, 4)},

};

tttapa commented 4 years ago

Does your board have a pin labeled A8? Did you select the right board in the Tools menu of the IDE?

An Arduino UNO only has 6 analog pins: A0-A5.
If you want more analog pins, you'll have to use a multiplexer: https://tttapa.github.io/Control-Surface-doc/Doxygen/d5/d7d/md_pages_Getting-Started.html

davidgauze commented 4 years ago

yes friend I did this programming for Arduino Mega that I used in another controller because I added more pin

tttapa commented 4 years ago

If you select the Arduino Mega in the Arduino IDE, you'll have access to the pins A6-A11.

note (0x60, 4) might not do what you expect. It's not used like that, the first argument is the note, e.g. C or `Bb, as shown in this example: https://tttapa.github.io/Control-Surface-doc/Doxygen/de/dcc/NoteButton_8ino-example.html
Also see the documentation here: https://tttapa.github.io/Control-Surface-doc/Doxygen/d7/d78/namespaceMIDI__Notes.html