Arduino Optical Theremin

148,436

378

59

Introduction: Arduino Optical Theremin

When I first became aware of Arduino, a theremin seemed like a natural project: sensor + actuator.  It turned out to be quite affordable and fun to make.  It is a naive design, using just one photocell and some hacked headphones.  After some experimentation, I decided that a  self-calibrating function was essential if I wanted repeatable performance in different light levels.  Also, I decided to autotune it using math instead of a lookup table.  To me, the pentatonic tuning is the most pleasant, although this can be adjusted easily to chromatic or other tuning schemes if desired.

Here's a list of the materials I used:

* Arduino Uno (running on Mac OS X 10.7.4 Intel)
* USB cable
* Breadboard
* Super-cheap earbud style headphones (from a plane flight, I think)
* standard small photocell
* 10K Ohm resistor
* Some wire
* Soldering gun with solder

Step 1: Hack the Headphones

In order to send signals to the headphones, I cut the wires and soldered them to some jumper wires.  There are a few tricky points here. 

First, once you cut the wires and strip off some insulation, you should see 4 wires, 2 from each side.  Each pair forms a circuit with a single headphone.  So we can effectively think of each pair as containing a + wire (usually colored red or blue) and a ground wire (usually copper colored).  We can either just use 1 of the headphones (and thus one of the wire pairs), or we can combine the wires to use both, thereby achieving twice the fun.  To do this, we will want to solder the + wire from each pair together to one jumper wire, and the ground wire from each pair to the other jumper wire.  See detail photo of headphone hack above.

Second, beneath the obvious rubber insulation, there is often a mostly invisible resin layer coating the 4 individual wires.  The easiest way to get it off is to heat it with a lighter until the wires appear to burn briefly.  Note that after this is done, the colors can be very difficult to discern, so it is a good idea to leave a section unburned that you can use to identify them.  I also use a wet cloth to wipe of some of the residue from the burnt resin to improve conduction.

For the actual soldering, I have very primitive equipment, so I just twist the headphone wires together and around the jumper cable and then drip some solder on that.

Step 2: Assemble the Circuits

There are two simple circuits involved.

Headphone circuit: Use any Adruino digital out pin and a ground to make the circuit with the headphone jumper cables.

Sensor circuit: It's a standard voltage divider job that lets the varying resistance of the photocell modulate a voltage read by an Arduino analog in pin.  First, I make a series circuit that starts from the Arduino 5V power pin, goes to my photocell, then to my 10K Ohm resistor, and finally back to Arduino ground.  I probe the voltage at the node between the resistor and the photocell using the A0 analog in pin.

Occasionally, I had problems with flaky connections.  I think I need to use better jumper cables next time.  When things just weren't working right, I could just wiggle some cables and identify the flaky connection.  Securing the cable more firmly in the breadboard or re-burning the resin always did the trick.

Step 3: Write the Code

The heart of the code is basically two commands:
* An analogRead that gets the value of the voltage from pin A0.  This effectively measures the light level on the photocell.
* A tone command that sends a signal to pin 9 and causes the headphones to produce a tone at a specified frequency.

Of course there are a lot of other things to be done:
* Variable definitions
* setting up pin 9 for output
* Calibration loop: The user exposes the photocell to a range of light levels, teaching the program how to scale frequencies
* Compute scale and shift parameters based on calibration data
* Autotuning:  rounding frequencies to the nearest desired note using logarithms

The sketch is attached as a text file and has a ton of comments.

Step 4: Play (see Video Link)

Now you just open the Arduino editor, verify the sketch, plug in the USB, and upload.  Here's a video of what it should be like.
Of course there's plenty of room for modification and improvement.  Some possibilities include:

* Adding a volume control like (potentiometer, or another photocell)
* Using a better speaker
* Making the code more efficient (fewer doubles)
* Taking advantage of the map function instead of mapping the calibration by hand

Feel free to suggest your own ideas, and have fun annoying people with your theremin.

8 People Made This Project!

Recommendations

  • For the Home Contest

    For the Home Contest
  • Game Design: Student Design Challenge

    Game Design: Student Design Challenge
  • Big and Small Contest

    Big and Small Contest

