Arcade icon

Building an Arduino MIDI Controller


I'm a beginner in all things Arduino and I've been working on an easy, fast, and cheap project to learn more about it.

A MIDI controller with 16 buttons with an Arduino board

I enjoy building stuff that include electronics, and I always wanted to build something using Arduino.

One of the most common builds for beginners I found was a MIDI controller. A MIDI controller is any hardware that send MIDI data (Musical Instrument Digital Interface) to a device to trigger sounds and make music.

I found that many implementations are complicated, even those that are for beginners. It was very frustrating to find I need to use hundreds of lines of unreadable code. Or that I need to solder a resistor in some cases, among other examples.

The Project

By building my own Arduino MIDI Controller, my intention was to make an enjoyable project, keeping the noise at the lowest. Something any beginner could follow. To acomplish that, I used the MIDI Fighter 3D as a base inspiration and removed every non-essential feature.

The total cost of my project was under $30, and the list of materials was really short (affiliate links):

Take a look at how was the experience building this controller:

The Arduino Board

When I started this project I found there are a bunch of new Arduino models (not including the hundreds of compatible boards). And all them offer slightly different capabilities.

I needed to send MIDI signals to a computer and the simplest way to do that is through USB. Any Arduino board based on the ATmega32u4 microcontroller has built-in USB communication.

The official Arduino boards with native USB support are Arduino Due, Arduino Zero, Arduino Leonardo, Arduino Micro. These boards have integrated USB support which means they can act as a USB MIDI device.

I decided to go with a clone of the Arduino Leonardo. It has enough inputs for this project and it also includes headers, which makes easier to plug/unplug wires.

First Steps

Although I'll explain step-by-step how I implemented the code for this project, you can download the final version.

To upload code to the board you need to use the Arduino IDE. They also have a Web editor that is very useful but they have a limited quota on times per day that you can compile code.

Step 1. Blinking the built-in LED

It's funny how the "Hello World" in the world of hardware is blinking an LED.

It was a nice surprise for me to discover that Arduino Leonardo has a built-in LED that you can blink to test your code. That way you don't need to build an external circuit on a breadboard with an LED and a resistor.

Step 2. Blinking the LED on a manual input

The next logical step was to blink the same LED whenever I send some signal. I removed the plastic cover of one end of 2 dupont wires, and connected the other end to the board:

Now, every time I join the exposed ends of the wires I'm closing the circuit and thus I can execute code in consecuense.

Each of the 20 digital pins on the Leonardo have an internal resistor (disconnected by default) that can be enabled using INPUT_PULLUP. Keep in mind that a pull-up input means the button state is inverted:

Step 3: Installing the MIDIUSB library

This library allows an Arduino board with USB capabilites to act as a MIDI instrument over USB. Check the official documentation for more info.

Using the Arduino IDE, you can install extra Arduino Libraries using the Library Manager:

  1. Open the IDE and click on the "Sketch" menu, then "Include Library", then "Manage Libraries".
  2. Search for MIDIUSB and click Install.
  3. Once it has finished, an Installed tag should appear next to the MIDIUSB library.
  4. Close the Library Manager.

Now the Leonardo can send MIDI messages via USB! But first, some insight about how MIDI works is needed.

How MIDI Works

"MIDI (Musical Instrument Digital Interface) is a standard communication protocol that connects electronic musical instruments, computers, and related audio devices for playing music." — Wikipedia

It handles event messages with data of the pitch and velocity of the note played, among other instructions.

In this specific project the input from the 16 buttons send different messages via USB. These messages can be converted into sound on a computer using any suitable software like GarageBand or Ableton Live.

Anatomy of a MIDI message

To send a MIDI message, I used the sendMIDI() method from the MIDIUSB Library I installed on step 3.

This method can receive 4 parameters:

Step 4: Sending a MIDI message

I included the MIDIUSB Library and instead of blinking the built-in LED, I sent a note.

⚠ Important:

From this step onwards the Arduino turns into a MIDI USB Controller, and it stops receiving code via USB.

When you get stuck in a position where the Arduino can no longer be programmed, follow these steps:

  1. Hold down the rounded reset button on the Arduino board.
  2. Click Upload on the Arduino IDE.
  3. Release the reset button.
  4. The updated code will be uploaded to the board.

Step 5: Sending a MIDI message from each button

The final step was to map every pitch to a button. For the 16 buttons I defined a scale from C2 to E3b, which are the pitches from 36 to 51 in a sequence from bottom to top and from left to right. Check out this file from Arduino Tutorials to see what pitch corresponds to each note.

I used digital pins from 2 to 12 and analog pins (using them as digitals) from A0 to A4.

3 diagrams of the MIDI controller with notes, pitches and pins, assigned to the 16 buttons from bottom to top and from left to right

And this is how the final code looks like:

The Case

To keep this project simple, I was extremelly picky choosing which features include.

Unibody Design

One of the challenges I faced was designing a case simple enough that it doesn't need assembly and can be 3d printed in one single run.

To avoid using screws or glue, I needed to desing an enclosure that provides the smallest access to the electronics. My biggest inspiration for the enclosure was the Mac Mini, which has a circle shaped hole at the bottom. I also wanted to design a screwable lid for that, but I decided to let it open to expose the electronics.

The bottom side of my MIDI controller

Download the 3d printable case (322 KB). Recommended settings: PLA, 0.15mm layers, 20% infill, support enforcers at least for the rounded bottom hole, the arduino holders and the micro USB.

Holding an Arduino with no screws

The Leonardo has 4 holes to screw the board into any suitable case, but my idea was to make it easy to add and remove the board from the case.

Finding a clip holder for Arduino on Thingiverse was easy, and it took me 5 iterations to integrate that holder to the unibody desing. The most difficult part was making its legs to avoid the holes for the buttons, and to make the micro USB to be center aligned to the case.

3 legs inside the MIDI controller case, to hold the Arduino board

The Assembly

After inserting all the buttons in place, I soldered short black wires joining all the negative legs of the buttons between them.

Black wires soldered to the buttons negative leg

Then I soldered long red wires from each positive leg to connect directly to the board.

Red and black wires soldered to the buttons

To connect the wires to the Arduino, I cut and soldered some dupont ends and covered them with heat-shrink tubing.

A red wire with a dupont end and a heat-shrink tubing

I connected the wires to the board following the same order as in the MIDI Fighter. From bottom to top and from left to right.

A diagram of the MIDI controller showing which buttons matches which pins The MIDI Controller from the bottom, all wired to the Arduino board

The Output

Any music software (or suitable hardware) can be used to receive MIDI and make some music. The most recommended ones are Garage Band, Ableton live, and I know there are a bunch of apps to install on a phone.

All those tools are useful for loading predefined sounds for finger drumming, but they were made for bigger purposes. Those tools can be tough for beginners to setup.

To make something more aligned with this project and its simplicity, I built a tool completelly focused on MIDI controllers.

Punchy: WebMIDI and WebAudio implementation for MIDI controllers.

It can read MIDI messages on any browser using the WebMIDI JavaScript API. Then it play sounds in a synthesizer (using the WebAudio API) or in a sampler, loading custom sounds from any sound pack.