« October 2006 | Main | December 2006 »

November 29, 2006

Final project - lamp protocol

I've defined a simple protocol for the lamps to communicate amongst themselves.

All commands start with the letter "L", followed by another letter and a series of parameters. The code for parsing the commands is pretty reliable, I will post it shortly.

Read past the link for a list of the commands.

The commands are:

Light LED: LS(LED number),(Red),(Green),(Blue)

Lights a multicolor LED (LED number) based on RGB values, which run from 0 (dark) to 255 (max bright)

Sensor: LE(Lamp number), (Sensor Number)

Sent by lamp (Lamp number) when the sensor (Sensor Number) is triggered.

Wakeup LW(Lamp number)

Sent by a lamp when it powers up. Used by the other lamps to maintain a list of which other lamps are active.

Timeout LT(Lamp number)

Sent by a lamp when it has received no local input for the time out period. When each lamp has received a timeout message from all other lamps, it goes into the timeout routine.

I am thinking of adding a heartbeat command, that allows the lamps to keep track of which other lamps are active, and a variant of the LS command that takes a specific lamp number. Right now LS will set all lamps to the same configuration. Also might add a debug command. The commands would look like this:

LB (Lamp number)

Sent every few seconds to indicate that a lamp is awake, or in response to receiving an LW message. (This allows a recently switched on lamp to build an inventory of other active lamps)

LI(Lamp number), (LED number), (Red), (Green), (Blue)

Like the LS command, but with a specific lamp number at the beginning. Maybe define a wildcard value for , in which case this command replaces LS.

LD(Lamp number)

This will trigger a debug output from the lamp specified, maybe current value of LEDs, timeout state, internal count of other active lamps.

Final Project - debugging wireless

Spent a frustrating evening trying to get the Zigbee radios to work.

Update: There is a further solution to the problems described in this article. Basically, always send a "wakeup" character to the Zigbee before doing anything else, and set the guard time before a "+++" command to 1100 msec, not 1000.

The problem:

On one of my prototype boards, the Zigbee radio did not seem to be receiving commands from the Arduino, so it wasn't getting the right network ID, or setting itself to transmit in broadcast mode.

I programmed the Zigbee on my "modem" board, which connects it directly to a USB adapter, but nothing doing. It was clearly receiving via wireless, and ouputing the received signal to the Arduino, which changed the display, but nothing coming back the other way.

I spent several hours trying different things, including an incorrectly connected 12V power supply which killed one of the AD5206 digital pots, and nearly killed an Arduino mini.

I had made a mistake, in that I had not set the Zigbees correctly to multicast by using the PAN ID FFFF. I had used FF instead. However, that did not fix everything - one Zigbee still did not work.

What turned out to be problem? One of the Zigbees is defective, probably as a result of bad soldering by myself. It works fine as a "modem", but simply refuses to accept input from the Arduino mini. Two other Zigbee radios are working fine.

I uploaded the receive protocol software to two of the working prototype boards, and tried sending various lighting commands to them, which worked fine.

Of course, now I am behind: I still need to port over the sensor code & the state machine from the midterm, and physically assemble the lamps.

November 28, 2006

First try with Flash

Argh. What a frustrating environment Macromedia Flash is! It has no conventions in common with video editing or page design. I feel like I am poking around blindly in the dark.

Anyway, my first try at something is here:

http://itp.nyu.edu/~gpv206/comm-lab/CommLab1.html

November 27, 2006

Quest for Pastrami

Here is my long-delayed video assignment for Comm Lab, I made it with Jack Aboutboul and it is called "Quest for Pastrami".

Find it here: http://villamil.org/movies/pastrami.mov

It was all shot in my neighborhood, features the now-defunct Second Ave. Deli and Katz Deli, and of course, a pastrami sandwich.

The story is simple: searching for a pastrami sandwich on the Lower East Side. The Second Ave. Deli is now closed, so we have to go down to Katz Deli on Houston St., passing a variety of different ethnic restaurants and food shops on the way.

