Introduction: Basic Arduino MIDI Arppegiator
In this instructable I will show you how to make a basic MIDI instrument using an Arduino Uno. This instrument plays three notes (a triad) in a row. Using the different potentiometers, you can move up and down the notes as well as up and down a scale. You can also control the delay between each note. I feel like I learned a some interesting things about MIDI controllers from this project and I hope you will too.
This instrument is a really basic version of an arpeggiator. Here is a video of a fancy one in action. Arpeggiators exploit the natural musicality of chords to make a lot of nice sounding noise for not that much effort. They often come as part of synths where you just hold down the chords you want to be arpeggiated. In this example, we have only have one button that trigger the arpeggio and three buttons to control what the starting pitch is and its position on the scale.
For the arduino Uno, the easist way to use the MIDI protocol is over the Serial port. It takes some configuration for this to work on Windows, which I will go over. I used the Ardunio MIDI library by FortySevenEffects. I also followed these excellent youtube tutorials: MIDI for the Arduino, How to construct a MIDI controller with an Arduino. I based the code for controlling the buttons and the potentiometers from the code from the second video series. It is really well documented at part of an entire free course on making MIDI controllers.
In this project I used the Grove Starter Kit Plus for the RGB backlit LCD screen. This is not strictly necessary, but it is nice to see what notes you are playing.
Supplies
- 4 potentiometers (I used whatever I had lying around)
- 1 Button
- 1 1k resistor for button
- 1 Arduino Uno
- 1 Grove Starter kit/ RGB backlight LCD (optional)
- Wires for connecting pieces
For the computer
- DAW (I am just using a trial version of Ableton right now. Cakewalk is free)
- Hairless MIDI (A serial bridge-- something that converts your serial output to MIDI input)
- Loop MIDI (Creates virtual loopback ports for your computer. )
- Arduino IDE
Step 1: Setting Up the Board
Below is a diagram of the layout that I used without the LCD. The button will be used as a trigger to start the arpeggio. Three of the potetiometers will control different aspects of the arpeggio and the last potetiometer will serve as a MIDI control.
In my actual circut layout, I used the Grove board (which connects on top of the Arduino Uno). It came with a button and a decent potetiometer, which you can see in the above picture plugged in to their respective ports. The LCD screen was very easy to connect with this, you just connect one of the cables that come with the Grove kit from the LCD screen to the I2C port.
Attachments
Step 2: Understand MIDI, Ever So Slightly
MIDI is a communication protocol that was purposely built for musical instruments created in the early 80's. With the software setup we have, we could use MIDI for input as well as output to our arduino but just to keep things simple we will focus on output. Specifically we will use two different channel voice messages: Note On and Controller Change. Note On allows us to tell the DAW or whatever we are using to turn on or off a note, and at what velocity (MIDI's strange way of saying volume.) Controller Change tells the DAW that a value of a controller has changed. You can imagine this as twisting a dial on an amplifier, wheter it is for volume or some effect like distortion or reverb. There are tons of other message types, and things can get really elaborate, really quickly. The MIDI library we are using has a bunch of functions to support these different message types.
Interested in finding out more? I would first refer you to the youtube links that I put at the beginning of the instructable. Then I would search around to see what people have done with MIDI to get an idea of the possibilities.
For Note On, this is a link to a list of pitches and their assigned MIDI values. For example, C4 has a midi value of 60. Each number maps to a semi-tone, so it is really easy to use modulo division to figure out what note you have. Given C4=60, I know that C5 = 72, C6 = 84, without having to look at a table because I know the octaves are spaced 12 semitones apart. This will come in handy later when we are converting the MIDI values to notes to display on the LCD screen. Also, if we save the Cmaj scale MIDI values to a list, we can use mod7 division to move around values in a scale.
Step 3: Code
If you do not want/need the LCD I attached a version where I commented out the LCD components. I heavily commented in the code, but here I will point some things out, starting from the top.
Initializing variables:
- The variable "debounce_delay" for the button and the variables "Timeout" and "var_threshold" can be used to reduce some of the noise and false readings from the button and the potentiometer. If you are having problems, that would be a good place to start. The potentiometers can get a little testy between boundaries because we are converting a continous range to discrete integers. If the potetiometers are flickering between states too much, there are several ways to address it. One solution that I did not implement here is to take several readings and average them before you do any further processing.
- The list "notes" is what sequence of notes we are going to play in the arpeggio. I have it set to play the starting note, and notes 2 notes and 4 notes a way in the major scale. This will make basic major, minor, and diminished chords. If you want something a little more interesting, you can add more notes to the list "notes". Just don't forget to change the constant "CHORD_LENGTH". For example, you can do this:
const int CHORD_LENGTH = 6; //number of notes in chord int midi_vals[CHORD_LENGTH] = {}; //array to store midi-output to play int notes[CHORD_LENGTH] = {0,2,4,2, 5,7}; //1st 3rd, and 5th note on scale, plus the 7th. This is more jazzy
- By creating the list "Cmaj_scale" I have created a template that I can move up and down to create the chords. If I want to change the key, all I need to do is change "midi_c_state[2]" using inputs from the 3rd potetiometer. If I just want to move around the major scale from a given starting note I just change "midi_c_state[0]" from the first potetiometer.
Setup:
- You need to have the correct Baud rate for Hairless MIDI to read your serial input correctly. Otherwise you will get errors in Hairless MIDI like "got unexpected data byte"
- The LCD screen comes with 16 column digits and 2 rows. I
Loop and associated Functions
- The Function "pause_length " controls the delay between notes being played.
- "starting_scale_position" allows you to move up and down the major scale without changing key. "Starting note" allows you to shift everything up or down a half-tone value, allowing you to change key. Both functions call "move_chord" that remaps the notes you have selected to MIDI values.
- Changing the delay, starting scale position, MIDI control or note will cause the LCD to refresh.
Attachments
Step 4: Setting Up the PC
For this to work, you need to download Hairless MIDI, a DAW, and Loop MIDI. The links to them are at the beginning.
First off, open up LoopMIDI and click on the plus button in the bottom left corner. This will create a loopback port called "loopMIDI port". If you then open up Hairless MIDI, you should see it as an option in the drop down menus for "Serial Port" and "MIDI Out". You can ignore "MIDI In" for this example. Note: If you have a lot of inputs from your controller, for example if a potentiometer is making a lot of noise, your computer will shut down the port and you will see it in LoopMIDI. You should try to make your potentiometers less noisy, then delete the port on LoopMIDI, using the "Minus" button on the bottom left of the screen. Then create a new port using the plus button and try again.
In Hairless MIDI, if you did it correctly, when you click on "Debug MIDI messages" and you trigger your MIDI controller, you should see what kind of MIDI message it is, as pictured. If there is a problem with your Baud rate, you will get an error like "Warning: got a status byte...". You just need to go into preferences and select the correct Baud rate. I included a screenshot of what worked for mine.
Now all you need to do is choose your favorite DAW and set it up so it can take input from LoopMIDI. This video which is part of one of the series that I linked to in the beginning, shows how it is done for Ableton, but different DAWs may vary.
Step 5: Enjoy!
Here is a demo of my project. In this video, I go over the basic functionalities. I also added an MP3 of some of the sounds that it can make if you just want to know what it can do. Here are some ideas for additions to this project:
- A way to choose between different arpeggio patterns
- Screen scrolling on the LCD to fit larger arpeggio patterns
- More midi controls/buttons
- A queing system so you could schedule one arpeggio after another
Happy Tinkering!