Building MIDI controllers #1 - The Matrix

MIDI controllers are not the most complicated things on earth to build and program.

If you have your MIDI basics covered and have a little experience with Arduino-type microcontrollers it’s just a matter of capturing an inputdevice (button, knob, …) into your microcontroller and sending some bytes out via a serial port, which MIDI essentially is.

There is a lot about building basic MIDI controllers on the net already so I won’t cover that, but give an overview of what helped me to get going:

  • This is probably the best explanation of how MIDI circuits really work from an electrical point of view.
  • This basic MIDI controllers tutorial is from the same guy but unfortunately he doesn’t explain much how it actually works, you won’t learn coding with this one.
  • Video series in german language for absolute beginners without any Arduino experience. Also he doesn’t use any libraries but explains how to do everything from scratch. Valuable!
  • This video is quite nice, he’s using a Teensy microcontroller which has MIDI over USB by default

Speaking of: just to get one slightly dissapointing thing straight from the beginning: Most of the common Arduino types are not capable of natively spitting out MIDI on their USB ports, but I’m going to show a hardware-hackish approach to still make it work. A few Arduinos have native USB capabilities and can make use of the MIDIUSB library , but that’s usually the type of Arduino you don’t have at hand at the right moment. The only one’s that have USB-MIDI out of the box are the Teensy’s but they cost a little more, if you don’t want any hassle go get one! This is the website of the founder, you’ll find excellent documentation there.

The input device

This is going to be my chosen input device, a button matrix out of a 1995 landline phone, built by the company Kapsch, model TP80.

I got these phone parts out of a spare parts collection
There was another PCB connected to the actual buttons PCB that had to be desoldered first

Understanding

So wtf is a key matrix? This guy explains it quite well, just ignore the voltage ladder for now. The german speaking guy over here, altough a bit more advanced, is explaining useful things too. He uses a button matrix out of an old chipcard terminal.

Personally my first experience with a button/keyboard matrix was the tiny 80s keyboard featured in one of my blog posts. I found a lot of information about a similar keyboard on this website. The site owner even has put together a whole FAQ about circuit bending and especially hacking keyboards. Scroll down a little (well a lot, it’s long) and look for headlines containing keyboard matrix. Deadly useful information there!!!

If it still all doesn’t add up, check this and certainly wikipedia

Measuring

The top 3 connections are labeled by a letter X, the bottom 4 with a letter Y. Ignore the red wire on the very bottom.
No buttons pressed - no connections, but when button 1 is pressed X1 to Y1 show a connection.
X2 to Y1 is connected when button 2 is pressed
X3 to Y1 is connected when button 3 is pressed
X1 to Y2 is connected when button 4 is pressed
X2 to Y2 is connected when button 5 is pressed

I guess you see where this is going by now. If not, go back and rewatch the youtube videos an links posted above. Ok, so we can think of our matrix that it has 3 column lines, the X-wires, and 4 row lines, the Y-wires.

Housing

Before I started with writing code, I did some fitting to the case I was planning to put it in. I found this in my parent’s basement. Eventually I built it myself during my apprenticeship back in the 90ies. As far as I remember it should have become a battery powered radio and due to time reasons we never even started to build the electronics.

These holes should have been the outlet for the speaker's sound.
On the inside we had to construct this battery holder. Won't use it but won't remove it, it's glued in there and seems pretty steady.
The keypad should sit on top of it, the MC inside the box.
It just fits's perfectly on top of it. How nice is that? At first I thought I have to remove the boxes lid and couldn't think of a possibility to then steadily mount the keypad, but after some head-scratching I had a better idea...
I replaced the original wires with new ones, but soldered them to the PCB upside-down, so they take as little space as possible underneath the keypad's PCB
The wires should be slipping into the speaker holes, so the PCB can be sticked to the box with hot-glue. The double-sided scotch tape was kind of a proof of concept.
Bougth these to be able to steadily close the lid. Lost the original ones or never had them.
Redrilled and used this handy tool, out of my girlfriend's stash, to make the screws fit and the screw-heads even with the housing again.
Et voila, finally the box can be properly closed.

Writing code

Breadboarding

Soldered a pin-header to an Arduino Nano. Didn't use the double-row header, so it still fits into the breadboard!
The 3 X wires (cols) and the 4 Y wires (rows) connected to the breadboard.
Digital pins 6-8 used as outputs (cols, X), digital pins 9-12 used as inputs (rows, Y). Some 10-15k pull-down resistors to keep LOW level when no buttons are pressed.
Much later on I decided to get rid of the pull-down resistors by making everything low-active. More on that further below...
Had to fix the matrix. For some reason in the last row, two pins were not connected as I supposed they would be (* and 0).
Removed the jumper pin-header that used to be here. It could be set/unset to change the phones behaviour. I just hard-wired it to stay closed.

