BLOG / TUTORIALS / Build an Arduino MIDI Controller: Step-b…
ब्लॉग पोस्ट

Build an Arduino MIDI Controller: Step-by-Step with Buttons, Pots, and LEDs

Viktor Build ~9 min read

Build a custom Arduino MIDI controller with buttons, pots, and LEDs. Complete wiring diagram, USB MIDI code, and DAW mapping guide for your next music project.

You want to build your own Arduino MIDI controller — with buttons, potentiometers, and LEDs — and you want a straightforward, step-by-step guide that actually works. This tutorial walks you through every connection, every line of code, and every design decision so you can create a custom MIDI controller that sends real MIDI messages to your DAW, synthesizer, or VST plugin.

Why Build an Arduino MIDI Controller?

Commercial MIDI controllers cost anywhere from fifty to several hundred dollars, and they rarely have exactly the layout you want. An Arduino MIDI controller puts you in control: you decide how many buttons, knobs, and LEDs you need, what they do, and how they look. It’s a perfect weekend project that teaches you digital input handling, analog-to-digital conversion, and the MIDI protocol — all while producing something you can actually use.

This project uses an Arduino Leonardo (or a clone like the Pro Micro) because it supports native USB MIDI — no additional serial-to-MIDI converter required. You’ll wire up four buttons, four potentiometers, and four LEDs. Once you understand the pattern, scaling up to 8, 16, or more controls is trivial.

Parts List: What You Need

Before wiring anything, gather these components:

Component Quantity Notes
Arduino Leonardo (or Pro Micro) 1 Must be ATmega32u4 for native USB MIDI
10kΩ potentiometers 4 Any linear taper potentiometer works
Tactile push buttons 4 Momentary, normally open
LEDs (any color) 4 Standard 5mm or 3mm
220Ω resistors 4 For LED current limiting
10kΩ resistors 4 Pull-down resistors for buttons
Breadboard 1 Half-size is enough
Jumper wires ~20 M-M and M-F for breadboard
USB cable 1 Micro USB or USB-C depending on board

Total cost: roughly $15–20 if you already have an Arduino. If you’re starting from scratch, grab a Leonardo clone for under $10.

Wiring the Arduino MIDI Controller

The wiring splits into three sections: buttons, potentiometers, and LEDs. Wire them one group at a time and test each group before moving on.

Button Wiring

Each button needs a pull-down resistor to keep the input LOW when the button isn’t pressed. Connect as follows:

  • Button pin 1 → 5V (via a small jumper)
  • Button pin 2 → Arduino digital pin + one leg of a 10kΩ resistor
  • Other leg of 10kΩ resistor → GND

Do this for all four buttons using digital pins 2, 3, 4, and 5.

Potentiometer Wiring

Potentiometers have three terminals. The outer two connect to 5V and GND; the middle wiper connects to an analog input.

  • Left terminal → GND
  • Center terminal → Arduino analog pin (A0, A1, A2, A3)
  • Right terminal → 5V

Double-check your wiring: swapping the outer terminals just reverses the direction of the knob, which is easy to fix in software.

LED Wiring

LEDs connect to digital PWM-capable pins through current-limiting resistors. Any pin on the Leonardo can do digital output, but PWM pins (3, 5, 6, 9, 10, 11) let you control brightness if you want visual feedback.

  • LED anode (long leg) → 220Ω resistor → Arduino pin (6, 9, 10, 11)
  • LED cathode (short leg) → GND

Here’s the full pin mapping:

Function Arduino Pin
Button 1 D2
Button 2 D3
Button 3 D4
Button 4 D5
Potentiometer 1 A0
Potentiometer 2 A1
Potentiometer 3 A2
Potentiometer 4 A3
LED 1 D6
LED 2 D9
LED 3 D10
LED 4 D11

Programming the Arduino for USB MIDI

The Leonardo’s ATmega32u4 can act as a USB MIDI device without any extra hardware. The Arduino IDE includes the MIDIUSB library, which handles all the protocol details.

Install the Library

  1. Open Arduino IDE
  2. Go to Sketch → Include Library → Manage Libraries
  3. Search for MIDIUSB
  4. Install the official library by Arduino

The Code

Copy this sketch. It reads all four buttons and potentiometers every 10 milliseconds and sends MIDI Control Change (CC) messages. Each control maps to a specific CC number — you can change these to match your DAW or synthesizer.

#include <MIDIUSB.h>

// Pin definitions
const int buttonPins[] = {2, 3, 4, 5};
const int potPins[] = {A0, A1, A2, A3};
const int ledPins[] = {6, 9, 10, 11};

// MIDI CC numbers for each control
const int buttonCC[] = {1, 2, 3, 4};
const int potCC[] = {5, 6, 7, 8};

// State tracking
bool lastButtonState[4] = {HIGH, HIGH, HIGH, HIGH};
int lastPotValue[4] = {0, 0, 0, 0};

unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 10;

void setup() {
  for (int i = 0; i < 4; i++) {
    pinMode(buttonPins[i], INPUT);
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);
  }
  // Initialize serial for debugging
  Serial.begin(9600);
}

