(8/09)
GPS-based theremin-a-like.
In July 2009, I was working with Phill and John from Dorkbot Bristol on some Arduino audio projects which were part of Staging Sound 2.0 in Bath.
That gave me ideas, so I bought some bits and spent some of my time at HAR in Holland, sitting on the floor of a tent fiddling with code. By the end of HAR, I had a working GPS-A-Min.
It is, more or less, a very big theremin. I use an LS20031 GPS Module to track position. The position is converted to a MIDI note number, and the note number is used to drive direct sound-synthesis code running on an Arduino.
Sound output is done without the benefit of a D-to-A converter. Instead, the Arduino's PWM output is run at 32kHz, and the audio signal is generated by varying the PWM duty cycle. It's a clever hack, and it works. Notes are actually generated by looping over a wavetable.
This project borrows heavily from several other Arduino projects (and I'd like to thank them all):
The Auduino does the PWM trick, but uses a different synthesis model.
The Arduino Theremin/Synth Code by Max Pierson does tricks with wavetables, but it generates effects by dynamically recalculating the wavetable, which we do not do here.
The Ardupilot project has some good NMEA parsing code, plus specifics on working with the LS20031.
I have added vibrato and sweep effects to the audio generation code, and tweaked code to convert position to note number to get the maximum possible sensitivity. One note now corresponds to a distance of a couple of feet.
The audio code is actually capable (on a 328 Arduino) of polyphony. Three notes is about the limit. I really ought to move more code out of the PWM interrupt routine - the logic for managing sweep and volume could be handled in loop() instead of in the interrupt routine. That might get more polyphony.
It's worth knowing (if you get to experimenting with this code) that the app will start to behave in very strange ways if you make the interrupt routine run for too long. First, code in loop() just doesn't execute. Second, the interrupt routine just stops when the next interrupt happens, so things like note volume decay just stop happening. So, if you have inexplicable syptoms, try turning down the value of NOTES and see if the world makes a bit more sense.
Another wrinkle is to do with power supply - when running this thing off batteries, you would expect the Arduino to flake out before the GPS as the batteries went undervoltage. But that is not the behaviour I observe. I suspect the Arduino can run at a bit under 5V, but the 3.3V regulator that runs the GPS cannot. So, if you seem to have a mysterious failure to maintain GPS lock, check your rail voltages.
This page also needs photos of the hardware, a circuit diagram, and a sample of the audio output. The circuit is terribly simple - connect Rx and Tx on the GPS module to Tx and Rx on pins 0 & 1 of the Arduino, connect the 3.3V output from the Arduino to +VCC on the GPS module, and wire a speaker or an audio input to the PWM output on pin 3. A cheap MP3 player amp & speakers (four pounds from the garage down the road!) works well.
Note that the Arduino also uses pins 0 & 1 for programming, so you need to disconnect the GPS in order to reprogram the Arduino. It also means that you need to debug the NMEA parsing code without the benefit of logging.
Here's my source as of the end of August 2009. If you use it for something, I'd love to hear about it, and if you have any questions please drop me a mail.
The Pisan-O-Matic project, which followed on in the Dorkbot work, has much better sound generation now, thanks to John's efforts.
If you are interested in this, you may be interested in that. Take a look at the code here.
And, after the Pisan-O-Matic came World-O-Music, which was a generative-music project which based its tune on its GPS location. More details and code here.