Prerequisites

I won’t copy tons of code to here but leave it on github and post links to commits/diffs and whole code checkouts for copying and pasting.

I use some libraries because they make sense. They can be installed from the Arduino IDE “Library Manager”.

  • advancedSerial - helps with debugging over the serial monitor, I think the original serial print and println commands are pretty uncomfortable to use.
  • MIDI - send and/or receive MIDI messages via any serial port.

Test sketches

Let’s check if the matrix and our breadboarding setup works and we actually understand what we are doing here with this test sketch. Manually set one of the output pins to HIGH level in lines 36-38 of the program and see what happens on the serial monitor.

With this next commit I loop through the 3 outputs, set them HIGH, and see which of the input lines have received the HIGH (because a button was pressed). This is the whole file to copy and paste. Actually this is the whole magic about reading out the state of any matrix keypad.

You should see something like that on the serial monitor when pressing buttons. It tells you wich row and col IDs are HIGH at the moment:

yes it's high: 0 0
...
...
yes it's high: 2 3

Best practices

Read through the commit messages and the comments in the code to see what I was thinking

  • store MIDI CCs in button array
  • 3 different modes - my suggestion on how to easily switch between software emulated MIDI, just debugging and “real” MIDI. Helps with going back to coding and extending your controller later on without thinking to much.
  • momentary press behaviour - I decided to program my controller so it sends out what is called a “momentary press”. It sends out a MIDI CC on message when a button is pressed and does nothing as long as you keep that button pressed. Only on releasing the button it sends out a MIDI CC off message.
  • set debounce time - these values worked for me, a button press feels pretty responsive.
  • make it low-active - saves the pull-down resistors. This is the final version for a native MIDI version. Read on, for a solution to make it work on any Non-USB-MIDI compliant Arduino. If you want to use the hairless MIDI bridge software, just change the mode to 1 here

Finalizing

Mounting the keypad to the case

The hot-glue idea went back to be double-sided scotch tape. I found this so-called mounting-tape somewhere and thought I give it a try.
I used two layers of tape, except on the places where the wires are. I guessed that they'd need about 1 layer of thickness.
Well, in the right half of the case where the 4 row wires are, I messed it up a little, there should have been only 1 layer of tape. Looks and feels pretty steady anyway.

The cheapest USB-MIDI-Arduino available

As mentioned at the very top of this post, most Arduinos are not capable of showing up as proper MIDI device in your computer’s operating system. If you are fine with using a software MIDI bridge like the hairless MIDI bridge, just look at the first picture in this chapter and you are done.

If it is not, one of the cheapest solutions around is to steal the electronics out of a USB to MIDI Adapter cable. You can get them in Europe for about 7-10 €. Certainly if you order them in China, a few pieces of them will cost you almost nothing. And btw: These cheap adapter cables are pretty useless for serious MIDI applications like controlling a synth from your your DAW. They are built so cheap, they literally loose data! Believe me, I measured it. But they are definitely good enough to be used for sending some knob or button movement aka some MIDI CC bytes. That’s only a tiny amount of data and my experience is that they handle that savely.

I decided to use a fresh Arduino Nano, solder the wires directly to it and keep the pin-headered Nano for breadboarding purposes. The 7 keypad wires are connected to digital pins, the USB port transports power and serial data. This is the final software simulated MIDI variant.
To make the Nano a fully fledged USB-MIDI device I'll (mis)use this cheap USB-MIDI adapter cable.
It could be easily opened by poking around on the edges with a screwdriver. Some versions of these adapter cables are easier to forcefully open than other's ;-) Good luck with yours!
This is where the MIDI-in and MIDI-out DIN jacks are connected. We are interested in the wires that connect the MIDI-INPUT port: IN- (black) and GND (red). Now please don't ask me why they chose to use a red wire for GND!?!
Original wires desoldered and hooked up to the Nano. Green wire: Nano TX1 to Adapter-PCB IN-, black wire: Nano GND to Adapter-PCB GND. Now recap the signal path when a button is pressed: Arduino sends OUT (TX1) data INTO (IN-) the adapter thing. ...
... The adapter thing sends the data INTO the computers USB port. Makes sense? If your chosen case allows it, leave the USB side connected as is. ...
... In my case I had to desolder it to nicely bring it into the case. I also reused the original strain relief plastic thing. Had to cut it a little to get it into my boxes hole.
Soldered on four fresh wires of the same color to the PCB. Note that I chose the opposite direction for my solder joints as it originally was. Helps when putting in the whole PCB into a bag for isolation.
Checking if everything still would fit in. Only thing left to do is connecting the four wires to the USB-cable
Decided to connect the red 5V wire of the Adapter-PCB directly to the Arduino's VIN pin first, ...
... and then via the 5V pin to the USB cable's red wire (V+, Vss). The attentive reader now would say that it would be more logic if I would've exchanged VIN and 5V on the Arduino. Well, that's true, but in the end 5V and VIN are exactely the same :-)
Finally soldering all the freshly hooked on wires from the Adapter-PCB's USB-side to the original USB-cable again (and certainly the red wire coming from Nano 5V pin I just mentioned).
Isolating the solder joints with shrink tube.
Mounting it together. We are looking good, but I forgot a couple of things so I had to reopen it ;-)

