Making Things Interactive

May 12, 2008

BOOMBOXES

Filed under: Assignments,Final Project,Jesse Chorng,Paul Castellana — paulcastellana @ 2:44 pm

Boomboxes is an environment designed to promote social interaction through music. It consists of a stationary hub, and five wireless modular seating units that can be moved and stacked to best fit the given social situation. Users can connect their mp3 players to an input jack in the hub to play music through all of the modular units. Each unit has a radio, RBG and white lights, a seat button that detects when someone is sitting down, and all are networked together using Xbee radio transmitters. Although a faulty seat button caused malfunctioning during the final presentation, the particular program we’re providing code for here changes the lighting of the boxes based on the number of people sitting down, so that when music is playing and the boxes are activated, the lights are white until all five boxes are in use, at which point each box lights a different color. If at this point, everyone stands up within 15 seconds of each other the colored lights dances to the music.

Project Website which is currently under construction. For now, check it out here

Here’s our proposal: Boomboxes Proposal

Part’s List: Boomboxes Parts List

Code:

/*
Boomboxes - Social Interaction Through Music
Small Undergraduate Research Grant

Paul Castellana
Jesse Chorng

*/

//----------- STATES ------------//
const int sWaiting = 0;          // The system is waiting for audio to be plugged in. Speakers/Lights are off
const int sActivate = 1;         // The system detects audio being played. Speakers/Lights are on
const int sAttract = 2;          // The system detects motion and inactive; lights turn to attract attention
const int sStandby = 3;          // If everyone sitting and someone stands up, wait 30 secs to see if everyone stands up
const int sParty = 4;            // If there's enough people around and people are moving, party time! Lights dance to music

int currentState = sWaiting;
int nextState = sActivate;

//----------- INPUTS ------------//
int audioIn = 1;                 // Audio signal in from stereo jack
int activateSwitch = 9;          // Switch to activate Boomboxes
int pirSensor = 8;               // PIR Motion swich, sends LOW when motion detected

int seat1 = 6;                   // Input Pin for Seat 1
int seat2 = 5;                   // Input Pin for Seat 2
int seat3 = 4;                   // Input Pin for Seat 3
int seat4 = 3;                   // Input Pin for Seat 4
int seat5 = 2;                   // Input Pin for Seat 5

//----------- OUTPUTS -----------//
int recModuleSwitch = 10;        // Seat switch to know when someone is sitting
int radioSwitch = 7;             // Activates radios in seats
int rgbLed = 12;                 // RGB LED
int whiteLed = 11;               // White LED

//---------- VARIABLES ----------//
int motionCount = 0;             // PIR Motion Count
int allSitting = 0;              // All sitting true (1) or false (0)
int allStanding = 0;             // All standing true (1) or false (0)
int audioVal;

//--------------------------- SETUP ---------------------------//
void setup()  {

    pinMode(audioIn, INPUT);
    pinMode(activateSwitch, INPUT);
    pinMode(pirSensor, INPUT);
    pinMode(seat1, INPUT);
    pinMode(seat2, INPUT);
    pinMode(seat3, INPUT);
    pinMode(seat4, INPUT);
    pinMode(seat5, INPUT);

    pinMode(recModuleSwitch, OUTPUT);
    pinMode(radioSwitch, OUTPUT);
    pinMode(rgbLed, OUTPUT);
    pinMode(whiteLed, OUTPUT);

    Serial.begin(9600);
}

