An instrument I’ve always admired is the theremin–it reminds me a bit of the smooth movement of the harp. Thus, for my practice this week, I decided to build a very mini version.
I wanted to try to use the ultrasonic sensor in our kits and wanted to be able to control at least one more variable such as volume or pitch. I decided to use the sensor for determining the note played and the potentiometer for controlling the volume.
I must admit I broke the rules of this assignment…I used serial communication between processing and arduino! In my defense, I broke the piezo buzzer and didn’t have a soldering station to fix it. Thus, my only way to test whether my instrument was working was to play using the output of my computer.
I used this tutorial to understand how the ultrasonic sensor worked and how to connect the four pins. One went to ground, one went to 5V, and the other two went to pins on my arduino (though one pin is input and the other is output). The code I used to find the distance of an object near the sensor seemed pretty standard between tutorials, but essentially a sound wave is emitted and then bounces back when it hits an object. We multiply by the speed of sound and then divide by 2 (so its just one way the wave travels).
From there, it was pretty straightforward. I read the value from the potentiometer and wrote the potentiometer value and sensor distance to the serial for Processing to read.
In Processing, I used an array of notes that mapped to the distance of the sensor. I used this documentation to learn more about creating a triangle wave. Essentially, all I did in Processing was read from the Serial and map the values and then play the triangle wave with the frequency depending on the sensor distance value and the amplitude (volume) depending on the potentiometer value.
I think it could be cool to experiment further by changing octaves and seeing if the photoresistor was more smooth than the ultrasonic sensor and adding LEDs that respond.
Here is my instrument!
Here is my Arduino code:
int trigger = 4; int echo = 3; int pot = A0; int distance; int duration; int volume; int c_notes[] = {35, 65, 131, 262, 523,1047, 2093, 4186}; void setup() { Serial.begin(9600); pinMode(trigger, OUTPUT); pinMode(echo, INPUT); pinMode(pot, OUTPUT); } void loop() { digitalWrite(trigger, LOW); delayMicroseconds(2); digitalWrite(trigger, HIGH); delayMicroseconds(10); digitalWrite(trigger, LOW); duration = pulseIn(echo, HIGH); volume = analogRead(pot); // Use 343 metres per second as speed of sound distance= duration*0.034/2; Serial.print(distance); Serial.print(","); Serial.print(volume); Serial.print("\n"); }
Here is my Processing code:
import processing.sound.*; import processing.serial.*; Serial myPort; TriOsc triOsc; //array of notes int[] midiSequence = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83}; float amp; int note = 0; void setup() { size(640, 360); String portname=Serial.list()[2]; println(portname); myPort = new Serial(this,portname,9600); myPort.clear(); myPort.bufferUntil('\n'); // Create triangle wave and start it triOsc = new TriOsc(this); void draw() { //frequency, amplitude (volume) triOsc.play(midiToFreq(midiSequence[note]), amp); } // This helper function calculates the respective frequency of a MIDI note // taken from example 2 in processing documentation https://processing.org/tutorials/sound/ float midiToFreq(int note) { return (pow(2, ((note-69)/12.0))) * 440; } void serialEvent(Serial myPort){ String s=myPort.readStringUntil('\n'); s=trim(s); if (s!=null){ int values[]=int(split(s,',')); if (values.length==2){ note=(int)map(values[0],-100,350,0, midiSequence.length); amp = map(values[1], 0, 1023, 0, 1); } } }
Theremins are cool for sure! Maybe try smoothing the note frequencies so it glides between the notes, that’s more like a real theremin (and would remove those glitchy sounds you get).