Main

September 18, 2007

FIRST ASSIGNMENT

FIND & FIX

The first assignment was to find something on the floor and whether fix it or improve it. Everything i found that needed to be fixed, was rather trivial and dint need much electronics at all, including the dirty microwave, need for paint and toilet paper.

So i came up with a not-to-clever idea to remind people to wear their goggles before entering the shop. Since everyone seems to forget them...

shop.jpg

MATERIALS USED

* Arduino
* Ultrasonic Range Finder
* Superbright LED

INTERACTION

You get close to the door and the alarm goes off, then as you get closer a robotic voice reminds you of your goggles and as you get even closer an LED sign blinks repeatedly.

September 20, 2007

GETTING STARTED

GLOW THAT LED

I managed to power the radio up! Assignment coming soon.

zigbee1.jpg

zigbee2.jpg

September 26, 2007

101ST ENTRY... LED GLOWING!

ZIGBEE PROGRESS>

Grant it was 5,30am when i finally decided to stop playing with the Zigbees, but still, i struggled so much with the processing code giving me an error message, the arduino 10000 needing Adruino009 or it won't run and the adressing to be done in Zterm since the processing terminal wasn't an option...
but i am, thanks to Rob Faludi's incredible patience, a lot further than before.

The problems that seem to persist are: 9v battery plug (need to get), the fact that when the power sources change from let's say usb to battery, the arduino diecimila seems to forget the code. They are still acting weird, hope to fix that soon.

Here is testimony of my progress:

board1.jpg

Board number 1, Zigbee ID 1000, PANID 0911, DH 0 with IR sensor.

board2.jpg

Board numer 2, Zigbee ID 2000, PANID 0911, DH 0 with Potentiometer.

October 11, 2007

ROCK, PAPER, SCISSORS

IT HAS BEEN A LONG HARD ROAD...

RPS.jpg

Still trying to get the code to work... But i am considering changing route.

//-----------abs values for rock paper scissors
#define rock 2
#define paper 0
#define scissors 1

int inByte= -1; // incoming byte from serial RX

int switchPin1 = 12; // digital input pin for a switch
int switchPin2 = 11;
int switchPin3 = 10;

int yellowLed = 3; // digital output pin for an LED
int redLed = 2;
int greenLed = 9;

int switchState1 = 0; // the state of the switch
int switchState2 = 0; // the state of the switch
int switchState3 = 0; // the state of the switch

int Loc = 0;
int Rem = 0;

int winner = 0;


//________________________________________

void setup() {
//-----------configure serial communications:
Serial.begin (9600);
pinMode(switchPin1, INPUT); // set the switch pin to be an input
pinMode(switchPin2, INPUT); //
pinMode(switchPin3, INPUT); //
pinMode(yellowLed, OUTPUT); // set the yellow LED pin to be an output
pinMode(redLed, OUTPUT); //
pinMode(greenLed, OUTPUT); //

//-----------set XBee's destination address:
setDestination();
//-----------blink the TX LED indicating that the main program's
//about to start:
}

//________________________________________
void setDestination() {
// put the radio in command mode:
Serial.print("+++");
// wait for the radio to respond with "OK\r"
char thisByte = 0;
while (thisByte != '\r') {
if (Serial.available() > 0) {
thisByte = Serial.read();
}
}

// set the destination address, using 16-bit addressing.
// if you're using two radios, one radio's destination
// should be the other radio's MY address, and vice versa:
Serial.print("ATDH0, DL1000\r");
// set my address using 16-bit addressing:
Serial.print("ATMY2000\r");
// set the PAN ID. If you're working in a place where many people
// are using XBees, you should set your own PAN ID distinct
// from other projects.
Serial.print("ATID0911\r");
// put the radio in data mode:
Serial.print("ATCN\r");
}

//________________________________________
void loop() {

//if (Serial.available() > 0) {
readSwitch();
handleEval();
winnerLights();
}