The music is mostly from the Klezmatics and the Amsterdam Klezmer band, and contributes pretty much all of the emotional impact of the piece.

I shot in HDV with a Sony A1J and used an Audio-Technica 835ST mike. Edit in Vegas Video 7.0, which now works *very* well with HDV, practically realtime. I only added a slight S-shaped color curve, in addition to the Cinegamma that the camera applies.

There were only two of us - no additional camera person. Given that constraint, it looks OK.

November 17, 2006

Final Project - Working with AD5206 digital pots - for the code junkies

For anyone interested in working with the AD5206 DAC, follow the link for my code that controls 4 multicolor LEDs using two AD5206 chips.

The write_LED routine is particularly handy. It is for controlling multicolor LEDs by specifying red, blue & green values. It is designed to work with multiple AD5206s chained together, and will figure out which set of pins on which DAC are assigned to a given LED.

It divides the LED number by the number of LEDs per chip to get the chip number, then uses a small lookup table to map the red, green & blue pins of the LED to the output pins on the DAC.

I use Heather's spi_transfer routine, and all her setup code.

Follow the link for the code...

/*

Multicolor LED driver using AD5206

This program drives 4 multicolor LEDS using the AD5206 digital pot

Gian Pablo Villamil
November 17, 2006

Based on SPI code by Heather Dewey-Hagborg

*/

#define DATAOUT 11//MOSI
#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK 13//sck
#define SLAVESELECT 9//ss

#define POTS_PER_DAC 6
#define LEDS_PER_DAC 2
#define NUM_DACS 2
#define NUM_LEDS 4

byte pot=0;
byte resistance=0;

// map pins to LEDs
// first column is LED selector (0 or 1)
// second column is color selector (Red = 0, Blue = 1, Green = 2)
// refer to http://public.fotki.com/gpvillamil/new_york/itp_classwork/phys_comp/ad5206-pinout-for-final.html

byte pinMap[2][3] = {
{
5,3,1 }
,{
4,0,2 }
};

char spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1< {
};
return SPDR; // return the received byte
}

