Control Surface master
MIDI Control Surface library for Arduino


This example demonstrates how to attach custom actions to incoming Note or Control Change MIDI events.

AVR, AVR USB, Due, Nano 33 IoT, Nano 33 BLE, Teensy 3.x



If a MIDI Note On event for note 0x3C (C4 or middle C) is sent, the built-in LED will light up at full brightness, if a Note Off event for that note is sent, the LED will light dimly.
(A Note On event with a velocity of zero also counts as a Note Off event.)


Route the MIDI output of a MIDI keyboard to the Arduino's MIDI input. Then play a middle C on the keyboard.

Written by PieterP, 2020-03-10

#include <Control_Surface.h> // Include the Control Surface library
// Instantiate a MIDI over USB interface.
// MIDI Input Element that listens for MIDI Note events that turns on the LED at
// full brightness if the note value (velocity) is above the threshold,
// and turns on the LED at a lower brightness if the value is below the
// threshold.
class CustomNoteLED
// First, inherit from the MatchingMIDIInputElement base class. Indicate that
// you want to listen to MIDI Note events by specifying the MIDI message type,
// and use a simple 2-byte message matcher, since MIDI Note events have two
// data bytes.
: public MatchingMIDIInputElement<MIDIMessageType::NOTE_ON,
TwoByteMIDIMatcher> {
// Constructor
CustomNoteLED(pin_t ledPin, MIDIAddress address, uint8_t lowBrightness)
: MatchingMIDIInputElement(address), ledPin(ledPin),
lowBrightness(lowBrightness) {}
// Called once upon initialization, set up the pin mode for the LED,
// and output the initial value.
void begin() override {
ExtIO::analogWrite(ledPin, lowBrightness);
// Called when an incoming MIDI Note message matches this element's matcher
// (i.e. it has the right MIDI address, channel and cable).
// The match object that's passed as a parameter contains the velocity value
// of the Note message that matched.
if (match.value >= threshold)
ExtIO::analogWrite(ledPin, lowBrightness);
// Called when the input element is reset (e.g. by an "All notes off" MIDI
// event).
void reset() override { ExtIO::analogWrite(ledPin, lowBrightness); }
pin_t ledPin;
uint8_t lowBrightness;
const static uint8_t threshold = 0x01;
// Instantiate the LED that will light up when middle C is playing.
CustomNoteLED led {
3, // Pin with the LED connected (PWM capable)
{MIDI_Notes::C(4), CHANNEL_1}, // Note C4 on MIDI channel 1
10, // Intensity when off
void setup() {
Control_Surface.begin(); // Initialize Control Surface
void loop() {
Control_Surface.loop(); // Update the Control Surface
constexpr PinStatus_t HIGH
constexpr PinMode_t OUTPUT
constexpr Channel CHANNEL_1
Definition: Channel.hpp:118
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,...
virtual void begin()
Initialize the input element.
virtual void reset()
Reset the input element to its initial state.
The MIDIInputElement base class is very general: you give it a MIDI message, and it calls the updateW...
MatchingMIDIInputElement(const Matcher &matcher)
virtual void handleUpdate(typename Matcher::Result match)=0
A class for MIDI interfaces sending MIDI messages over a USB MIDI connection.
void analogWrite(pin_t pin, analog_t val)
An ExtIO version of the Arduino function.
void pinMode(pin_t pin, PinMode_t mode)
An ExtIO version of the Arduino function.
void digitalWrite(pin_t pin, PinStatus_t val)
An ExtIO version of the Arduino function.
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).
constexpr Note C
C (Do)
Definition: Notes.hpp:40