void readSwitch() {

switchState1 = digitalRead(switchPin1);
switchState2 = digitalRead(switchPin2);
switchState3 = digitalRead(switchPin3);

if (switchState1 == 1) {
// if the switch is closed:
digitalWrite(greenLed, HIGH); // turn on the green LED
Serial.print(rock, DEC);
Serial.print("\r");

}
else {
// if the switch is open:
digitalWrite(greenLed, LOW); // turn off the green LED

}
if (switchState2 == 1) {
// if the switch is closed:
digitalWrite(redLed, HIGH); // turn on the red LED
Serial.print (paper, DEC);
Serial.print("\r");

}
else {
// if the switch is open:
digitalWrite(redLed, LOW); // turn off the red LED

}
if (switchState3 == 1) {
// if the switch is closed:
digitalWrite(yellowLed, HIGH); // turn on the yellow LED
Serial.print(scissors, DEC);
Serial.print("\r");

}
else {
// if the switch is open:
digitalWrite(yellowLed, LOW); // turn off the yellow LED

}

}

void handleEval () {

Rem = Serial.read();
//Serial.println(Rem, BYTE);

if (Loc == Rem) {
winner = 0;
}
else if (Loc == rock && Rem == paper) {
winner = 2;
}
else if (Loc == rock && Rem == scissors) {
winner = 1;
}
else if (Loc == paper && Rem == rock) {
winner = 1;
}
else if (Loc == paper && Rem == scissors) {
winner = 2;
}
else if (Loc == scissors && Rem == rock) {
winner = 2;
}
else if (Loc == scissors && Rem == paper) {
winner = 1;
}

}
void winnerLights () {

if (winner == 1) {

digitalWrite(yellowLed, HIGH);
digitalWrite(redLed, HIGH);
digitalWrite(greenLed, HIGH);

delay (200);

digitalWrite(yellowLed, LOW);
digitalWrite(redLed, LOW);
digitalWrite(greenLed, LOW);
}
}

October 17, 2007

ROCK, PAPER, SCISSORS FINAL

Sometimes you have to lose some to gain some... I decided to rethink our Rock Paper Scissors method and go for the random seed while keeping the feeling of playing a game, by leaving the push button for each player and the boards look like this:

RPSfinal.jpg

And if played, the tricolor LEDs would select one of the three possibilities and display them, while a yellow LED blinks to announce the winner.

playRPS.jpg


MIDTERM CONCEPT SKETCH

MIDTERM APPROACHING...

Group: Eric, Benny, Raphael, Rory.

Title: "Collaborative Music" (temporary title)

Description: Our group has decided to work on creating wearable music devices that would each separately make a simple electronic tune when unable to detect other members of the same network. They would instead play different and more articulate tunes once able to communicate with other devices present on the floor. Each device will employ a Mini Arduino, a Zigbee Radio, some other components like LEDs and a speaker, in order to be self contained units (possibly enclosed in belt buckle or other wearable elements that could be implemented in already designed clothing).

This is a preliminary sketch of what our midterm idea is and the directions it could take:

midtermsketchcmn.jpg


October 23, 2007

MIDTERM PROGRESS

Our initial plan was to combine in self contained units, a mini arduino, a zigbee and a speaker in order to broadcast each other's presence through music. The idea was to play a simple tune while noone was around or when only one radio was on the floor but as more people in our group appeared on the floor it would play a more complex tune.

We first wrote the arduino program that would check for the presence of the other radios, since their program would broadcast a 1, 2, 3, or 4 when turned on. We soon ran into some technical difficulties of running the part of the program that played notes at the same time as the broadcasting, in fact it seemed as though the delays present and necessary to play the notes on the arduino PWM pin, would actually stall and block anything else from happening.

We then decided to use a digital pot AD5206 to control an oscillator chip to actually produce the notes. That seemed to work, but ones interfaced with the Zigbee wasn't working properly and it still needed an amp of some sort, therefore making the idea of a wearable completely impossible.

musicchip.jpg

We then decided after investing a lot of time into this option, to opt for a base central station hooked up to a computer running a patch in Max MSP that would listen to the serial and expect 5 bytes, 4 of which represented the presence (1 or 49) or absence (0 or 48) from the Arduino base station. It then used each ON radio to trigger a different instrument.