void setup()
{

Serial.begin(9600);
byte i;
byte clr;
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
for (int i = 0; i < NUM_DACS; i++) {
pinMode(SLAVESELECT+i,OUTPUT);
digitalWrite(SLAVESELECT+i,HIGH); //disable device
}
// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 (fastest)
SPCR = (1< clr=SPSR;
clr=SPDR;
delay(10);
for (i=0;i<6;i++)
{
write_pot(i,255);
}
}

byte write_pot(byte address, byte value)
{
byte chipNum = address / POTS_PER_DAC ;
byte chipAddress = address % POTS_PER_DAC ;
digitalWrite(SLAVESELECT+chipNum,LOW);

//2 byte opcode
spi_transfer(chipAddress);
spi_transfer(value);
digitalWrite(SLAVESELECT+chipNum,HIGH); //release chip, signal end transfer

}

// Light a 3 color LED
// Takes an LED number, and values for RGB
// Routine will calculate the number of the correct DAC
// and look up the pin number using the pinMap array previously defined.

void write_LED(byte LEDnumber, byte redValue, byte blueValue, byte greenValue)
{
byte chipAddress ;
byte chipNum = LEDnumber / LEDS_PER_DAC ;
byte chipLED = LEDnumber % LEDS_PER_DAC ;

digitalWrite(SLAVESELECT+chipNum,LOW); // activate the selected chip

// set the red value

chipAddress = pinMap[chipLED][0];
spi_transfer(chipAddress);
spi_transfer(redValue);

digitalWrite(SLAVESELECT+chipNum,HIGH); //release chip, signal end transfer
digitalWrite(SLAVESELECT+chipNum,LOW); // activate the selected chip


// set the blue value

chipAddress = pinMap[chipLED][1];
spi_transfer(chipAddress);
spi_transfer(blueValue);

digitalWrite(SLAVESELECT+chipNum,HIGH); //release chip, signal end transfer
digitalWrite(SLAVESELECT+chipNum,LOW); // activate the selected chip

// set the green value

chipAddress = pinMap[chipLED][2];
spi_transfer(chipAddress);
spi_transfer(greenValue);

digitalWrite(SLAVESELECT+chipNum,HIGH); //release chip, signal end transfer

}

void loop () {
for (int i = 0; i < NUM_LEDS; i++) {
write_LED(i,1,0,0); // make white
delay(100);
write_LED(i,255,255,255); // turn off
}
}

Final Project - Working with AD5206 digital pots

Today I finished wiring the first of two prototype boards, and started testing code to work with the AD5206 digital potentiometer. This is a chip that takes serial input on two wires, and uses it to set a variable voltage on up to 6 output pins. You can chain them together, using an additional line to select the chip you want to address.

I am using two of these in each lamp. This lets me control 12 variable outputs using only 4 lines on the Arduino (clock, serial data, select chip 1, select chip 2).

Fortunately, Heather (another ITP student) has written a tutorial on working with the AD5206. Very helpful.

Here are the AD5206s in all their glory:

Read past the link for some weirdness and lessons learned...

I was able to run her example directly, and easily extend it to more than one AD5206. However, when I started writing code to handle multicolor LEDs, I experienced some odd problems. To achieve different color combinations, you have to provide voltage on several pots at once (something that Heather's example does not do).

The multicolor LEDs are connected to the AD5206 using the following scheme. Note that the pots are actually numbered 0-5 when programming, not 1-6. This caused a minor headache.



When I first tested this scheme, something strange happened: applying maximum voltage to the lines controlling the red element on the LEDs would turn off the blue and green element. Slightly reducing the voltage to the red element would allow it to light together with the blue & green.

I suspect that maybe the red element draws more current than the blue or green channel of the LED and that setting it to max power overrides the other digital pots.

I will try with a higher current external supply, and see what happens.

I also learned something about SPI (Serial Peripheral Interface), the protocol used to communicate between the Arduino and the AD5206. Basically, the AD5206 is enabled for writing by pulling the CS pin low. When the CS pin is set high again, the AD5206 acts on the command received. I thought that you could bring CS low, write a series of commands, and then all the commands would be executed when CS went high. In fact, you need to do the CS low, write, CS high cycle for every single command.

Finally, a brief note on the prototype board layout:



Basically, the long board to the lower left is the lamp controller as it will go into the project. The topmost board will be replaced by the physical structure of the lamp.

The little board to the right is interesting, it is the "programming module". The Arduino Mini, which I am using, does not have a built-in USB port, or a reset button. So I have placed those components on a small breadboard, which will allow me to move it from lamp to lamp for programming.

Order and clarity

At my age, memory is not what it used to be, so I find it helpful to help it out with copious documentation.

One thing I have found helpful is to make and print little cards with pinouts of all the pieces that I am using. I have put them online here: http://www.villamil.org/images/pcomp-pinouts/

Please feel free to use them. Right now is mostly documentation for Arduino mini, Xbee radio, and AD5206 digital pot.

I also make little cheat-sheets for different parts of my projects. For example, here is how I will connect multicolor LEDs to the AD5206 digital pot in my final project:

It saves a lot of time, and is less distracting than keeping laptop open to look for datasheets all the time.

November 16, 2006

Final project - description & plans

I've decided to go ahead with the cluster of lamps idea for my final project.

Basically, it is four lamps capable of responding to gestures, connected wirelessly so that their response is synchronized. This is an evolution of the midterm project, which involved a single lamp. I was quite intrigued by the fluidity of the gesture control system, and wanted to do more with it.

Since the radios are quite powerful, it is possible for the lamps to be quite far away from each other. This has a practical impact: they can be used as a communications device, by interacting with a lamp you can send a message to someone next to a distant lamp. I also like the reference to the quantum physics concept of "action at a distance", where in some way the lamps are "entangled" and always in sync.

Since the lamps will be able to respond to any commands coming in over the Xbee radios, it should also be straightforward to write a program on the laptop that will talk to them and help them do more complicated things.

Keep reading for further information on implementation.

I am using a number of components which are all new to me:

1) Arduino Mini
2) multicolor (RBG) LEDs
3) AD5206 Digital Potentiometer
4) XBee radios (802.15.4)

