After this tutorial, you will be able to control Ableton Live instruments or devices with the motion of you hand. We will build the hardware circuit, write the Arduino code, construct the Max patch and put it all together! No soldering required!
If you are new to these concepts I suggest following along with my previous tutorial which is more of an entry level tutorial, while this one is more involved.
What you will need to follow along.
- Ableton Live (the latest is best)
- Max for Live (the latest is best)
- Arduino Uno with USB & Software
- Ultrasonic Ranging Module HC - SR04 or equivalent
- 4 x female to male breadboard jumpers (this is best)
DOWNLOAD: Finished Max Patch and Arduino Sketch
Hardware Setup
The hardware setup for this project is quite simple. Make sure the Arduino is not being powered. Take a look at the Ultrasonic Ranging Module. It has 2cm - 400cm non-contact measurement functionality, with ranging accuracy that can reach up to 3mm. It sends out 8 cycle 40 kHz signal busts and waits until it gets the bust back by way of reflection. Then it does some math to figure out the distance depending on how long the reflection takes to return.
If you would like to see the full specs for the module click the link here.
There should be 4 pins extruding from one side. They are labeled VCC, Trig, Echo, GND.
The VCC stands for Voltage at Common Collector. We will want to run a jumper wire from it to one of the 5V pins on the Arduino.
The Trig is short for trigger. You send a pulse to the trigger to start the module ranging. We need to put this into any of the digital pins on the Arduino. I am using digital pin 12.
The Echo waits and calculates the distance if an echo is received. We need to put this into any of the digital pins on the Arduino. I am using digital pin ~11.
The GND is short of Ground. We need to connect this to one of the Arduino’s GND pins.
Now, beyond plugging the Arduino into the computer we are done. Can you believe it? Let’s move on to the Arduino Sketch.
The Arduino Sketch (program)
Below you will find a photo of the Arduino Sketch. I suggest you copy it from the picture. Copy it word for word. I have added a good deal of comments to explain what each line of the code is doing. Copying it will help you understand what is going on better than if you just download it and don’t take a critical look.
Though if you want, the sketch is available in the download for this project.
Plug in your Arduino if it isn’t already.
Once you have the code written, or loaded, you need to make sure your device and the correct port are selected before you can upload. Go to Tools in the main menu of the software and make sure your Arduino type is selected.
Now, if you are like me, and you like your code to look beautiful, there is a neat option in the Tools menu. It is at the top and it’s called “Auto Format” (Ctrl+T). This will read your code and make any changes to the formatting.
Click the Check Mark in the top left to Verify the code. If you are good to go and have no errors, which should be the case if you did things correctly, hit the Right-Facing Arrow to upload the Sketch to the Arduino.
Once done you should see a message saying it was uploaded successfully. Now, we can verify that everything is working. Wave your hand in front of the sensor. You should see the LED on the Arduino turn off when your hand is in range. Remember there will be a slight delay, so don’t panic!
We can also verify that the numbers are being printed correctly by opening the Arduino Software’s Serial Monitor. It’s the little magnifying glass icon in the top right of the program. When there is nothing in front of the sensor it should just be printing -1 after -1. Then if you wave your hand in front of it you should see values. Moving your hand closer should result in smaller numbers and farther away will get larger numbers. Those numbers are the distance in Centimeters.
The only numbers you need to make a serious note of are the max & minimumRange values. These determine how far the sensor will be looking for movement. So, if you want a longer or shorter range you need to update the values in the sketch and re-upload to the Arduino. Then you need to change the input min/max on the “scale” object in the Max patch, more on that in a bit.
- int maximumRange = 30; // The max distance observed from the sensor
- int minimumRange = 0;
The Max for Live Device
Originally, I went ahead and made an entire, albeit basic, Max patch that worked with the Dry/Wet parameter of the simple delay. However, there were a number of issues with that. Like, for instance, not all parameters have uniform minimum and maximum values. The reverb’s decay time is drastically different form the Dry/Wet parameter, for example.
In order to save time and headaches for those who are just looking to get this thing working I chose to modify one of the example Max API devices. Specifically, the Max.API.DeviceParam device. I went with this one because of its incredible versatility and of course how well it was made.
Max.API.DeviceParam device allows you can choose any device in the set from any channel, the return tracks or the master.
That can be found in the Max for Live browser window -> Max Audio Effect -> Max.API.DeviceParam

