Introduction: Building a Basic Midi Controller Part 1 - Easy 3 Pot (Potentiometer) Arduino Uno Effects Midi Controller (Serial-USB)... Quick,easy and Cheap!
Hello everyone,
I'm relatively new to Arduino and so have been battling my way to make my own midi controllers. There is a huge amount of information dotted around but I couldn't find a simple tutorial for such a simple device; so here it goes.
My original intention was to create a mixer similar to that used with a pair of decks. However, before I move onto that I wanted to make a piece of code which gave accurate and stable readings for potentiometers.
Step 1: What You'll Need!
- Arduino of any kind, in this case I am using an Arduino Uno.
- 6 short cables
- 5 long cables
- A prototyping breadboard
- 3 x 10k Linear Potentiometers (the potentiometer should normally be labelled B10K)
- Hairless Midi Serial Bridge (Software for sending/receiving midi data)
- LoopBe1 (Virtual Midi Device Software)
Make sure you have all of these before starting.
Step 2: Wiring It Up...
Hopefully you know the basics of circuits. Wire up cables from the positive rail to the positive pin on each of the pots, then do the same for the ground to the ground pins on the pots. The middle pin of each potentiometer is for data, providing an analogue reading from 0-1023. In the code we will use later this value is divided by 8 to give a value between 0-127 which is necessary so that the MIDImessage command works.
Hook up each of the middle pins to analogue pins on the Arduino 0 to 2 (A0 - A2).
Note: If your pots when finishing the tutorial work inversely (clockwise decreases the value and anti clockwise increases the value) then you simply need to switch the ground and power for each pot which should now give you the values rising when turned clockwise and decrease when turned anti-clockwise.
Step 3: Installing the Software...
Install LoopBe1 and Hairless Midi Serial Bridge if you haven't already.
To check that LoopBe1 is running, it should be in the bottom right of your OS (windows) and mute should be unchecked.
Once you have installed Hairless Midi, go into the preferences and set as the image shows. Do not worry about having your Arduino hooked up yet.
Step 4: The Code
Here's the nice bit of simple code based upon an example made back in 2009 by starfiretech. The key adjustments I have made to this code were to check new values against old values, only sending midi data when a change is detected; and the other adding a small delay to remove any slight variations given in value when the pot is not being touched, slightly touched or gets a little knock. Before I added this I was getting some variation (by +/- 1) in value when slightly touched which the delay helps to remove.
int val = 0; //Our initial pot values. We need one for the first value and a second to test if there has been a change made. This needs to be done for all 3 pots.
int lastVal = 0; int val2 = 0; int lastVal2 = 0; int val3 = 0; int lastVal3 = 0;void setup() { Serial.begin(9600); // Set the speed of the midi port to the same as we will be using in the Hairless Midi software }
void loop() { val = analogRead(0)/8; // Divide by 8 to get range of 0-127 for midi if (val != lastVal) // If the value does not = the last value the following command is made. This is because the pot has been turned. Otherwise the pot remains the same and no midi message is output. { MIDImessage(176,1,val);} // 176 = CC command (channel 1 control change), 1 = Which Control, val = value read from Potentionmeter 1 NOTE THIS SAYS VAL not VA1 (lowercase of course) lastVal = val;
val2 = analogRead(1)/8; // Divide by 8 to get range of 0-127 for midi if (val2 != lastVal2) { MIDImessage(176,2,val2);} // 176 = CC command, 2 = Which Control, val = value read from Potentionmeter 2 lastVal2 = val2; val3 = analogRead(2)/8; // Divide by 8 to get range of 0-127 for midi if (val3 != lastVal3) { MIDImessage(176,3,val3);} // 176 = CC command, 3 = Which Control, val = value read from Potentionmeter 3 lastVal3 = val3; delay(10); //here we add a short delay to help prevent slight fluctuations, knocks on the pots etc. Adding this helped to prevent my pots from jumpin up or down a value when slightly touched or knocked. }
void MIDImessage(byte command, byte data1, byte data2) //pass values out through standard Midi Command { Serial.write(command); Serial.write(data1); Serial.write(data2); }
Step 5: Upload and Setup With Your DAW
If all has been copied correctly or adapted to your needs, the code should upload fine. Make sure you disable Hairless Midi Serial Bridge before trying to upload. You cannot to both at the same time!
Once the code has been uploaded successfully, ensure LoopBe1 is on and startup Hairless Midi serial Bridge.
Set the options as shown with your Arduino on the serial port and LoopBe1 as your midi output.
Next you need to setup the options in your DAW. In Ableton I have put LoopBe1 as a midi input ONLY (this is important as LoopBe1 can only act as either an input or outout in each application, you may get an error if you do and LoopBe1 will be muted. In this case make sure you have the correct settings in ableton as shown, then untick the mute button on LoopBe1) and put the input on remote mode.
Great, If all has worked then you should be able to see the midi input light turn on when moving one of the pots.
Step 6: Midi Mapping
Next map your midi controls to something in the DAW. Here I have inserted a test music track and applied a ping pong delay to that track. I have then assigned the 3 pots to different controls on the ping pong delay. To asign a pot, first click the midi button at the top right of the app. All assignable controls should now turn blue. Next click on the control in the plugin you want to be controlled by one of your pots. Once selected, then move a pot. That pot is now assigned to that control. Repeat for the other 2 pots but controlling different variables on the plugin.
Step 7: The Result
Here's a short video showing it in action.
Since this is my first instructable I'd love some feedback to improve on in the future. Hope this has helped a few of you trying to get to grips with Arduino Midi controller making.

Participated in the
Mind for Design

Participated in the
Coded Creations
35 Comments
1 year ago
Many thanks for great tutorial .
I begin with Arduino effect with Reaper DAW
I want to know if possible to have a 10 steps rotary switch choice to control a knob on a plugin ? It s possible with only Arduino uno you think ? Can you help please :)
Thanks
2 years ago on Introduction
great .. can u tell me how to use many pots ..not only 3 pots ...
Question 4 years ago on Step 2
do you not need to add library usbmidi.h or midi.h?
Answer 2 years ago
Adding that to my code actually messed it up
3 years ago
Hey did everyone else have issue where the midi controlled was turning on but wouldnt disable again
4 years ago
Hi! Thanks for the tutorial, it´s my first time with Arduino!!! I have some troubles, but I fixed it up:
* Serial.begin(115200);
* IAC Bus
It works perfect!
Thanks!!!
Question 5 years ago on Step 1
Hi thanks for the tutorial, my question is this, can you change the 3 potensiometers for a 3-axis joystick? ( no buttons on stick, just 3 axis)
Cheers
P.
5 years ago
Great, it works perfectly for me with "Reaper". Now I can buy some multiplexers cd4067B or 74HC4067 and get up to 96 analog inputs to control some Arturia's Synths.
5 years ago
Everything looks right from start to finish, however Ableton is still not recognizing that it's receiving MIDI signals even after configuring MIDI input on my Mac for ipMIDI as input while hairless MIDI is running. Hairless-midiserial confirms it is receiving proper signals from the 3 pots from 0-127, then I set up the input as remote for ipMIDI, but still Ableton LIve 9 Suite does not recognize incoming MIDI signals. What could I be missing?
Reply 5 years ago
I figured it out, I had to use IAC bus, not ipMIDI and configure my Ableton MIDI to have "Track" on. Here's the video that taught me in case anyone else needs it too: https://youtu.be/AepicXO7Dlc
5 years ago
Congratulations!!! It's a very nice project. Just a question: may I use with my iMac?
Thank a lot for your kind help....
Gian Battista Pettinelli
6 years ago
Loopbee keeps muting me due to the amount of signals I think, is there anyway to solve this issue? its the only thing thats stopping it at the moment
6 years ago
now how would i go about adding buttons. so i could play samples off of them
6 years ago
Hi all,
I am new to Arduino and Max and i can't figure out how to do it with Max. I wired everything and uploaded the code to Arduino but on Max i am really confused and i can't afford for LoopBe1 software right now. At first didn't now it wasn't free and i bought some potentiometers but can't figure it out. Also i want to learn Max to build controllers like this. I am lost at "serial" object on Max and can't find the port name for example. Any help or a Max patch for this project will be very appreciated!
7 years ago
Hey Andrew,
I followed your instructions up until the arduino code.. After uploading it to the board and opening it in the serial monitor I receive the unknown character question mark symbol. I have attached an image below, I copied your code exactly. I know this error normally appears when the baud rates are different in the serial and arduino code but this isnt the case.. Is it something simply i am overlooking? sorry im a relative beginner
Thanks
Mike
Reply 6 years ago
99% of the time it's because your Baud rate is incorrect. Check the code for the Baud rate and then set the same rate on the Serial Monitor screen. (lower right hand corned)
6 years ago
Hi, do you know why it flickers a little bit the values? im using it via MIDI cable and its always sending data... i have to be moving all the time the potentiometer i want to control the parameter or otherwise choose one randmly because theyre all active. and if i map it the value moves a little bit, any idea why? thanks!
Reply 6 years ago
Hi there Matias, sorry for the slow reply. This will be due to the delay which may not be significant with your pots (potentiometers). I can't sya for certain but this ussually happens with poor quality pots or pots that have a very high sensitivity. try increasing the delay to see if this solves the problem. increase 10 to 15, 20 etc until you find something stable, let me know how this work for you.
"delay(10); //here we add a short delay to help prevent slight fluctuations, knocks on the pots etc. Adding this helped to prevent my pots from jumping up or down a value when slightly touched or knocked."
6 years ago
Thanks for this tutorial!! Works fine.
Someone know how to add buttons to this??
7 years ago
Cool project ! i 'm from France thanks for the tutorial everything works fine ! (i also added more pots) but i want to add 12 buttons. Can anyone help me with that?
This is the code.
int val = 0; //Our initial pot values. We need one for the first value and a second to test if there has been a change made. This needs to be done for all 3 pots.
int lastVal = 0;
int val2 = 0;
int lastVal2 = 0;
int val3 = 0;
int lastVal3 = 0;
int val4 = 0;
int lastVal4 = 0;
int val5 = 0;
int lastVal5 = 0;
int val6 = 0;
int lastVal6 = 0;
void setup()
{
Serial.begin(9600); // Set the speed of the midi port to the same as we will be using in the Hairless Midi software
}
void loop()
{
val = analogRead(0)/8; // Divide by 8 to get range of 0-127 for midi
if (val != lastVal) // If the value does not = the last value the following command is made. This is because the pot has been turned. Otherwise the pot remains the same and no midi message is output.
{
MIDImessage(176,1,val);} // 176 = CC command (channel 1 control change), 1 = Which Control, val = value read from Potentionmeter 1 NOTE THIS SAYS VAL not VA1 (lowercase of course)
lastVal = val;
val2 = analogRead(1)/8; // Divide by 8 to get range of 0-127 for midi
if (val2 != lastVal2)
{
MIDImessage(176,2,val2);} // 176 = CC command, 2 = Which Control, val = value read from Potentionmeter 2
lastVal2 = val2;
val3 = analogRead(2)/8; // Divide by 8 to get range of 0-127 for midi
if (val3 != lastVal3)
{
MIDImessage(176,3,val3);} // 176 = CC command, 3 = Which Control, val = value read from Potentionmeter 3
lastVal3 = val3;
val4 = analogRead(3)/8; // Divide by 8 to get range of 0-127 for midi
if (val4 != lastVal4)
{
MIDImessage(176,4,val4);} // 176 = CC command, 4 = Which Control, val = value read from Potentionmeter 4
lastVal4 = val4;
val5 = analogRead(4)/8; // Divide by 8 to get range of 0-127 for midi
if (val5 != lastVal5)
{
MIDImessage(176,5,val5);} // 176 = CC command, 5 = Which Control, val = value read from Potentionmeter 5
lastVal5 = val5;
val6 = analogRead(5)/8; // Divide by 8 to get range of 0-127 for midi
if (val6 != lastVal6)
{
MIDImessage(176,6,val6);} // 176 = CC command, 6 = Which Control, val = value read from Potentionmeter 6
lastVal6 = val6;
delay(10); //here we add a short delay to help prevent slight fluctuations, knocks on the pots etc. Adding this helped to prevent my pots from jumpin up or down a value when slightly touched or knocked.
}
void MIDImessage(byte command, byte data1, byte data2) //pass values out through standard Midi Command
{
Serial.write(command);
Serial.write(data1);
Serial.write(data2);
}