Get the Flash Player to see the slideshow.

Meet TweetChime

Posted: December 3rd, 2009 | Author: Cindy | Filed under: ITP | Tags: , , , | No Comments »

TweetChime Live Demo from cindy wong on Vimeo.

Helping people overcome long distances, TweetChime is a melodic chime that communicates people’s sentiments and transmits them into melody. So, no matter where you are, you can let your loved ones know you’re thinking of them and they can hear your sentiment in real-time in sound. By using Twitter, you can send your preferred sentiment, anytime and anywhere at your convenience.

In this case, in the video above, my brother, Pat has sent me this coded message: “@tweetchime [dinnertime] awww yeah!” Why? Because he has an odd sense of humor  from living in Mobile, Al. which somehow is lost on me  in New York City. Ah, family.

Who Could Use TweetChime?

TweetChime is great for ambient contact technology. In other words, you can keep yourself open to others without them having to actively message you (through phone/IM/email). Vice versa, they can quickly tweet you and have the satisfaction of knowing that you will hear their tweet melody in real time on your side.  The TweetChime is unobtrusive and (if prototyped further) can blend into your household.

  • Long distance friends/family
  • Parents who want to communicate with their kids (who can’t read time, distinguish technology)
  • Visually Impaired

Interact with TweetChime:

Would you like to send a sentiment to me? Please tweet to @tweetchime, the TweetChime’s Twitter account.

How to Send: TweetChime recognizes the coded message within the brackets [ ]. The TweetChime website will scan Twitter’s search results looking for messages aimed at @tweetchime.

I have programmed a reply that TweetChime can recognize from a Twitter message. Choose your choice below:

  • @tweetchime [be happy]
  • @tweetchime [congratulations]
  • @tweetchime [missing you]
  • @tweetchime [holla]
  • @tweetchime [coming home]
  • @tweetchime [dinner time]

ex: cwong08 says: “@tweetchime [dinner time] Mom is serving mashed potatoes and turkey! Mmmm!

Where Does My Tweet Go?

TweetChime will be searching for all mentions of itself (@tweetchime) through Twitter’s public search time line. When it finds the coded tweet (1 of the 6 above), it’ll understand it and output into a short melody that the TweetChime owner will understand.

See It In Action

Software Setup:

screengrab_tweetchimewebsite

TweetChime – home page for the TweetChime machine

So, what’s running the online component of TweetChime? TweetChime involves 2 websites: TweetChime, the html site and a php site. The recipient of all these TweetChime melodies has the TweetChime website open in their web browser. The TweetChime website is constantly communicating to its PHP site (via AJAX) which is  checking a RSS feed of Twitter’s search results for mentions of @tweetchime [coded message here]. The ones that are properly formatted get grabbed to TweetChime’s html website. That website has Javascript coding which allows serial communication between the PC and the Arduino. The website passes the encoded values (for example, [be happy] = byte value 65)  within the Twitter messages to the Arduino which can understand them and output the commands associated with each coded byte value. The beauty is that TweetChime will only play fresh tweets so that folks will always know that the tweet melody heard is something that was sent by someone in real time.

phpcode

PHP site that is parsing the tweets that people are sending to @tweetchime

serialcommunication_javascript

Javascript receives the parsed tweets and transmits to Arduino to output to TweetChime

  • Update: Managed to parse Twitter RSS data to now include the current Twitter sender, Twitter sender’s icon

Physical Setup

Ingredients: 5 Servo Motors, 1 Arduino, 1 BreadBoard, 22-gauge wires, 5 large metal wind chimes, 5 tiny metal chime pipes (to act as knockers), plywood, DC jack, 12V DC adapter, voltage regulator, heat shield (to protect the voltage regulator from overheating)

TweetChime Machine Setup

Servo Motors are mounted to a back board. Attached to each servo motor is a smaller wind chime pipe that acts as a knocker to produce a clear ring against the hanging wind chime tube pipe. The Arduino and breadboard are mounted behind the back board.

backoftweetchime

Arduino Coding:
Did you know that the servo library can now handle multiple servos without it overloading the timing involved in it? I originally wrote my Arduino code to include delays with the Servo Library and for whatever reason, when I added my 4th servo motor, it got jittery, ran abruptly and sometimes went on randomly. It may or may not have been a power issue involving a misplaced wire. However, after talking to my professor Tom Igoe, he managed to demonstrate a way for me to orderly arrange my servo motors (with arrays rather then explicitly listing each servo motors and it’s individual slot pin). I also learned that when you use the Servo Library, you don’t have to deal with mounting servo motors on only PWM slots on the Arduino – you can use ANY slot (which in my case was ANY digital slot). Here’s the code I ended up with:

#include
// an array of instances of the Servo library:
Servo myServos[5];
int incomingByte = 0;  //SETS UP AS ZERO INTERACTION @ START.
int pos = 0;   

void setup() {
 Serial.begin(9600);
 // opens serial port, sets data rate to 9600 bps

 // initialize the servos in the array on pins 2,3,4,5,6
 // servo 0 = pin 2; servo 1 = pin 3, servo 2 = pin 4, servo 3 = pin 5, servo 4 = pin 6
 for (int thisServo = 0; thisServo < 5; thisServo++) {
  int thisPin = thisServo + 2;
  myServos[thisServo].attach(thisPin);
 }

}

