Here's a list of the materials I used:
* Arduino Uno (running on Mac OS X 10.7.4 Intel)
* USB cable
* 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
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
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
* 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)
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.