Headphone Heterotopia - tech notes
Here are some notes on Headphone Heterotopia, a project I am working on with Lesley Flanigan.
A simple box with a selection dial and a headphone jack allows you to pick a city, and experience realtime weather data from that place as a simple musical phrase.
What is happening inside the box: an Arduino microcontroller uses an XPort network controller to fetch weather data from the NOAA (via a PHP script that simplifies it), and uses it to play a melody using an audio circuit based on digital potentiometers and simple oscillators.
Most of the technical issues are now resolved: the microcontroller is successfully parsing the weather data, and feeding it to the audio synthesis routines. Still need to set up the selection mechanism for multiple cities, and build an enclosure.
Here's a picture of the guts of the thing:
Read the past the jump for detailed description and technical issues.
The board in the picture contains a bunch of stuff, from left to right:
* USB to Serial converter, also used to supply 5V power
* 3.3V voltage regulator and smoothing caps, for the XPort
* Xport Ethernet network adapter (and reset switch for same)
* Arduino Mini microcontroller
* Reset for Arduino mini
* 74C14 Schmitt trigger hex inverter - used as VCO (voltage controlled oscillator)
* Row of three 0.1 microfarad capacitors, for the VCOs
* AD5206 digital potentiometer, with 3 pots used for frequency and 3 for amplitude controller of the VCOs
* Mixer stage for the oscillators - note that two voices are routed to left and right channels, and one is routed to both (ie middle position).
* Audio output (red/white/black wire)
Technical challenges and solutions
This is a pretty complex project. It has taken us a while to get it working. Here are some of the challenges faced, and working solutions.
Audio circuit construction
The audio circuit, using digital potentiometers, did not seem to be working. Either no sound was produced, or else a very limited range of tones. Close inspection of another project showed that the wiring of the oscillator and the digipots has to be done in a very precise manner, or it will not work at all.
Three of the pots on the AD5206 are used to control the frequency of the VCOs (green and yellow braided wires). The output of the VCOs is then taken into the other three pots, to modulate amplitude of the signal (single blue wires).
Here is how it has to be wired in order to work:
Each of the potentiometers on the AD5206 has a ground pin, a wiper pin, and a power pin. The ground pin is connected to ground, the other two connect to each side of one inverter pair on the 74C14. In order for the full tonal range to be realized, the power pin from the AD5206 digipot has to go to the leg of the inverter (VCO) where the capacitor is attached (green wire). The wiper pin from the AD5206 has to go to the other leg of the VCO, from which the output is tapped (yellow wire). If these are reversed, for some reason the VCO will not produce a full range of tones (less than a third of the range). To sum up: wiper to hex inverter output, power to hex inverter input (where the capacitor is).
Then, to connect the amplitude pots, do this: take the output from each of the VCOs (the pin without a capacitor on it) and run it to the power pin of a pot on the AD5206 (blue wire). Take the wiper pin of that pot, and connect it to the output bus (through a resistor).
The output bus is made as follows: take the output of the first oscillator and connect it to the right channel, passing through a 10k ohm resistor. Take the output of the second oscillator, and connect it to *both* the left and right channels, through a 10k ohm resistor on each one. Finally, take the output of the last oscillator and connect it to the left channel via a 10k ohm resistor.
Here's a closeup of the output bus:
You have to wire it exactly as shown. For some reason, I was extremely lucky with my first two projects using this technique, and I got it right by accident...
Getting weather data using PHP
Actually getting the weather data turned out to be relatively straightforward. The National Oceanic and Atmospheric Administration is now publishing XML weather feeds. We started to write a PHP script (running on our server) that would parse this information and return a much more simplified set of data to the rest of the system.
Unfortunately, we found that the Simple XML library (which seemed ideal) requires PHP v5.0 or above, and NYU is running PHP v4.3. We got a good suggestion, which was simply to "scrape" the raw XML feed to extract our numbers.
Fortunately, Lesley used the power of Google to find PXWeather, an extremely simple library designed specifically for retrieving and parsing NOAA weather data!
Using this, it was the work of minutes to write a PHP script that would turn the weather data into a string of numbers. Click here to see typical output. You can change the city name in the URL if you want.
There was a problem: wind direction is returned as a string indicating cardinal direction, not a heading. It turns out that the solution was extremely easy: PHP treats all arrays as lookup tables (key => value) pairs, so it was easy enough to set up an array with all the directions mapped to numbers.
Getting the data into the Arduino
This was quite awkward to debug, since the Arduino is using its serial output to control the Xport, and hence can't be used easily for debugging.
However, it turns out that you can "brute force" a simple debugger by simply connecting to the Arduino to the XPort and to the USB-serial interface at the same time. You can see everything that the Arduino is sending out, and it is easy enough to change the software so that it echoes all incoming data as well.
This technique worked well to get us up and running initially. We were able to connect to the server and ensure that the data was coming in. This gave us some pointers on how to change the PHP script for easier parsing: use a "!" to signal the start of the data, and an "x" to mark the end.
It was straightforward to change the Arduino code so that it reads the weather data into an array of numbers, and when it has all the data, moves it into arrays that are used to control an audio "sequencer".
However, all the debugging data coming from the Arduino in this setup is also going to the XPort, and hence to the webserver, which gets confused and starts putting up all sorts of weird error messages.
Debugging using SoftwareSerial
Fortunately, there is a solution to the Xport debugging issue: the SoftwareSerial library, which allows you to set up an additional serial port on the Arduino using any two digital I/O pins.
At first, I could not get SoftwareSerial to work - nothing seemed to be coming back. It turns out I had made silly mistake: I'd assumed that the digital I/O pins on the Arduino Mini run consecutively from 0 to 9 along the side. However, there are actually two unused pins between 0 & 1, and the rest. Moving the serial connecting cable down two positions, so it was really connecting to pins 2 & 3, fixed everything.
Now we could use the Arduino's builtin serial comms to talk to the XPort on pins 0 and 1, and use pins 2 and 3 for an additional serial port which talks to our computer, for debugging purposes. Here's a picture of everything set up and working:
Where we are now, and what's next
Right now, we can successfully get weather data into the Arduino, and use it to make sound. Next steps are:
* Implement a selector dial to pick different cities
* Tune the mapping of weather data to tunes to make it more musical