59 Comments

0
GryfalconA
GryfalconA

2 years ago

For anyone having the Double Log error, change the name of the variable and the problem will be resolved. I just got rid of the "g" and left it as "Lof".

0
EvanMaksud
EvanMaksud

Question 2 years ago

why does mine keep saying 'double log' redeclared as different kind of symbol

0
DavidW31
DavidW31

8 years ago on Introduction

I'm getting some errors. ...sketch_feb22a.ino:13:8: error: 'double log' redeclared as different kind of symbol

/Users/mconstant/Downloads/Arduino.app/Contents/Resources/Java/hardware/tools/avr/avr/include/math.h:304:15: error: previous declaration of 'double log(double)'

extern double log(double __x) __ATTR_CONST__;

^

sketch_feb22a.ino: In function 'void loop()':

sketch_feb22a.ino:62:8: error: assignment of function 'double log(double)'

sketch_feb22a.ino:62:8: error: cannot convert 'double' to 'double(double)' in assignment

In file included from sketch_feb22a.ino:8:0:

/Users/mconstant/Downloads/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/cores/arduino/Arduino.h:88:41: error: invalid operands of types 'double(double)' and 'double' to binary 'operator+'

#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

0
tomapatata
tomapatata

Reply 7 years ago

I just had the same issue, you only need to rename the double variable named logf (I used flogf), probablly in line 9, because it overrides another variable from math.h library. You also need to rename it twice in void loop(). (At least that worked for me)

0
arendt
arendt

Reply 7 years ago

I'm having the same problem.. Solution?

0
Brezorojo
Brezorojo

7 years ago on Introduction

@gwarbeh. Hi, I managed to make this cool project and even got it to work with a piezo buzzer, not with the headphones (probably joined the wrong cables)... But as an electronics virgin I can't figure out where to insert the values in the sketch to make a chromatic or pentatonic scale. Please help!

0
danielg19
danielg19

8 years ago on Introduction

@gwarbeh, if you were to use an Ultrasonic Ping sensor rather than a photoresistor... how would your calibration and note mapping code change?

0
gwarbeh
gwarbeh

Reply 8 years ago on Introduction

Hi, danielg19.

Not really sure, but my instinct is to say that you wouldn't have to change anything. Did you try it as is? The idea of the calibration loop is to adjust to whatever range of values you get. So if your ping sensor spits out totally different voltages than my photoresistor, it should still work as long as you give it a taste of the full range you want to use during calibration. I've never worked with the ping sensor. Maybe it will by more linear in response than the photoresistors. If so, the sound should be a lot easier to control. Let me know how it works out.

0
DavidW31
DavidW31

8 years ago on Introduction

I'm getting this: 63:11: note: in expansion of macro 'round'

Error compiling.

0
j450nn014n
j450nn014n

8 years ago on Introduction

added a push button before the speaker. though I'm sure I can put it anywhere, just so that I don't go insane with it on. this is a good activity to play with lots of variables.

0
rzaragoza2
rzaragoza2

8 years ago on Introduction

having some trouble with this project (my first), the sensor isn't getting any variation in its serial feed ( just 0,0,0) when you view it in the serial monitor. Any tips? the sensors work fine when tested and the circuits are correct when checked by a friend.

0
EmmanuelLobont
EmmanuelLobont

8 years ago

Hi! Can I ask you where I can get the sketch? I'm a beginner with Arduino and wanna practice with this project :)

Hi! Can I implement the code on windows 7?

Also I have a Arduino ng kit... Will this work fine???

0
gwarbeh
gwarbeh

Reply 8 years ago on Introduction

Don't see why not. Just go to Arduino page and find the right download for you.

M a beginner... this being my first arduino project.... M doing it for my college technical fest... Plz help me... M a rookie!!!!!!!!!!!

0
gwarbeh
gwarbeh

Reply 8 years ago on Introduction

No worries, nakul.tomarrajput. You can do it! Just follow the steps and let me know if you have other specific questions.

0
rs242
rs242

8 years ago

Sounds great :-)

temp_828978169.jpg