Using Max.API.DeviceParam gets us most of the way the way to success town, but we need to modify it to get and use the information (data) being sent from the Arduino & Sensor into the computer.
After you load with the Max.API.DeviceParam you should immediately go to “Save As” and rename it so we can avoid messing up the original device if anything goes wrong.
Go ahead and open Max for Live by clicking the edit button on the device. Unfreeze and then go into patching mode. Double click the object called “patcher Properties”. This is a subpatcher and that is where we need to do our editing.
NOTE* The main device needs to be locked when you double click if you are looking to edit the subpatcher.
Now we need to add the following objects into the patch.
Everything that is red in the photo below is what we need to add in order to make this patch communicate correctly with the Arduino.
The print button will help to make sure you have the correct COM referenced.
Essentially what is happening with the additions is that we are telling Max to open a “serial connection”, info passing over USB, and look for any data being sent out. That data is read, interpreted and translated into numbers Max can work with.
Those numbers are passed into a scale object. The scale object makes everything nice and neat. The first two values are the min and max coming out of the Arduino, which you might remember from the Sketch (min 0, max 30). Then the second two numbers are the new min and max values the input is scaled two which come from whichever device we have selected. Then the new scaled values will control the “live.property value @observe 1“ which will then update and control whichever parameter we have selected in Live
There you go. I hope your custom DIY motion controller is working at this point and maybe you learned a thing or two along the way!
I want to give a special shout out to Michael Mckellar for helping to get me started with the base for the Arduino Sketch and Max patch.
Discussion
The thing is that the m4l patch doesn't work; I've downloaded the .zip with the patch and the sketch, but my Live says it is broken.
Thank you for sharing, man!
The thing is that the m4l patch doesn't work; I've downloaded the .zip with the patch and the sketch, but my Live says it is broken.
Thank you for sharing, man!
Best,
Stephen
I downloaded what you had setup. Followed it precisely. No error messages in the Max window. Everything you did is very well put out by the way and I wish I had more to tell you about the problem. I am basically just not being able to finally map my Arduino to a desired audio effect. I can read the numbers as states previously.
So yes, I have downloaded your files. The numbers show up correctly, and I am not getting any error messages in the Max window.
Thank you for your quick response!
Stephen
Same problem happening to me. Anyways I am still glad you make tutorial like this. I have done everything from the text above. Hope you help us out anyhow.
Dan
Dan
I copied the code from the downlload. All I have is -1. What do you think?
First of all, thanks for this great tutorial, i guess this is an inspiration for a lot of people(including myself) to start programming arduino's.
I got as far as making the sensor work with the uploaded code but is i am totally new to M4L is got stuck in the first step, i cannot seem to find Max.API.DeviceParam, my max for live browser is practically empty. Any sugestions for this problem?
greetings
Simon
I'm using arduino uno too.
Similarily my port is different but it is still the port Arduino is connected to. Any tips?
Thank you! Great project!
Thank you for this great tutorial! It's exactly what I have been looking for.
I have a similar problem to Stephen. Everything has been setup and I have gone through it with a fine tooth comb but still the dry/wet knob does not move. I have used the coding/patches you provided and everything is setup but still I cannot get the device to speak with the max patch.
Any suggestions?
Thank you!
Andrew
I had the same issue described in the other comments. I followed these steps to get it working (Ableton 10):
1. From Ableton click on 'edit' button to launch Max editor
2. Click on properties button
3. Open Max console from the Window menu
4. In the properties section click on the red 'print' button
5. All available serial ports should be printed in the console. In my case the 'port b' showed the USB modem, which I guess is the port the Arduino is connected to.
6. Next close the subpatch (properties) screen and unfreeze the Max patcher (lower left side of the screen)
7. Make sure the main patch screen is locked (button next to freeze) and click 'Properties'
8. Unlock the properties subpatch
9. Change the 'serial' object such that it now states 'serial 9600'. Where as in my case was 'b'.
This procedure made my setup work with Joshua's Arduino sketch. Hopefully this can be of use to anyone.
Note: I also made a small change to filter out all '-1' values, because this is interpreted as an invalid value by Ableton. (I added a 'sel -1' object just before going into the scale object -> using left inlet and right outlet, which forwards everything accept for '-1'. Don't know if this is the best approach, this is my first day working with Max).
regards,
Arjan
I'm so happy that I found what I was looking for months.Thank you very much.
But!
I downloaded the files but as I set UltraSonicSensor to control fro example Simple delay nothing is really happened. I noticed that i had a message at the max console that
"live.object 'DeviceParameter' object has no attribute 'default_value'.
Could you please help me how can I figure that so to control effects on Ableton with the UltraSonic Sensor?
Thank toy again!!
Charis
Everything went as planned according to Joshua's instructions until i got here:
''The Max for Live Device''. These are the files that i get when downloading the Finished Max Patch and Arduino Sketch : UltraSonicSenosrController.amxd,ultrasonic-sensor-MAX.ino and UltraSonic-Sensor-Controller.adv.
The first two seem to load ok but when i load the adv file i get the orange ''missing files'' orange notification in the top bottom side of ableton. I tried to relocate the file by dropping it in the Replace Files menu that pops when i hit ''manage device file'' but it doesn't seem to do anything. Can someone please help? Thanks in advance
#define SENSOR_2 1
#define echoPin1 11 // The number of the digital pin connected to the echo input
#define trigPin1 12 // The number of the digital pin connected to the trigger output
#define echoPin2 8 // The number of the digital pin connected to the echo input
#define trigPin2 9 // The number of the digital pin connected to the trigger output
#define LEDPin 13 // This enables the LED feedback for testing
int maximumRange = 50; // The max distance observed from the sensor
int minimumRange = 0;
long duration1, duration2, distance1, distance2; //duration used to calculate distance
void setup() {
Serial.begin(9600); //starts the serial communication via USB
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(LEDPin, OUTPUT); //board LED for testing
}
void loop() {
// sensor 1
if (SENSOR_1) {
digitalWrite(trigPin1, LOW);
delayMicroseconds(2); // pulse off
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10); // pulse for 10 microseconds
digitalWrite(trigPin1, LOW);
duration1 = pulseIn(echoPin1, HIGH); // echo pin listens / receives
distance1 = duration1 / 58.2;
// error handling
if (distance1 >= maximumRange || distance1 = maximumRange || distance2
#define SENSOR_1 1
#define SENSOR_2 1
#define echoPin1 11 // The number of the digital pin connected to the echo input
#define trigPin1 12 // The number of the digital pin connected to the trigger output
#define echoPin2 8 // The number of the digital pin connected to the echo input
#define trigPin2 9 // The number of the digital pin connected to the trigger output
#define LEDPin 13 // This enables the LED feedback for testing
int maximumRange = 50; // The max distance observed from the sensor
int minimumRange = 0;
long duration1, duration2, distance1, distance2; //duration used to calculate distance
void setup() {
Serial.begin(9600); //starts the serial communication via USB
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(LEDPin, OUTPUT); //board LED for testing
}
void loop() {
// sensor 1
if (SENSOR_1) {
digitalWrite(trigPin1, LOW);
delayMicroseconds(2); // pulse off
digitalWrite(trigPin1, HIGH);
delayMicroseconds(10); // pulse for 10 microseconds
digitalWrite(trigPin1, LOW);
duration1 = pulseIn(echoPin1, HIGH); // echo pin listens / receives
distance1 = duration1 / 58.2;
// error handling
if (distance1 >= maximumRange || distance1 = maximumRange || distance2
I have both sensors communicating with ardunio, and used an unpack object to split the signal in max. However, similarly, I do not know what else to write into the max patch so I can control two different parameters.
Want to join the discussion?
Create an account or login to get started!