void loop() {
  unsigned long currentMillis = millis();
  
  // Read buttons with debouncing
  if (currentMillis - lastDebounceTime >= debounceDelay) {
    for (int i = 0; i < 4; i++) {
      bool reading = digitalRead(buttonPins[i]);
      if (reading != lastButtonState[i]) {
        lastDebounceTime = currentMillis;
        lastButtonState[i] = reading;
        
        if (reading == HIGH) {
          // Button pressed: send CC 127
          controlChange(0, buttonCC[i], 127);
          MidiUSB.flush();
          digitalWrite(ledPins[i], HIGH);
        } else {
          // Button released: send CC 0
          controlChange(0, buttonCC[i], 0);
          MidiUSB.flush();
          digitalWrite(ledPins[i], LOW);
        }
      }
    }
  }
  
  // Read potentiometers
  for (int i = 0; i < 4; i++) {
    int raw = analogRead(potPins[i]);
    int scaled = map(raw, 0, 1023, 0, 127);
    
    // Only send if value changed by more than 1 (avoid flooding)
    if (abs(scaled - lastPotValue[i]) > 1) {
      lastPotValue[i] = scaled;
      controlChange(0, potCC[i], scaled);
      MidiUSB.flush();
    }
  }
  
  delay(5); // Small delay to avoid overwhelming the USB bus
}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}

How the Code Works

  • Debouncing: The lastDebounceTime check prevents false triggers from mechanical button bounce.
  • Potentiometer mapping: analogRead() returns 0–1023, but MIDI CC values are 0–127. The map() function scales it perfectly.
  • Change detection: The potentiometer code only sends a new MIDI message when the value changes by more than 1. This keeps your USB traffic minimal and prevents your DAW from slowing down.
  • LED feedback: LEDs mirror the button state — on when pressed, off when released.

Testing Your Arduino MIDI Controller

Before connecting to your DAW, test with a MIDI monitor tool:

  1. Windows: Use MIDI-OX
  2. macOS: Use the built-in Audio MIDI Setup or download MIDI Monitor
  3. Linux: aseqdump -l followed by aseqdump -p <port>

When you press a button or turn a knob, you should see MIDI CC messages appearing. Each movement triggers a message like:

TIMESTAMP IN PORT STATUS DATA1 DATA2
00714466   1   B     1     5     64

The B status byte means Control Change. The first data byte is the CC number, the second is the value (0–127).

Integrating with a DAW or Synth

Your Arduino MIDI controller appears as a standard MIDI device. Here’s how to use it in popular DAWs:

Ableton Live

  • Go to Preferences → Link, Tempo & MIDI
  • Under Control Surface, choose “None” and select your Arduino as the Input
  • Map controls by right-clicking a parameter and selecting “MIDI Learn”

FL Studio

  • Open Options → MIDI Settings
  • Find your Arduino in the Input list and enable it
  • Right-click any knob or fader, select “Link to controller”, then move your physical control

Reaper

  • Open Preferences → MIDI Devices
  • Enable your Arduino as a control input
  • Use the “Learn” button in Reaper’s parameter modulation window

Expanding Your Design

Once the basic Arduino MIDI controller works, you can easily scale it up:

Add More Controls

  • Use analog multiplexers (CD4051) to read 8+ potentiometers with only 3 analog pins
  • Matrix your buttons to handle 16 or more with just 8 digital I/O pins

Add Visual Feedback

  • Use RGB LEDs (WS2812B) for color-coded feedback — red for mute, green for active
  • Add a small OLED display to show current CC values. See our guide on OLED Display Arduino for wiring details.

Add Velocity Sensitivity

  • Replace buttons with force-sensitive resistors (FSR) for velocity-sensitive pads
  • Read the analog value from the FSR and map it directly to MIDI note velocity

Wireless MIDI

Troubleshooting Common Issues

No MIDI device detected:

  • Make sure you’re using a Leonardo or Pro Micro (Uno and Mega don’t support native USB MIDI)
  • Press the reset button on your Arduino while it’s connected — it should re-enumerate

Buttons trigger multiple times:

  • Your debounce delay might be too short. Increase it to 20–30ms
  • Check pull-down resistor connections — floating inputs can cause ghost presses

Potentiometers jump erratically:

  • Noisy potentiometers need a small capacitor (100nF) between the wiper and GND
  • Add a constrain(raw, 0, 1023) before mapping to filter out extreme readings

MIDI messages flood the DAW:

  • Increase the dead zone threshold in the potentiometer reading code (change > 1 to > 3)
  • Add a longer delay() — 10ms works well for most applications

Going Further: Real Projects Using This Controller

Professional musicians and hobbyists alike use custom Arduino MIDI controllers for everything from VST automation to modular synth control. You can adapt this project for:

  • Lighting control: Map the CCs to DMX lights via a bridge
  • DJ controllers: Use buttons for cue points and pots for filter sweeps
  • Game controllers: Map to MIDI notes in games like Guitar Hero or Synthesia
  • Accessibility tools: Create custom input devices for people with limited mobility

For more inspiration, check out our 555 Timer IC: Build a Simple LED Flasher project — it uses similar wiring principles for timing applications.

Conclusion

Building an Arduino MIDI controller from scratch is one of the most rewarding electronics projects you can tackle. You learn about debouncing, analog reading, the MIDI protocol, and USB HID emulation — all while creating a genuinely useful device. Start with four buttons and four pots, get it working with your DAW, then expand from there. The code and wiring in this guide give you a solid foundation; what you build on top is up to you.

Discord पर कम्यूनिटी से जुड़ें

सवाल पूछें, अपने प्रोजेक्ट शेयर करें, और साथी मेकर्स से मिलें।

Discord जॉइन करें — मुफ़्त है

यह ट्यूटोरियल पसंद आया?

Patreon पर चैनल को सपोर्ट करें और प्रोजेक्ट्स, बिल्ड लॉग्स और बहुत कुछ तक जल्दी पहुंचें।

Patreon पर सपोर्ट करें →