4zig.jpg4zig1.jpg

Close up of one of the small now wearable radio circuits.

4zigcloseup.jpg

And a cute casing for it.

sawing.jpg

October 24, 2007

MAX PATCHES FOR MIDTERM

Here is the first patch that Raphael and I worked on, which attributes one different instrument to each radio coming into the range of the base station:

patch1.png

And this is the patch that Eric worked on that adds a little excitement to our demonstration and works off of Rob's radio metronome:

patch2.png

Code for the Base station here:

//Rory Nugent, Raphael Zollinger, Eric Beug, Benedetta Piantella Simeonidis
//Collaborative Mesh Networking

#define timecodeLED 13
#define receiveLED 12

#define nodeOneLED 8
#define nodeTwoLED 7
#define nodeThreeLED 6
#define nodeFourLED 5

byte availByte = B10000;
boolean oneAvailable = false;
boolean twoAvailable = false;
boolean threeAvailable = false;
boolean fourAvailable = false;

unsigned long lastOneAvailable = 0;
unsigned long lastTwoAvailable = 0;
unsigned long lastThreeAvailable = 0;
unsigned long lastFourAvailable = 0;

const unsigned long nodeTimeout = 5000;

unsigned long lastReceive = 0;
unsigned long lastBroadcast = 0;
const unsigned long freqBroadcast = 1000;

int beat = 0; // used to store the current beat number
unsigned long timeCode = 0; // used to store the current time code value

byte inByte = 0;

void setup()
{
pinMode(timecodeLED,OUTPUT);
pinMode(receiveLED,OUTPUT);
pinMode(nodeOneLED,OUTPUT);
pinMode(nodeTwoLED,OUTPUT);
pinMode(nodeThreeLED,OUTPUT);
pinMode(nodeFourLED,OUTPUT);

digitalWrite(nodeOneLED,LOW);
digitalWrite(nodeTwoLED,LOW);
digitalWrite(nodeThreeLED,LOW);
digitalWrite(nodeFourLED,LOW);

Serial.begin(9600);
setupXBee();
Serial.flush();
blinkLED(receiveLED,2,250);
}

void loop()
{
checkforBroadcast();
checkNodeTime();
setAvailByte();
}

void setAvailByte()
{
availByte = B10000;

if(fourAvailable)
{
availByte = availByte + (B1 << 3);
}
if(threeAvailable)
{
availByte = availByte + (B1 << 2);
}
if(twoAvailable)
{
availByte = availByte + (B1 << 1);
}
if(oneAvailable)
{
availByte = availByte + B1;
}
}

void checkforBroadcast()
{
if(Serial.available() > 2)
{
inByte = Serial.read();
if(inByte == '#')
{
inByte = Serial.read();
if(inByte == '1')
{
lastOneAvailable = millis();
digitalWrite(nodeOneLED,HIGH);
oneAvailable = true;
blinkLED(receiveLED,1,20);
}
else if(inByte == '2')
{
lastTwoAvailable = millis();
digitalWrite(nodeTwoLED,HIGH);
twoAvailable = true;
blinkLED(receiveLED,1,20);
}
else if(inByte == '3')
{
lastThreeAvailable = millis();
digitalWrite(nodeThreeLED,HIGH);
threeAvailable = true;
blinkLED(receiveLED,1,20);
}
else if(inByte == '4')
{
lastFourAvailable = millis();
digitalWrite(nodeFourLED,HIGH);
fourAvailable = true;
blinkLED(receiveLED,1,20);
}
}
else if(inByte == '*')
{
blinkLED(timecodeLED,1,20);
Serial.print('$');
Serial.print(availByte,BIN); //outputs availability status to Max, format can be changed accordingly
}
}
}

void checkNodeTime()
{
if((millis() - lastOneAvailable > nodeTimeout) && oneAvailable == true)
{
digitalWrite(nodeOneLED,LOW);
oneAvailable = false;
}
else if((millis() - lastTwoAvailable > nodeTimeout) && twoAvailable == true)
{
digitalWrite(nodeTwoLED,LOW);
twoAvailable = false;
}
else if((millis() - lastThreeAvailable > nodeTimeout) && threeAvailable == true)
{
digitalWrite(nodeThreeLED,LOW);
threeAvailable = false;
}
else if((millis() - lastFourAvailable > nodeTimeout) && fourAvailable == true)
{
digitalWrite(nodeFourLED,LOW);
fourAvailable = false;
}
}

