Control Surface - Speed Sensitive Encoders

Hello community,

I happily made a control surface with encoders and potentiometer.
I would like to know if it's possible to program the encoders to be sensitive to speed in order to use the rotational speed to decide for coarse and fine tuning.

Thank you

It's definitely possible. there are libraries for encoders tracking speed.

Yes, for example there are this two libraries:

I'm trying to use the MD_REncoder but I'm unable to assign the MIDI address to it.

You don't “assign” a MIDI address to it. You read the encoder, and then send a MIDI message with a certain address depending on the value you read.

If you're using the Control Surface library, you can plug in your own encoder types into the existing GenericMIDIRotaryEncoder class:

#include <Control_Surface.h>

struct MyCustomEncoder {
    MyCustomEncoder(uint8_t pinA, uint8_t pinB) { /* ... */ }
    void begin() { /* ... */ } // optional
    uint8_t read() { return 42; } // preferably returns an unsigned type
};

using MyCustomMIDIEncoder = GenericMIDIRotaryEncoder<MyCustomEncoder, RelativeCCSender>;

MyCustomMIDIEncoder enc {
    {2, 3}, // MyCustomEncoder constructor
    MIDI_CC::Channel_Volume, // MIDI address
    1, 4, // Multiplier and pulses per step
    // ↑ set to 1 if encoder library already handles this
    {}, // MIDI sender initialization (unused in this example)
};

USBMIDI_Interface midi;

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

Hello @PieterP and thanks for explaining. It really helped.
I didn't know I can use my own encoder types with the GenericMIDIRotaryEncoder class.
However the sketch compiles and get uploaded to the Pro Micro but it doesn't work properly.

It looks like there is some redundancy going on: I have to set the class MD_REncoder and relative input pins because it needs the variable "R" (see sketch below), meaning that I'm setting twice the same pins for the same encoder (one for the MD_REncoder, one for the MyCustomEncoder constructor).


#include <Control_Surface.h>
#include <MD_REncoder.h>

MD_REncoder R = MD_REncoder (4, 3);

struct MyCustomEncoder {
    MyCustomEncoder (uint8_t pinA, uint8_t pinB) { /* ... */ }
    void begin() { /* ... */ } // optional
    uint8_t read() { return 42; } // preferably returns an unsigned type
};

using MyCustomMIDIEncoder = GenericMIDIRotaryEncoder<MD_REncoder, RelativeCCSender>;

MyCustomMIDIEncoder enc {
    {4, 3}, // MyCustomEncoder constructor
     MIDI_CC::Channel_Volume, // MIDI address
    1, 1, // Multiplier and pulses per step
    // ↑ set to 1 if encoder library already handles this
    {}, // MIDI sender initialization (unused in this example)
};

USBMIDI_Interface midi;

void setup() { 

Control_Surface.begin(); 
Serial.begin(57600);
R.begin();}

void loop() 
{ 
Control_Surface.loop(); 
uint8_t x = R.read();
  
  if (x != DIR_NONE) 
  {
    Serial.print(x == DIR_CW ? "\n+1" : "\n-1");
#if ENABLE_SPEED
    Serial.print("  ");
    Serial.print(R.speed());
#endif
}
}

Let me know your thought.
Thanks a lot

The idea is that you implement the required functionality in the MyCustomEncoder struct. It should contain a MD_REncoder member variable (or reference/pointer to it), and you should implement the MyCustomEncoder::begin() function to initialize the MD_REncoder. MyCustomEncoder::read() should update and return the position of the encoder (modulo 256).