void loop() {
  if (Serial.available() > 0) {
   // read the incoming byte:
   incomingByte = Serial.read(); // CHECKS FOR INCOMING SERIAL DATA.

   if(incomingByte == 70) {      // IF INCOMING DATA = 70, REACT.
       // MELODY 68 =  Chime Sequence = 0,5,0,5 = coming home

            for (int thisServo = 0; thisServo < 1; thisServo++) {

            myServos[2].write(180); //  servo in array; swing forward in 180 deg.
            delay(500);

            myServos[2].write(100); //  servo in array; swing back 100 deg.
            delay(500);

            myServos[3].write(180);
            delay(500);

            myServos[3].write(100);
            delay(500);

            myServos[1].write(180);
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100);
            delay(500);

           myServos[2].write(180);
            delay(500);

            myServos[2].write(100);
            delay(500);

            myServos[3].write(180);
            delay(500);

            myServos[3].write(100);
            delay(500);

            myServos[1].write(180);
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100);
            delay(500);
            }
       } 

    if(incomingByte == 69) {      // IF INCOMING DATA = 69, REACT.
       // MELODY 68 =  Chime Sequence = 0,5,0,5 = dinner time

            for (int thisServo = 0; thisServo < 1; thisServo++) {
            // move to 0 degrees:
            myServos[0].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[0].write(100);
            delay(500);

            myServos[4].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[4].write(100);
            delay(500);

            myServos[0].write(180); // 3rd servo in array; swing forward
            delay(900);
            // move to 0 degrees:
            myServos[0].write(100); // 3rd servo in array; swing back
            delay(900);

            myServos[4].write(180); // first servo in array; swing forward
            delay(900);
            // move to 0 degrees:
            myServos[4].write(100);
            delay(900);

            }
       } 

     if(incomingByte == 68) {      // IF INCOMING DATA = 67, REACT.
       // MELODY 68 =  Chime Sequence = 2,1,0,4,3 = HOLLA

            for (int thisServo = 0; thisServo < 1; thisServo++) {
            // move to 0 degrees:
            myServos[2].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[2].write(100);
            delay(500);

            myServos[3].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[3].write(100);
            delay(500);

            myServos[1].write(180); // 3rd servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100); // 3rd servo in array; swing back
            delay(500);

          myServos[2].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[2].write(100);
            delay(500);

            myServos[3].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[3].write(100);
            delay(500);

            myServos[1].write(180); // 3rd servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100); // 3rd servo in array; swing back
            delay(500);
            }
       } 

       if(incomingByte == 67) {      // IF INCOMING DATA = 67, REACT.
         // MELODY 67 =  Chime Sequence = 1,3,1,2,0 = MISSING YOU

            for (int thisServo = 0; thisServo < 1; thisServo++) {
            // move to 0 degrees:
            myServos[1].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100);
            delay(500);

            myServos[3].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[3].write(100);
            delay(500);

            myServos[1].write(180); // 3rd servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100); // 3rd servo in array; swing back
            delay(500);

            myServos[2].write(180); // 4th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[2].write(100); // 4th servo in array; swing back
            delay(500);

            myServos[0].write(180); // 5th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[0].write(100); // 5th servo in array; swing back
            delay(500);
            }
       }
             if(incomingByte == 66) {      // IF INCOMING DATA = 65, REACT.
       // MELODY 66 =  Chime Sequence 0, 2, 4, 1, 3 = CONGRATULATIONS

            for (int thisServo = 0; thisServo < 1; thisServo++) {
            // move to 0 degrees:
            myServos[0].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[0].write(100);
            delay(500);

            myServos[1].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100);
            delay(500);

            myServos[2].write(180); // 3rd servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[2].write(100); // 3rd servo in array; swing back
            delay(500);

            myServos[3].write(180); // 4th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[3].write(100); // 4th servo in array; swing back
            delay(500);

            myServos[4].write(180); // 5th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[4].write(100); // 5th servo in array; swing back
            delay(500);
            }
      }

    if(incomingByte == 65) {      // IF INCOMING DATA = 65, REACT.
       // MELODY 65 =  Chime Sequence 4,3,2,1,0

            for (int thisServo = 0; thisServo < 1; thisServo++) {
            // move to 0 degrees:
            myServos[4].write(180); // first servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[4].write(100);
            delay(500);

            myServos[3].write(180); // 2nd servo in array; swing back
            delay(500);
            // move to 0 degrees:
            myServos[3].write(100);
            delay(500);

            myServos[2].write(180); // 3rd servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[2].write(100); // 3rd servo in array; swing back
            delay(500);

            myServos[1].write(180); // 4th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[1].write(100); // 4th servo in array; swing back
            delay(500);

            myServos[0].write(180); // 5th servo in array; swing forward
            delay(500);
            // move to 0 degrees:
            myServos[0].write(100); // 5th servo in array; swing back
            delay(500);
            }
       }
    }
  }


Leave a Reply

  • Powered by WP Hashcash