MIDI Output Basics
Send MIDI note-on/off and control change messages over USB, map electrodes to notes, and connect to any DAW or synth.
Why MIDI?
The Touch Board’s built-in MP3 player is simple and powerful, but MIDI opens up a different world: you become a controller that any software instrument, DAW, or hardware synthesiser can respond to. One Touch Board can trigger samples in Ableton Live, play a software piano, control lights via DMX bridge, or drive a hardware synthesiser — all without changing the physical hardware.
The MIDIUSB library
The ATmega32U4 (same chip as the Arduino Leonardo) has native USB. The MIDIUSB library makes it appear as a USB MIDI device — plug it in and it shows up in your DAW’s MIDI device list immediately.
Install: Library Manager → search “MIDIUSB” → Install
Basic MIDI sketch
#include <MPR121.h>
#include <Wire.h>
#include <MIDIUSB.h>
// Map each electrode to a MIDI note number
// C major scale starting at middle C (C4 = MIDI 60)
const int NOTES[12] = { 60, 62, 64, 65, 67, 69, 71, 72, 74, 76, 77, 79 };
const int MIDI_CHANNEL = 0; // 0-indexed, so channel 1
const int VELOCITY = 100;
void noteOn(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOn = { 0x09, 0x90 | channel, pitch, velocity };
MidiUSB.sendMIDI(noteOn);
MidiUSB.flush();
}
void noteOff(byte channel, byte pitch, byte velocity) {
midiEventPacket_t noteOff = { 0x08, 0x80 | channel, pitch, velocity };
MidiUSB.sendMIDI(noteOff);
MidiUSB.flush();
}
void setup() {
Serial.begin(57600);
if (!MPR121.begin(0x5C)) {
Serial.println("MPR121 error");
while (1);
}
MPR121.setInterruptPin(4);
}
void loop() {
if (MPR121.touchStatusChanged()) {
MPR121.updateTouchData();
for (int i = 0; i < 12; i++) {
if (MPR121.isNewTouch(i)) {
noteOn(MIDI_CHANNEL, NOTES[i], VELOCITY);
Serial.print("Note ON: ");
Serial.println(NOTES[i]);
}
if (MPR121.isNewRelease(i)) {
noteOff(MIDI_CHANNEL, NOTES[i], 0);
}
}
}
}
Connecting to a DAW
macOS:
- Upload the sketch
- Open GarageBand, Logic, Ableton, etc.
- The Touch Board appears as “Arduino Leonardo” in MIDI preferences
- Create a software instrument track, set input to “Arduino Leonardo”
- Touch electrodes — notes play
Windows: MIDIUSB works natively on Windows 10/11. No driver needed. The device appears in DAW MIDI input lists.
Linux:
The device appears as a MIDI device via ALSA. Use aconnect -l to list devices.
MIDI note numbers
The MIDI standard uses note numbers 0–127:
| Note | MIDI # |
|---|---|
| C3 | 48 |
| C4 (middle C) | 60 |
| A4 (concert pitch) | 69 |
| C5 | 72 |
Map any scale:
// Pentatonic scale (C D E G A)
const int PENTATONIC[12] = { 60, 62, 64, 67, 69, 72, 74, 76, 79, 81, 84, 86 };
// Chromatic (all 12 semitones)
const int CHROMATIC[12] = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 };
// Drum mapping (General MIDI percussion channel 9)
const int DRUMS[12] = { 36, 38, 42, 46, 49, 51, 37, 40, 44, 48, 55, 57 };
// Kick, snare, closed hat, open hat, crash, ride, rimshot, ...
Sending Control Change (CC)
Use proximity data or multiple touches to send CC (continuous controller) messages:
void controlChange(byte channel, byte control, byte value) {
midiEventPacket_t event = { 0x0B, 0xB0 | channel, control, value };
MidiUSB.sendMIDI(event);
MidiUSB.flush();
}
// Example: electrode 0 sends CC#1 (modulation) based on how long it's held
if (MPR121.isNewTouch(0)) {
holdStart = millis();
}
if (MPR121.getTouchData(0)) { // currently held
long held = millis() - holdStart;
int ccVal = constrain(map(held, 0, 2000, 0, 127), 0, 127);
controlChange(0, 1, ccVal); // CC1 = modulation wheel
}
Sending to a hardware synth (serial MIDI)
For hardware synths with a 5-pin DIN MIDI input, use the Serial port instead of USB:
// Hardware MIDI via Serial1 (pins 0/1 on the Touch Board)
// Connect pin 1 (TX) via a 220Ω resistor to the MIDI DIN connector
void noteOnSerial(byte channel, byte pitch, byte velocity) {
Serial1.write(0x90 | (channel & 0x0F));
Serial1.write(pitch & 0x7F);
Serial1.write(velocity & 0x7F);
}
void setup() {
Serial1.begin(31250); // MIDI baud rate
// ...
}
Key takeaways
- The MIDIUSB library makes the Touch Board appear as a USB MIDI device in any DAW
noteOn()andnoteOff()are the two core functions — always send a noteOff for every noteOn- Map electrodes to any musical scale via a
NOTES[]array - Control Change (CC) messages send continuous values (0–127) — map to proximity or hold duration
- For hardware synths, use Serial1 at 31250 baud with the correct resistor circuit
- Always call
MidiUSB.flush()after sending — otherwise the packet may not transmit