//---------------------------- LOOP -----------------------------//
void loop()  {

  switch(currentState) {
       case sWaiting:                                            // Waiting to either activate or attract people
           Serial.println("Waiting");

           digitalWrite(radioSwitch, LOW);                       // Radios are off
           digitalWrite(recModuleSwitch, LOW);                   // Don't play "Boomboxes" sample
           digitalWrite(whiteLed, LOW);                          // No LED action
           digitalWrite(rgbLed, LOW);                            // No color LED action

           if (digitalRead(activateSwitch) == HIGH) {            // Check switch to activate
               currentState = sActivate;
           }

           motionCheck();                                        // Check for motion from PIR sensor
           if(motionCount > 30) {                                // If there's enough motion, go into Attract state
             currentState = sAttract;
           }
           break;

       case sAttract:
           Serial.println("Attract");

           digitalWrite(radioSwitch, HIGH);
           digitalWrite(recModuleSwitch, HIGH);
           digitalWrite(whiteLed, LOW);

           motionCount = 0;

           for(int h=0; h < 10; h++) {                            // When in attract mode, flash lights for 15 secs
             digitalWrite(rgbLed, HIGH);
             delay(500);
             digitalWrite(rgbLed, LOW);
             delay(500);
           }

           if(digitalRead(activateSwitch) == HIGH) {
             currentState =sActivate;
           } else {
             currentState = sWaiting;
           }

           break;

       case sActivate:                                            // Activated mode is simply white LEDs on
           Serial.println("Activated"); 

           digitalWrite(radioSwitch, HIGH);
           digitalWrite(recModuleSwitch, LOW);
           digitalWrite(whiteLed, HIGH);
           digitalWrite(rgbLed, LOW);

           if (digitalRead(activateSwitch) == LOW) {
             currentState = sWaiting;
           }       

           allSittingCheck();                                      // If all 5 seats are occupied, go to
           if(allSitting == 1) {                                   // Standby mode before Party state
             currentState = sStandby;
           }
           break;

       case sStandby:
           Serial.println("Standby to Party");

           digitalWrite(radioSwitch, HIGH);
           digitalWrite(recModuleSwitch, LOW);
           digitalWrite(whiteLed, LOW);
           digitalWrite(rgbLed, HIGH);

           allSittingCheck();

           if (allSitting == 0)  {                                  // If everyone is sitting there is
             for(int f=0; f<15; f++) {                              // 15 secs to go into Party State
               digitalWrite(whiteLed, HIGH);
               delay(500);
               digitalWrite(whiteLed, LOW);
               allStandingCheck();
               if(allStanding == 1) {
                 f = 15;
                 currentState = sParty;
               }
               delay(500);
             }
             allSittingCheck();
             if(allSitting == 0) {
               currentState = sActivate;
             }
           }

           if (digitalRead(activateSwitch) == LOW) {
           currentState = sWaiting;
           }

           break;

       case sParty:
           Serial.println("Party!");

           digitalWrite(radioSwitch, HIGH);
           digitalWrite(recModuleSwitch, LOW);
           digitalWrite(whiteLed, LOW);

           audioVal = analogRead(audioIn);

           if (audioVal <= 14) {                                    // Flash lights to music
             digitalWrite(rgbLed, LOW);
           } else {
             digitalWrite(rgbLed, HIGH);
           }

           allStandingCheck();

           if (allStanding == 0)  {
             currentState = sActivate;
           }
           if (digitalRead(activateSwitch) == LOW) {
             currentState = sWaiting;
           }
           break;

       default:
           Serial.println("ERROR: default state");
           currentState = sWaiting;
           nextState = sActivate;
           break;
   }
}

//------------------- PIR SENSOR MOTION CHECK -------------------//
void motionCheck()  {
  for (int j=0; j < 5; j++)  {
    if (digitalRead(pirSensor) == LOW)  {
      motionCount++;
      delay(500);
    }
  }
}

//----------------- EVERYONE SITTING DOWN CHECK -----------------//
void allSittingCheck()  {
  if (digitalRead(seat1) == HIGH and digitalRead(seat2) == HIGH and
      digitalRead(seat3) == HIGH and digitalRead(seat4) == HIGH and
      digitalRead(seat5) == HIGH) {
    allSitting = 1;
  } else  {
    allSitting = 0;
  }
}

//------------------- EVERYONE STANDING STANDING ----------------//
void allStandingCheck()  {
  if (digitalRead(seat1) == LOW and digitalRead(seat2) == LOW and
      digitalRead(seat3) == LOW and digitalRead(seat4) == LOW and
      digitalRead(seat5) == LOW) {
    allStanding = 1;
    Serial.println("All Standing");
  } else  {
    allStanding = 0;
  }
}

Overall, we were very satisfied with how the project turned out. It was well received at the Meeting of the Minds, and we even won a prize from the STUDIO for Creative Inquiry. We plan on continuing to develop Boomboxes as concept, further improving the design and functionality of the space. The next public forum in which we are hoping to present the project is the Outdoor Lounge Exhibition of Artscape 2008, in Baltimore, MD, which we are currently on the waitlist for.

May 5, 2008

Boomboxes: Update

Filed under: Final Project,Jesse Chorng,Paul Castellana — Jesse @ 4:36 am

Paul and I have been working around the clock to get our project ready for both Meeting of the Minds and MTI’s final show. For everyone who has been asking about the project, we wanted to post an update to show the class our progress. Here are some pictures of the construction process thats lasted the past few weeks.

More pics can be found on the project’s website here. The site itself is a work in progress- none of the buttons on the left actually work. But check out the blog. And although there are no pics of it, we’ve been working hard on the electronics side of it all as well. If you’re interested stay tuned to the Boomboxes blog/site as we’ll be posting up tutorials, diagrams, schematics, and pics throughout this week. Besides the XBee Radios, everything else is wired up and ready for the final show.

May 1, 2008

Reflections

Filed under: Assignments,Final Writing Assignment,Paul Castellana — paulcastellana @ 10:05 am

