Control Surface master
MIDI Control Surface library for Arduino


This is an example that demonstrates how to extend the library using your own MIDI Senders. It implements functionality similar to the built-in DigitalNoteSender class, but with support for different on and off velocities.

See also
MIDI Senders for different kinds of MIDI senders to start from.
AVR, AVR USB, Due, Nano 33 IoT, Nano 33 BLE, Teensy 3.x, ESP32


The internal pull-up resistor for the button will be enabled automatically.



Select the Arduino as a custom MIDI controller in your DAW, and use the MIDI learn option to assign the button to a function.

Written by PieterP, 2020-04-18

// A custom sender to use later. It has to declare two methods:
// - sendOn(MIDIAddress): will be called when the button is pressed
// - sendOff(MIDIAddress): will be called when the button is released
// Other types of senders need to implement different methods.
// For example, a continuous CC sender just has a send(value, address)
// method.
class CustomNoteSender {
CustomNoteSender(uint8_t onVelocity, uint8_t offVelocity)
: onVelocity(onVelocity), offVelocity(offVelocity) {}
void sendOn(MIDIAddress address) {
Control_Surface.sendNoteOn(address, onVelocity);
void sendOff(MIDIAddress address) {
Control_Surface.sendNoteOff(address, offVelocity);
uint8_t onVelocity, offVelocity;
// Now tell the MIDIButton class template (included with the Control
// Surface library) that it has to use your custom sender class.
// We wrap it in another class so we can easily construct it later,
// without having to write `MIDIButton<CustomNoteSender>` all the time,
// and so we have more control over the constructor arguments.
// The colon (:) indicates inheritance.
struct CustomNoteButton : MIDIButton<CustomNoteSender> {
// Constructor
CustomNoteButton(pin_t pin, MIDIAddress address, uint8_t onVelocity,
uint8_t offVelocity)
: MIDIButton(pin, address, {onVelocity, offVelocity}) {}
// ^~~~~~~~~~ Initialization of the base class MIDIButton
// Now we can instantiate an object of our custom class.
// The four arguments match the ones of the CustomNoteButton
// constructor we wrote a couple of lines back.
CustomNoteButton button {
5, // button pin
MIDI_Notes::C(4), // MIDI address
0x40, // on velocity
0x10, // off velocity
void setup() {
void loop() {
The main header file that includes all Control-Surface header files.
Control_Surface_ & Control_Surface
A predefined instance of the Control Surface to use in the Arduino sketches.
void begin()
Initialize the Control_Surface.
void loop()
Update all MIDI elements, send MIDI events and read MIDI input.
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
An abstract class for momentary push buttons that send MIDI events.
void sendNoteOn(MIDIAddress address, uint8_t velocity)
Send a MIDI Note On event.
Definition: MIDI_Sender.ipp:20
void sendNoteOff(MIDIAddress address, uint8_t velocity)
Send a MIDI Note Off event.
Definition: MIDI_Sender.ipp:31
A class for MIDI interfaces sending MIDI messages over a USB MIDI connection.
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).
constexpr Note C
C (Do)
Definition: Notes.hpp:40