The project is divided into a number of components:

a) Gesture recognition (taken from midterm)
b) Display routine
c) Wireless synchronization
d) Physical assembly

At this point, I think that b) will be the most fun, c) will take the most intellectual effort, and d) will take the most time.

I've already spent quite a bit of time assembling the radios, which all seem to work quite well (thanks Rob!), I have also experimented with the Arduino Mini and with the multicolor LEDs. Now the fun begins - assembly!

My plan is to assemble two of the control boards, each with an Arduino mini, an Xbee, and two 5206s. These are basically the control boards for the lamps. Next to them, I will make breadboards with all the lamps and sensors, as stand-ins for the final physical assembly.

I should be able to do most of my gesture, display and wireless coding with just these two boards, while in parallel researching the physical assembly.

November 10, 2006

MIDI lab - a MIDI Theremin

I built a simple MIDI "theremin", using an ultrasonic rangefinder.


I had an initial false start, when I soldered the leads on the MIDI connector incorrectly.Once resolved, everything worked fine. Click here for a picture of the MIDI connector.

The picture also shows a multi-colored LED, which I am testing for another project.

Keep reading past the link for the code for the MIDI theremin.

/*
Ultra-basic MIDI theremin, using a MaxBotix rangefinder

Reads an analog sensor and uses value to generate a MIDI note.

*/

// Constants

#define rangeFinderPin 0
#define sensorMin 10
#define sensorMax 120
#define sensorTrigger 127
#define midiMin 40
#define midiMax 120
#define midiDuration 100

// Variables

int rangeFinderValue = 0;
int note = 0;

void setup() {
Serial.begin(31250);
}

void loop() {
rangeFinderValue = analogRead(rangeFinderPin);
if (rangeFinderValue > sensorMin && rangeFinderValue < sensorTrigger) {
delay(midiDuration); // this delay is to crop out the high transition
rangeFinderValue = analogRead(rangeFinderPin); // re-read
note = scale(rangeFinderValue, sensorMin, sensorMax, midiMin, midiMax);
noteOn(0x90, note, 127);
delay(midiDuration);
//Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
noteOn(0x90, note, 0x00);
// delay(midiDuration);
}

}

int scale(int inputValue, int inputMin, int inputMax, int outputMin, int outputMax) {
long temp = (outputMax-outputMin)*(inputValue-inputMin);
return constrain(temp/(inputMax-inputMin)+outputMin,outputMin,outputMax);
}

// plays a MIDI note. Doesn't check to see that
// cmd is greater than 127, or that data values are less than 127:
void noteOn(char cmd, char data1, char data2) {
Serial.print(cmd, BYTE);
Serial.print(data1, BYTE);
Serial.print(data2, BYTE);
}

Getting started with Arduino Mini

Just received my order of Arduino Minis for my final project.

I've written up some quick installation tips. Below is a picture of the Mini together with the Mini USB adapter (on the left).

A couple of notes:

* The yellow and blue cables going off to the right are connected to an XBee radio module.

* Note the 10K resistor connecting the reset pin to +5V volt. This is to keep the reset pin high, until the reset button is pushed. The reset button is visible on the right, it is connected to the reset pin via a blue lead which is under the Arduino mini board, to save space.

* I have connected a red LED to pin 13, this pin is flashed by the bootloader whenever the Arduino is reset, and acts like a simple health check.

Here is a detailed shot of the reset button, showing the wire to the reset pin routed under the Arduino Mini board.