What I have found most interesting about this class is simply learning of the prevalence and accessibility of (as I believe Sid put it) this “culture” surrounding microcontrollers and sensors and making things interactive in general. Prior to this class, I was under the impression that work in this field was limited to those formally taught as engineers. I’d never have imagined that it was as accessible as it is. Now, I find myself constantly coming across everyday technology and thinking, “wow, I know how to make that.” As an economist, I find this accessibility particularly interesting because of the implications it has for innovation, which in the long run is most responsible for the improvement of people’s everyday lives. As more and more people are exposed to this field the overall source of technological innovation becomes greater and greater, extending far beyond formal engineers and into the hands of anyone with a computer and access to the internet. Simultaneously, the knowledge pool relevant to this field will grow tremendously as people share their work on the internet, as will components at the public’s disposal to work with.

I think that there is a growing trend of DIY and personalization that this field compliments perfectly. As the two become more and more intertwined, the commercial viability of microcontrollers and sensors will bring them into a new realm. Perhaps this is a stretch, but imagine if a major consumer electronics company such as Apple supplied and supported this technology in even more accessible and easy-to-use forms.

In terms of how the class will affect my future work personally, it has definitely dramatically altered how I will approach any future projects. I labeled myself as a woodworker at the beginning of the semester, but now I can’t imagine a project being very interesting without incorporating what I’ve learned in this class.

March 20, 2008

3D Mirror State Diagram

Filed under: 8: State Machine,Paul Castellana — paulcastellana @ 1:15 am

Continuing with the 3D Mirror concept, I want to luminate each moving block according to its position, so as it moves it’s constanting changing color.

3dmirrorstatediagram.pdf

March 8, 2008

Midterm: Single Pixel of a 3-D Mirror

Filed under: 7: Mid-Term Project,Paul Castellana — paulcastellana @ 4:21 pm

I was trying to insert some images I posted to Flickr, but it’s not working. Here’s the link to flickr though.

I found the formula for linearizing the voltage output from the IR Range sensor here.

Video:

int servoPin = 2;     // Control pin for servo motor
int minPulse = 500;   // Minimum servo position
int maxPulse = 2500;  // Maximum servo position
int pulse = 0;        // Amount to pulse the servo

long lastPulse = 0;    // the time in milliseconds of the last pulse
int refreshTime = 20; // the time needed in between pulses

int val;             // outgoing ADC value
int distance = 0;    // linearized distance value

void setup()
{
pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
pulse = minPulse;           // Set the motor position value to the minimum
beginSerial(9600);
}

void loop()
{
val = analogRead(0); // read analog input:
distance = (2914 / (val + 5)) - 1;   // linearize sensor readings
printString("distance = "); // print out distance readings for reference
printInteger(distance);
printString("  ");

delay(10);

pulse = distance*125;    // convert distance to a value between minPulse
// and maxPulse

if (minPulse &lt; pulse = refreshTime) {  // pulse the servo again if rhe refresh time (20 ms) have passed:
digitalWrite(servoPin, HIGH);   // Turn the motor on
delayMicroseconds(pulse);       // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW);    // Turn the motor off
lastPulse = millis();           // save the time of the last pulse
} else {
pulse = minPulse;
}
}
}

February 28, 2008

Midterm Proposal: Piece of a 3D Mirror

Filed under: 7: Mid-Term Project,Assignments,Paul Castellana — paulcastellana @ 9:04 pm

Abstract:

My goal for this semester is to develop the foundations of a 3D mirror. Ultimately, I imagine this as a grid of hundreds of small blocks that would each move to “reflect” a point over a
complementary sensor grid. In this sense, each block would act as a pixel on a screen, except
instead of changing color they change height. So for the midterm I’m breaking it down to
just two blocks and two IR range sensors.

Code Sketch:

- Set servos to starting position
- Check inputs of range finders
- Convert input voltages into linear values
- If linear values fall within defined range, then move servos according to values
- If not, return servos to starting position

Parts:

Arduino
2 x Servo Motor
2 x GP2D120 IR Range Sensors
Gears
Wiring
Building Material (haven’t decided on this yet)

Drawings and Circuit Schematics:

Diagrams

(pdf)

February 12, 2008

Making Motion

Filed under: 5: Making Motion,Assignments,Paul Castellana — paulcastellana @ 2:54 pm

For this assignment, I used a potentiometer to control a DC motor and a servo simultaneously. The speed of the DC changes as you turn the potentiometer, as does the position of the servomotor. At this point my only goal was to produce some sort of variation in the movement of both motors, but it would be useful to further investigate the exact relationship between the turn of the potentiometer and the change in the motors. As it is now, with both motors powered at the same time, the servo is very jumpy and somewhat unpredictable, where as if I turn off the power to the DC motor, the servo runs more smoothly. I’m not sure what the cause of this is… possibly I have the diode in the wrong place?


