USB MIDI Controller With Arduino Leonardo
USB MIDI Controller With Arduino Leonardo
A2 ESAT
Code images
- Code 1: Code start
- Code 2: Buttons On / Off
- Code 3: Velocity and Channel change potentiometers
- Code 4: Pitch bend potentiometer 1
- Code 5: Pitch bend potentiometer 2
Introduction
The Arduino Micro Pro (or Leonardo) prototyping platform is a great tool to create a small MIDI controller
device. The Arduino Micro controllers can send USB MIDI messages directly from the Arduino IDE to the DAW of choice
(Ableton in this case). The rest of the connection is to enable physical inputs to activate and alter those MIDI messages.
Using buttons and potentiometers this creates a basic but entirely usable MIDI controller surface.
This circuit design is inspired by the video made by PretEnGineering (PretEnGineering, 2019) on MIDIUSB
controller and instruments.
Circuit Design
1) Tinkercad and Breadboard
Tinkercad has been very useful when representing a circuit on the Arduino Uno, however, using the Arduino
Micro Pro in this assignment, Tinkercad does not fully represent the created circuit.
Nevertheless, I decided to re-design the Circuit in Tinkercad in order to show a clearer view of how each Input device
is connected to the prototyping platform. Thus, this Tinkercad representation is only an accurate representation of
the Breadboard in the sense of the physical connections, and the flow of information, the Arduino Uno is not used in
the final design.
1kOhms
Button1
Button2
10kOhms
Button3
Button4
potpitch potvel potChannel Pic 1
Tinkercad enables a simpler view of the connections made on the breadboard circuit but with the wrong
Arduino platform.
Breadboard Circuit Design
potChannel
potvel
potpitch
1kOhms
10kOhms
1kOhms
Button1 Button2 Button3 Button4 Pic 2
The picture of the breadboard shows the working Circuit Design, however the connections from INPUT to Arduino are
not as clear as on Tinkercad.
-Connection to the INPUT pin on the Arduino Micro Pro at Digital pin
Input 2.
Each button has the exact same connections between Vcc, GRND and
a Digital pin Input on the Arduino controller.
Button1
Pic 3
3) Potentiometer Connections
PotPitch Breadboard Circuit Connections
The three potentiometers are connected to a Vcc, GRND and an attributed
analogue input each in the exact same way.
In this here image on the right hand-side, the connections shown are for
potpitch, the potentiometer which will serve as a Pitch Bending pot.
In Pic 4, the green line to blue wire above the right-most potentiometer
shows the connection to the variable terminal of the potentiometer, which
will then be connected to the Analogue Input 0 (A0) on Pic 5.
PotPitch In the same picture, the Black and Red lines respectively represent
connection to GRND and Vcc through the potentiometers 5V and GRND
terminals.
Pic 4
Pic 5
Similar to the previous Pic 5, this here image (Pic 6) shows closely the
connection of the GRND terminal of PotPitch (right-most). Through the
connection of the blue cable, linked then to a 10kW (10 kilo-Ohms)
resistor which is itself wired into the GRND line of the breadboard
connected to the GRND pin of the Arduino board.
Pic 6
PotPitch Breadboard Vcc Connection
In Pic 7 is imaged as a close up, the connection from the 5V terminal of the
potentiometer to the Vcc line of the circuit. The connection is directly
though a orange cable going from the 5V terminal to the Vcc line, no need
for resistors as the Potentiometer is a variable resistor itself.
Pic 7
Code Design
This code is designed to make the above pictured circuit function as a MIDI controller. The four
buttons work as piano keys playing starting from button1 to button4: C4 – E4 – G4 – C5. In other words, due
to the pitch bend being able to change the base notes, the buttons will play: Tonic – Major Third – Perfect
Fifth – Tonic Octave.
The potentiometers each affect the MIDI message differently. The potpitch can perform a PitchBend making
the notes higher by up to 1 octave. The potvel can augment or diminish the velocity of the notes, starting
very low at 6, going all the way up to 127 (max range 0-127). Finally the potChannel, changes the Channel
on which the MIDI message is sent ranging from 0-15 (1-16 on DAW).
2) Buttons Code
To continue according to the order the inputs were shown on the breadboard, the design of the code for the
buttons is rather straightforward and functions technically the same way as programming an LED luminosity change
through Arduino.
Code 2
Upon having assigned the input pins to input sensors, the digitalRead() is used to have the Arduino Read the input
message.
In the case of Push Buttons like these ones, the reading will be either “HIGH” where the voltage is close or
equal to the Vcc (5V), or “LOW” where the voltage is much lower than the Vcc.
When the value is “LOW” i.e. the button is pressed and the voltage is subsequently lower, the code enters the “if”
statement and does the following:
- Prints in the Serial Monitor “button1 On”, to confirm to the user that the input value “LOW” has been read.
- Triggers the “noteOn” function which sends a MIDI message of activation of a note following the before
established order (Channel, Note, Velocity). In this code, the “Channel” and “Velocity” have changing values
thanks to the potentiometers for which their code will be viewed later.
- MidiUSB.flush(), is a function which forces the program to immediately send the MIDI message, as a
MidiSend() might not necessarily send it straight away.
And the “if” statement ends there.
When the value is “HIGH” i.e. the button is not being pressed, and the voltage is around 5V, the code will enter the
“else if” statement:
- Prints “button1 Off” in the Serial Monitor, to confirm to the user that the input value “HIGH” has been read.
- Triggers the “noteOff” function which sends a MIDI message to stop sending a note at the specified (Channel,
Note, Velocity). If the “noteOff” message is not send, the note played earlier continues to play indefinitely.
- Forces the MIDI message to be sent immediately exactly the same as in the “if” statement.
The above code only specifies use of the “button1” push button, however, it the exact same code for the other buttons,
it was merely simpler to showcase it on one and put the rest in the complete code later on.
Code 3
Both the potvel and potChannel work in similar fashions, except that one controls the channel change and the
other the velocity.
To start off, the potentiometers were declared as constant integers at the Analogue inputs A1(potvel) and
A3(potChannel). As a short side note, potChannel was connected to A3 because the soldering on the Arduino Micro
Pro created a connection between A1 and A2, therefore if potChannel remained connected to A2, any changes to
potvel would affect potChannel and vice-versa. Both pots were then declared as INPUTS thanks to the pinMode
function.
On lines 65 and 72, potvel and potChannel each have their input respectively read through the analogRead() function.
Upon enabling the platform to read the value of the potentiometers which will range from 0 to 1023 as Arduino
converts the analog input of varying voltage into a digital value (arduino2go, 2017).
However, since velocity only ranges from 0 to 127 and there are only 16 channels, the analogRead value has
to be converted in order for the potentiometer to be less sensitive and change its range.Hence the map() function;
this tool will dictate that the 0-1023 range of the potentiometer will become 0-127 for the potvel and 0-15 for the
potChannel, making it so that the user has more room to change these setting by twisting the potentiometer.
Otherwise a change from 0-15 would only have allowed a tiny change of the pot resistance value.
Furthermore, as seen in the code above, the minimum read value for the potentiometer is 524 and not 0, this is
explained by the fact that even when at its lowest, the potentiometer still has a resistance and does not allow 5V to
go through, as such if it were a 0 instead of 524 at the lowest, the minimum velocity would be 68 instead o 0, and the
minimum channel 5 instead of 0 as well.
Following this, both pots print their name in the Serial Monitor, then alongside that their current value to
enable the user to visually confirm that modification without having to open a DAW.
Finally, the potvelmap and potChannelmap replace numerical values in the “noteOn” and “noteOff” functions
at each button. Originally being in the format of noteOn/Off(channel, note, velocity), it has now become
noteOn/Off(potChannelmap, note, potvelmap). For each button, the user can change the velocity and Channel at will.
Code 4
To carry on, the potpitch potentiometer to acquire a pitch bend functionality requires the pitchToNote.h
library as declared at the beginning of the code. Following the same flow and going through the code line by line:
The first part is to declare a value for the reading of A0 which has already been associated to potpitch as an
input in the setup section of the code. Potpitchval will be the read value at A0.
On line 156 a delay of 2ms (milliseconds) is added, this is not necessary, it is merely because upon trial of the
code without delay, the pitch bend seemed to struggle to remain consistent, this delay seemed to help the program
run more smoothly.
Line 160 starts the code for the pitch bend carefully explained on (tigoe, 2019). Starting off similarly to the
potvel and potChannel codes, it is required to “map” the potentiometer values in order to get a full use of the
potentiometer assigning these mapped values to a new integer pitchBend. As shown in the mapping, the
potentiometer has a range of 0-1023, and the pitch bend ranges 0-16383. A much wider range. Without mapping, the
pitch bend using only the potentiometer range would be minimal.
To confirm that the mapping worked to the user, the program prints the message “PitchBend value: “, and
alongside it the value of the integer “pitchBend”.
These next three lines convert the 8-bit bytes of the pitchBend, to 7-bit bytes, as MIDI represents all values in
7-bit bytes. Having 8 would not send the data properly. In order to create this conversion, the use of msb (most
significant bit) and lsb (least significant bit), is necessary.
Line 164 shifts the bits so that the top bit of lsb, is now in msb.
Line 165 assigns byte msb to receive the high bits, which does not change anything from how it normally functions.
Line 166 then gets the low part of the 7 bits but also shifts to the right to go back to its original position shifted earlier.
Similar to the earlier delay(2), this facilitates the smooth running of the program through the pitch bend code.
The program is then prompted to print the text “highByte value: “ and print the “msb”, followed by the text
“lowByte value: “ to then print the “lsb” which ends the first pitch bend section of the code.
Line 217 is the end of the void loop() function, and the end of
the code.
Code 5
5) Full Code
Evaluation
In order to showcase the way the program works along with the physical Input sensors, here is the
link to a demonstration video:
https://uwloffice365live-
my.sharepoint.com/:v:/g/personal/21403399_student_uwl_ac_uk/ESp5s5h_M_ZEmZ3UqPlmuSUBVdi40ZT
5KvAqNk2PzYGczQ?e=WQHri4
The following image of the Ableton Live 11 session is a screenshot of what the session looked like during the
demo video. Displaying the different channels on the different tracks to exhibit the use of the channel
switcher potentiometer.
Pic 8
Each button sends the proper note and both the channel switcher as well as velocity varying potentiometers
work exactly as intended and permit a wider range of use of the MIDI controller. The pitch bend
potentiometer, unfortunately only works on channels 1 to 10, however, on these 10 different channels, it
permits a pitch bend of up to one octave higher than the original note. When used with continuous
instruments especially like strings or pads, the pitch bend becomes a great feature, as it only goes note to
note, it is not as great on single note instruments like the piano or glockenspiel, but still enables a greater
variety of possibilities than if the notes were restricted to their first programmed pitch.
Conclusion
To conclude, this MIDI controller remains very basic. Like a commercial MIDI keyboard it has key push
buttons and pots. It could have been a more complete controller had there been more material and inputs.
However, material-wise, the four push buttons were the only available. With two more the function of
octave shift would have been added. The pots on MIDI commercial MIDI controllers can be assigned to
Control Changes on the DAW, in this instance the choice was to make a controller that can be plugged into
any DAW with very few setup. Only assigning channels to different instruments, and then it can be
immediately used.
Input-wise, the Arduino Uno has more digital pins as well as analogue pins to enable a greater variety of
inputs. Nevertheless, the computer used for this program is a Macbook Pro 2020, 13inch, M1 chip. In order
to use Arduino with MIDI USB sent messages, the program requires the software “Hairless” to transform the
sent MIDI information by Arduino IDE into MIDI USB. “Hairless” being a 32-bit software cannot be opened
on the computer as the M1 chip is incompatible with 32-bit applications. Thus, a Arduino Micro Pro has to
be used.
Finally, if more time had been available in the computer laboratories at the University of West London, more
research on the functionality of distance sensors could have been made as this was the very first idea for
this project. However, due to the sanitary crisis, the labs had limited access, and allocated enough time for
a thorough understanding of buttons and potentiometers linked to MIDI, creating this here functioning MIDI
controller.
References
- Arduino2go, 2017. Chapter 6: Analog input – Arduino to Go. [online] Arduinotogo.com. Available at:
<https://arduinotogo.com/2017/02/28/chapter-6-analog-input/> [Accessed 4 June 2021].
- PretEnGineering, 2019. Arduino Cloud. [online] Create.arduino.cc. Available at:
<https://create.arduino.cc/editor/lnimmo/1d45349b-ae1b-4521-af2f-1ba3bb4d0db7/preview> [Accessed 4
June 2021].
- PretEnGineering, 2019. Arduino MIDI controller and Instrument! - Arduino Tutorials. [online] YouTube.
Available at: <https://www.youtube.com/watch?v=s-gcZ61Dj5g&t=218s&ab_channel=PretEnGineering>
[Accessed 4 June 2021].
- Tigoe, 2019. MIDIUSBPitchBend.ino. [online] GitHub. Available at:
<https://github.com/tigoe/SoundExamples/blob/master/MIDI_examples/MIDIUSBPitchBend/MIDIUSBPitch
Bend.ino> [Accessed 4 June 2021].