// this function blinks andddd LED light as many times as requested
void blinkLED(int targetPin, int numBlinks, int blinkRate) {
for (int i=0; i digitalWrite(targetPin, HIGH); // sets the LED on
delay(blinkRate); // waits for a blinkRate milliseconds
digitalWrite(targetPin, LOW); // sets the LED off
delay(blinkRate);
}
}

///////////////////////////////// UTILITY FUNCTIONS //////////////////////////////////////////
// this function checks for a specific response on the serial port
// it accepts a string to look for and a timeout in milliseconds
int checkFor(char* desiredResponse, int timeout) {
int result = 0;
int length = 40;
char incomingResponse[41];
memset(incomingResponse,0,length); // initialize all incomingResponse string positions to null
char inByte = NULL;
long startTime = millis();//makes the start time = to now
char* ptr_incomingResponse = incomingResponse;
// while we haven't timed out or gotten back the string that we are looking for
while (millis() - startTime < timeout && strstr(incomingResponse,desiredResponse) == NULL ) { //strstr compares strings
if (Serial.available() > 0) { // if there are any bytes waiting to be read
inByte = Serial.read(); // read one byte
if (incomingResponse > ptr_incomingResponse-length) { // if we haven't read in 80 characters yet
*ptr_incomingResponse = inByte; // put the byte into the current position in the string
ptr_incomingResponse++; // advance to the next position in the string
}
else {
//move the last char to be next to last, and so forth until we reach the end of the array.
for (int i = 0; i < length; i++) {
incomingResponse[i] = incomingResponse[i+1];
}
incomingResponse[length-1] = inByte; // put the byte into the current position in the string
}
}
}
if (strstr(incomingResponse,desiredResponse) != NULL ) { // if the desired string is found
result = 1;
}
else {
result = 0;
}
return result;
}

void setupXBee() {
boolean success = false;
int ctr = 0;
while (success == false && ctr < 100) {
// blink the status LED
blinkLED(receiveLED, 2, 250);
// an arbitrary byte to wake up the XBee
//Serial.print("X");
//delay(1100);
// put the XBee in command mode
Serial.print("+++");
delay(1100);
// wait for a response from the XBee for 2000 ms, or start
// over with setup if no valid response comes
// set the PAN (personal area network) ID number
// set the MY (16 bit address)
// set the Destination High to 0x0
// set the Destination Low (16 bit address)
// exit command mode (using a Serial.printLN to end the command with a linefeed)
Serial.println("ATRE,ID333A,MYBEEF,DH0,DLBEEF,CN");
if (checkFor("OK", 1000)) {
// if an OK was received then continue
success = true;
}
else {
success = false;
}
ctr++;
}
}

Code for the 4 Nodes here:

//Rory Nugent, Raphael Zollinger, Eric Beug, Benedetta Piantella Simeonidis
//Collaborative Mesh Networking

#define broadcastLED 13

unsigned long lastBroadcast = 0;
const unsigned long freqBroadcast = 1000;

const char* broadcastID = "#1"; //change depending on the number of the node

byte inByte = 0;

void setup()
{
pinMode(broadcastLED,OUTPUT);

Serial.begin(9600);
setupXBee();
Serial.flush();
blinkLED(broadcastLED,2,250);
}

void loop()
{
broadcast();
}

void broadcast()
{
if(millis() - lastBroadcast > freqBroadcast)
{
blinkLED(broadcastLED,1,20);
Serial.print(broadcastID);
lastBroadcast = millis();
}
}

// this function blinks the an LED light as many times as requested
void blinkLED(int targetPin, int numBlinks, int blinkRate) {
for (int i=0; i digitalWrite(targetPin, HIGH); // sets the LED on
delay(blinkRate); // waits for a blinkRate milliseconds
digitalWrite(targetPin, LOW); // sets the LED off
delay(blinkRate);
}
}

