Bare Conductive Beginner Article 7

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.

⏱ 20 min read MIDI USB MIDI MIDIUSB note on note off DAW

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:

  1. Upload the sketch
  2. Open GarageBand, Logic, Ableton, etc.
  3. The Touch Board appears as “Arduino Leonardo” in MIDI preferences
  4. Create a software instrument track, set input to “Arduino Leonardo”
  5. 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() and noteOff() 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