0% found this document useful (0 votes)
352 views

USB MIDI Controller With Arduino Leonardo

Breadboard circuit to send MIDI messages over USB to a DAW and create a small MIDI controller with the Arduino Leonardo microcontroller.

Uploaded by

leo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
352 views

USB MIDI Controller With Arduino Leonardo

Breadboard circuit to send MIDI messages over USB to a DAW and create a small MIDI controller with the Arduino Leonardo microcontroller.

Uploaded by

leo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Design and development of a MIDI controller using

the Arduino prototyping platform

A2 ESAT

Leo Romain Foulloy


UWL Sound Engineering year 2, Embedded Systems for
Audio Technology, TC50321E
Abstract
Musical Instrument Digital Interface most commonly known as MIDI is connectivity standard for transferring
digital instrument data invented in 1983 by Ikutaro Kakehashi a Japanese engineer and inventor alongside Dave Smith
an American electronics and computer engineer. The first synthesisers released with this technology were the Roland
Jupiter-6 and the Prophet 600.
MIDI connections have now become a standard of the music industry. From studio productions using MIDI controller
keyboards to live shows with MIDI connected guitar pedal boards, the majority of contemporary popular music is
created using MIDI signals.
Upgrading from a 5-pin connector known as MIDI-cables to USB connections, the Digital Interface technology has
greatly improved over the years. So much so that it can be used by prototyping platforms to create small MIDI
controllers.
Table of Contents
Abstract ................................................................................................................................................... 1
Images..................................................................................................................................................... 3
Code images ............................................................................................................................................ 3
Introduction ............................................................................................................................................. 4
Circuit Design........................................................................................................................................... 4
1) Tinkercad and Breadboard .......................................................................................................................... 4
2) Push Buttons Connection ............................................................................................................................ 5
3) Potentiometer Connections ........................................................................................................................ 6
Code Design ............................................................................................................................................. 8
1) Code Start (void functions and “setup”) ...................................................................................................... 8
2) Buttons Code .............................................................................................................................................. 8
3) Velocity and Channel change Potentiometers Code .................................................................................... 9
4) Pitch Bend Potentiometer Code ................................................................................................................ 10
5) Full Code ................................................................................................................................................... 12
Evaluation ............................................................................................................................................. 15
Conclusion ............................................................................................................................................. 16
References ............................................................................................................................................. 17
Images
- Pic 1: Tinkercad circuit representation
- Pic 2: Breadboard circuit design
- Pic 3: Button1 breadboard circuit connection
- Pic 4: Potpitch breadboard circuit connections
- Pic 5: Potpitch breadboard A0 connections
- Pic 6: Potpitch breadboard GRND connections
- Pic 7: Potpitch breadboard Vcc connections
- Pic 8: Ableton Live 11 demonstration session

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.

Tinkercad Circuit Representation:

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.

2) Push Buttons Connection


Button1 Breadboard Circuit Connection
All four buttons are connected in a similar fashion. In the right-hand
side image is shown mainly the connections for button1.
As can be seen, button1 has 3 connections.

-Connection to the voltage source (Vcc) through a 1kW (1 kilo-Ohm)


resistor linked to the button’s top left terminal.

-Connection to the Ground (GRND) through an orange cable shown


at the bottom of the picture, incidentally linked to the other buttons’
GRND connection.

-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

PotPitch Breadboard A0 Connection

As aforementioned, through the close up on the potentiometer in


Pic 4, the blue wire through the variable terminal of the potpitch
(right-most) potentiometer, is connected to the A0 Input as seen
here.

Pic 5

PotPitch Breadboard GRND Connection

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).

1) Code Start (void functions and “setup”)

The functions “noteOn” and “noteOff” are used


by the buttons. These must be declared, to
precise in which order the bytes will be assigned.
In this case it goes (channel, pitch, velocity) but
can be switched around.

The “midiCommand” function, has multiple uses


to send Command data via MIDI USB, here used
for pitch bend. Similar to the “noteOn” and
“noteOff” functions, this one declares that it will
be formatted with (command type, data1,
data2) data 1 and 2 will vary depending on the
command type.

In order for the Arduino Micro Pro to recognise


Inputs at its pins, there are two necessary steps:

The first is to declare which pins are used and


what their value is. Hence the “const int”, this
assigns a constant integer, a value which will
remain the same to the Input pins of the
Arduino.

The second, is to configure the I/O, in other


words, whether the pins are Inputs are Outputs.
Here being that all pins are input sensors, they
are all configured as inputs.
Code 1
The Serial.begin message sets up the communication between the Arduino board and the Serial Monitor which enables
the user to watch how the program behaves if specified to do so within the code.

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.

3) Velocity and Channel change Potentiometers Code

Line 60 is the start of the loop() function which


repeats the code inside of it until the user decides to
end the program.

Every line between line 61 to line 217 is part of the


loop() function and will be read through line by line
and then repeat.

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.

4) Pitch Bend Potentiometer Code

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.

This next portion of code links the pitchBend alongside the


potChannel.

In the way that the MIDI message is sent, there needs to be a


midiCommand() function. Similar to the noteOn/Off()
functions used by the buttons. Each time a button is pressed
it sends a noteOn() MIDI command, when it is not it still
sends a noteOff() MIDI command.

For the pitchBend to send its MIDI command, it requires a


function called midiCommand(), this is formatted with the
(event type & channel, byte 1, byte 2).

As seen here, the midiCommand() format requires the use of


a channel. Upon attempting to declare man integer “i” with
the value of potChannelmap or a for() loop, for which the
value of “i” changes alongside potChannelmap. The
formatting of the midiCommand() function makes it so the
value of the Channel must be a digit between 0-9.

As such, following the values of potChannelmap, the code


here shows an if-else statement which sends pitchBend data
to the right channel depending on the channel called by
potChannelmap.

It will limit the available channels to pitch bend on the DAW


between 1 and 10, but it is already 10 different channels on
which the user can use a pitchbend.

Finally, the code delays each sent message by 800ms. Which


means that each midiCommand sent by the program is only
sent every 800ms, converting it to a bpm in 4/4, that makes
for notes at a bpm of 75.

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.

Ableton Live 11 Demonstration Session

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].

You might also like