///////////////////////////////// UTILITY FUNCTIONS //////////////////////////////////////////
// this function checks for a specific response on the serial port
// it accepts a string to look for and a timeout in milliseconds
int checkFor(char* desiredResponse, int timeout) {
int result = 0;
int length = 40;
char incomingResponse[41];
memset(incomingResponse,0,length); // initialize all incomingResponse string positions to null
char inByte = NULL;
long startTime = millis();//makes the start time = to now
char* ptr_incomingResponse = incomingResponse;
// while we haven't timed out or gotten back the string that we are looking for
while (millis() - startTime < timeout && strstr(incomingResponse,desiredResponse) == NULL ) { //strstr compares strings
if (Serial.available() > 0) { // if there are any bytes waiting to be read
inByte = Serial.read(); // read one byte
if (incomingResponse > ptr_incomingResponse-length) { // if we haven't read in 80 characters yet
*ptr_incomingResponse = inByte; // put the byte into the current position in the string
ptr_incomingResponse++; // advance to the next position in the string
}
else {
//move the last char to be next to last, and so forth until we reach the end of the array.
for (int i = 0; i < length; i++) {
incomingResponse[i] = incomingResponse[i+1];
}
incomingResponse[length-1] = inByte; // put the byte into the current position in the string
}
}
}
if (strstr(incomingResponse,desiredResponse) != NULL ) { // if the desired string is found
result = 1;
}
else {
result = 0;
}
return result;
}

void setupXBee() {
boolean success = false;
int ctr = 0;
while (success == false && ctr < 100) {
// blink the status LED
blinkLED(broadcastLED, 2, 250);
// an arbitrary byte to wake up the XBee
//Serial.print("X");
//delay(1100);
// put the XBee in command mode
Serial.print("+++");
delay(1100);
// wait for a response from the XBee for 2000 ms, or start
// over with setup if no valid response comes
// set the PAN (personal area network) ID number
// set the MY (16 bit address)
// set the Destination High to 0x0
// set the Destination Low (16 bit address)
// exit command mode (using a Serial.printLN to end the command with a linefeed)
Serial.println("ATRE,ID333A,MYBEEF,DH0,DLBEEF,CN");
if (checkFor("OK", 1000)) {
// if an OK was received then continue
success = true;
}
else {
success = false;
}
ctr++;
}
}

December 12, 2007

FINAL: TOOL FOR PERFORMANCE

PERFORMANCE TOOL

One thing i remember from dancing and performing live is that there is no real and concrete way of predicting how long a performance is going to take. Things can go wrong during a live performance, things can happen that were not anticipated, and more than anything due to the adrenaline and excitement of performing live I remember always accelerating the movements much more than during rehearsals. Therefore unless you have someone that can control the video, audio and lighting for you that can adapt the environment to the speed of the performance, things can go awfully wrong.

My idea was to create a performance tool that took advantage of the acceleration of my body as a mean to navigate through all the media involved in the performance.

I decided to make a couple of versions, one that uses bluetooth for short distances, and one that takes advantage of the Zigbee radios bandwidth as a way to reach further.

Here is the base station:

zigbee-device1.jpg

And here is the wearable device, not yet in wearable format, but soon enough...

zigbee-device2.jpg

This is the radios set up to send the analog readings of the 3 axis of the accelerometer:

SENDING ZIGBEE

ATMY1000
ATDL2000
ATID911
ATD02
ATD12
ATD22
ATIR3E8 (1000 ms)
ATIT1

------------------------------

RECEIVING ZIGBEE

ATMY2000
ATDL1000
ATP02
ATIU1
ATIA1000 (or ATIA911)

--------------------------------

And here is the Max MSP patch that takes in the 3 axis readings, bit shifts the ones that need to be 'reassembled' and then computes the total acceleration and uses that to detect certain events and can trigger audio, video or manipulate both. Click on the images below to see an enlarged view:

patch1-zigbees.jpg

And here is the other half:

patch2-zigbees.png