Testrun

Now that we don’t have to use the hairless MIDI bridge anymore, we change the mode of the program to send native MIDI speed (31250 bps) out of the Arduinos TX1 pin:

Line 9

Flashing the final program to the fresh Arduino via the black USB cable connected to the original Arduino's USB port. Notice that the silver USB cable is not connected to the computers's USB-port at this moment because I think it's not a good idea if two power sources were connected at once. So watch out!!!
That's when I relized that the red power LED's of the Arduino and the Adapter-PCB are shining through the orange case heavily. Nice!
Left is the Adapter-PCB's LED and right the Arduino's tiny but pretty bright SMD-LED. This certainly brings up new ideas...

The Nano’s onboard LEDs and the Adapter-PCB’s MIDI-IN LED should blink shortly when MIDI data is transmitted from the controller.

But what if I just want to use a classic MIDI cable?

Just connect GND, +5V and TX1 pins of the Arduino to a 5-pin DIN-socket like described in this sparkfun tutorial.

The drawing on the bottom of this pic shows where the pins of your DIN jack should go:

  • pin 4 -> 220R resistor -> +5V
  • pin 5 -> 220R resistor -> Arduino TX1
  • pin 2 -> cable shield -> Arduino GND

As you’d expect, just use an ordinary MIDI cable (jack-jack) to connect from your controller’s socket to the device you want to control.

Making it even fancier

I had 5 digital pins left on the Arduino Nano, let’s use them!

One 2,2k resistor hooked up to GND will be used to limit current for 5 white LEDs.
Connecting the resistor with 5 wires going to the LEDs cathode pins.
Soldering together this amount of wires sometimes is a bit challenging but if you just do it once and make sure you would never have to resolder this exact joint, IMHO it's an OK solution.
Shrink tube for isolation.
The 5 white LEDs connected to the resistor (hidden in the shadows and shrink-tubed already). Orange wires are, you guessed it, the LEDs anodes, ...
... which were connected to the 5 remaining digital pins (D1-D5).
Alright, it's getting packed in there ;-)

Just a little addition to the code: blink 5 LEDs when sending CC

Maybe using red LEDs would bring a more dramatic effect.

No buttons pressed
Any button is pressed - At the moment the white LEDs are hanging around loosely in the case, sticking them closely to the cases edges with some tape probably would help to let them shine through better.

The final product

Happy with the thing.
I really dig it's small size.
Compared to an already small Korg Volca Beats. The lila thing bottom right is another controller I built, it will be featured in a future post.

Using it

MIDI mapping in Ableton Live - The momentary-mode buttons behave differently depending on which controls they are mapped to:

  • (mis)using buttons for dial type controls: as long as the button is pressed the dial is put to halfway up (we send MIDI CC value 64), when releasing it goes to 0 again.
  • on/off controls like eg the mute buttons: as long as the button is pressed it’s unmuted, if released it’s muted again. For device on/off buttons the behaviour is the same.
  • the solo buttons behaviour is different: press once - solo stays on - press again - solo stays off

Getting supplies

As usual I recommend supporting and buying from musikding.de, because it’s just well sorted and has good prices (first two links). For the MIDI adapter cables and Arduinos I have put together some links to cheap buys on amazon.de. If you like what you see on this blog please support me by using these links. I get a little nothing from amazon then ;-)

This article was first published on Nov 25, 2018 and last updated on Nov 29, 2018. I built/coded/did this project around November 2018. jump to top