int potPin = 0;           // Analog in 0 connected to the potentiometer
int potValueT = 0;         // value returned from the potentiometer used to control transistor
int potValueS = 0;        // value returned from the potentiometer used to control Servomotor
int transistorPin = 9;    // connected to the base of the transistor

int servoPin = 2;         // Control pin for the servomotor
int minPulse = 500;       // Minimum servo position
int maxPulse = 2500;      // Maximum servo position
int pulse = 0;            // Amount to pulse the servo

long lastPulse = 0;       // the time in milliseconds of the last pulse
int refreshTime = 20;     // the time needed in between pulses

void setup() {

  pinMode(transistorPin, OUTPUT);  // set the transistor pin as output:
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  pulse = minPulse;           // Set the motor position value to the minimum
  Serial.begin(9600);
}

void loop() {

  potValueT = analogRead(potPin) / 4;  // read the potentiometer, convert it to 0 - 255:
  analogWrite(9, potValueT);  // use that to control the transistor:

  potValueS = analogRead(potPin);      // read the potentiometer input
  pulse = (potValueS * 19) / 10 + minPulse;    // convert the analog value
                                            // to a range between minPulse
                                            // and maxPulse. 

  // pulse the servo again if rhe refresh time (20 ms) have passed:
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // Turn the motor on
    delayMicroseconds(pulse);       // Length of the pulse sets the motor position
    digitalWrite(servoPin, LOW);    // Turn the motor off
    lastPulse = millis();           // save the time of the last pulse

  }
}

February 5, 2008

Counting with LEDs

Filed under: 4: Counting Sensor Input,Assignments,Paul Castellana — paulcastellana @ 2:35 pm

Each time you press the push button an LED lights up, and stays lit until all five are on, at which point pressing the button turns them all off, and restarts the cycle. To get it work, I manipulated the code presented at the end of the Lesson 5 LadyAda Tutorial.

int switchPin = 2;              // switch is connected to pin 2
int led1Pin = 12;
int led2Pin = 11;
int led3Pin = 10;
int led4Pin = 9;
int led5Pin = 8;

int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

int lightMode = 0;              // What mode is the light in?

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(led5Pin, OUTPUT);

  Serial.begin(9600);           // Set up serial communication at 9600bps
  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings
    if (val != buttonState) {          // the button state has changed
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 0) {          // if its off
            lightMode = 1;               // light up 1
        } else {
          if (lightMode == 1) {        // if one's lit
              lightMode = 2;             // light up 2
          } else {
            if (lightMode == 2) {      // if 2 are lite
                lightMode = 3;           // lit up 3
            } else {
		if (lightMode == 3) {
                    lightMode = 4;
                } else {
                    if (lightMode == 4) {
                        lightMode = 5;
                    } else {
                        if (lightMode == 5) {
                            lightMode = 0;

                    }
                }
             }
           }
         }
       }
     }
   }

    buttonState = val;                 // save the new state in our variable
  }

  // Now do whatever the lightMode indicates
  if (lightMode == 0) { // all-off
    digitalWrite(led1Pin, LOW);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }

  if (lightMode == 1) { // One on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, LOW);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }

  if (lightMode == 2) { // two on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, LOW);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }

  if (lightMode == 3)  { // three on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, LOW);
    digitalWrite(led5Pin, LOW);
  }

  if (lightMode == 4)  { // four on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, LOW);
  }

  if (lightMode == 5)  { // five on
    digitalWrite(led1Pin, HIGH);
    digitalWrite(led2Pin, HIGH);
    digitalWrite(led3Pin, HIGH);
    digitalWrite(led4Pin, HIGH);
    digitalWrite(led5Pin, HIGH);
  }        

January 29, 2008

Term Project Ideas

Filed under: 2: Term Project Idea,Assignments,Paul Castellana — paulcastellana @ 6:20 am

One idea I’ve been thinking about is actually how I pictured the “Wooden Mirror” in my head before seeing a video of it. I was thinking of a grid of small rectangular blocks that were each connected to sensors that detected distance and were in a similar grid formation. As objects come before the sensor grid, the blocks would move up and down to create a rough 3D representation of them. If this is even feasible, I have a feeling it’s probably to costly to actually do.

My other idea is to create a sculpture that is constantly changing according to actions of its spectators.

January 21, 2008

Ambient Addition

Filed under: 1: Post Something Interesting,Assignments,Paul Castellana — paulcastellana @ 6:04 pm
Tags: , ,

Ambient Addition, designed by Noah Vawter of the Computer Culture research group at MIT’s Media Lab, is a walkman that “superimposes a layer of harmony and rhythm on top of the listener’s world.” A microphone captures ambient noises which serve as the foundation for music that is simultaneously played in the user’s headphones. What I like about this project is its intention to alter the user’s everyday experience not by completely changing it, but by enriching it using stimuli that the user might otherwise want to block out.

The Rubric Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.