Making Things Interactive

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.

April 18, 2008

Interactive Hovercraft

Filed under: Assignments, Final Project, Lingshui Wang — lingshui @ 11:13 am

Currently I have a working hovercraft which can hold the weight of an arduino, power pack, and various inputs and outputs. I am looking to improve this to hold more weight (a.k.a. strip down the weight of the hovercraft). I am having a bit of a problem with the interactive bit of it but should have it up and running very soon. Still hopeful about creating movement with the hovercraft, but right now it seems I’ll have to settle for something simpler.

Schematic

Code coming as soon as I fix it

Washroom Penitentiary

Filed under: Final Project, Gaku Sato — ponkotsu @ 3:24 am

Here is my final state diagram, wiring schematic, and code (though I might change some threshold values).  The code is excessively long and definitely not optimized; it was just the easiest way to understand what was going on so I can more easily debug.  It should be relatively self-explanatory therefore.  The state diagram from which the code was derived is similarly not optimal for the same reason.

And I figured out that the reason the bell & buzzer weren’t going off during the demo was because I turned on the batteries improperly, as in apparently I need to turn on the Arduino last, otherwise it will enter some strange inescapable state-change path.  I don’t have it all figured out but it’s hopefully enough such that the effectiveness of Murphy’s Law won’t be consistent.

HELP REQUEST!
I’m having no luck photographing it and I honestly have no idea how to videoscenario it so if anyone has any suggestions or can offer help it would be greatly appreciated!

[State Diagram & Wiring Schematic]

[Code]

#include <Servo.h>

// PINS //
int soapLED_R = 10; // warning light
int soapLED_G = 9;  // indicates soap being dispensed
int soapLED_B = 8;  // standard light [GB=white]
int sinkLED = 11;   // indicates running water [B]

int soapsensor = 0;
int sinksensor = 1;

int toiletswitch = 12; // indicates motion detected [into toilet!]
int flushbutton = 13;
int lockbutton = 7;
int doorswitch = 4;

int signservo = 3;
int locksolenoid = 2;
int speaker = 5;
int bell = 6;

Servo sign;

// STATES //
int State = 0;
const int Blank = 0;
const int Locked = 1;
const int Wash = 2;
const int LockWash = 3;
const int Flush = 4;
const int Toilet = 5;
const int DUnlock = 6;
const int DLeaving = 7;
const int DSoap = 8;
const int DRinse = 9;
const int Clean = 10;
const int CLeaving = 11;
const int TUnlock = 12;
const int TLeaving = 13;
const int TSoap = 14;
const int TWater = 15;

int LockState = 0;
const int Auto = 0;
const int Manual = 1;

// OUTPUT CONDITIONS //
int Reward = 0;
const int Off = 0;
const int On = 1;
int Buzzer = 0;
int Sign = 0;
const int Bl_Bl = 125; // in: blank   out: blank
const int Wa_Bl = 107; // in: wash    out: blank
const int Wa_Di = 87;  // in: wash    out: dirty
const int Ri_Bl = 68;  // in: rinse   out: blank
const int Fl_Bl = 51;  // in: flush   out: blank
const int Fl_Fl = 31;  // in: flush   out: flush
const int Th_Cl = 13;  // in: thanks  out: clean!
int Soap = 0;
const int White = 0;  // standard light
const int Red = 1;    // warning light
const int Green = 2;  // indicates soap being dispensed
int Sink = 0;
int Lock = 0;

// ANALOG INPUT THRESHOLDS //
int soapmin = 30;
int soapmax = 100;
int sinkmin = 100;
int sinkmax = 300;

// OTHER //
int lockbuttonpress = 0;
int dooropentime = 0;
int sinkontime = 0;

void setup()
{
  Serial.begin(9600);
 
  pinMode(soapLED_R, OUTPUT); // digital
  pinMode(soapLED_G, OUTPUT); // digital
  pinMode(soapLED_B, OUTPUT); // digital
  pinMode(sinkLED, OUTPUT);   // digital
  pinMode(soapsensor, INPUT); // analog
  pinMode(sinksensor, INPUT); // analog
  pinMode(toiletswitch, INPUT);  // digital
  pinMode(flushbutton, INPUT);   // digital
  pinMode(lockbutton, INPUT);    // digital
  pinMode(doorswitch, INPUT);    // digital: LOW when closed, HIGH when open
  pinMode(signservo, OUTPUT);    // digital PWM
  pinMode(locksolenoid, OUTPUT); // digital
  pinMode(speaker, OUTPUT);      // digital
  pinMode(bell, OUTPUT);         // digital
 
  State = Blank;
  LockState = Auto;
  Reward = Off;
  Buzzer = Off;
  Sign = Bl_Bl;
  Soap = White;
  Sink = White;
  Lock = Off;
 
  lockbuttonpress = 0;
  dooropentime = 0;
  sinkontime = 0;
 
  sign.attach(signservo);
  sign.setMaximumPulse(2400);
  sign.setMinimumPulse(544);
  sign.write(Bl_Bl);
}

void loop()
{
  // SWITCH STATES //
  switch(State)
  {
    case Blank:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH &amp;&amp; digitalRead(doorswitch)==LOW)
      { lockbuttonpress=1; State=Locked; }
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(analogRead(soapsensor)<soapmin) {State=Wash;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case Locked:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=Blank;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(analogRead(soapsensor)<soapmin) {State=LockWash;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case Wash:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH &amp;&amp; digitalRead(doorswitch)==LOW)
      { lockbuttonpress=1; State=LockWash; }
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH) {State=Blank;}
      if(analogRead(sinksensor)<sinkmin) {State=Clean;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case LockWash:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=Wash;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH) {State=Blank;}
      if(analogRead(sinksensor)<sinkmin)
      { if(sinkontime==0) {sinkontime=millis();}
        if(millis()-sinkontime>1000) {sinkontime=0; State=Clean;} }
      if(analogRead(sinksensor)>sinkmax) {sinkontime=0;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case Flush:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=DUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=DLeaving; }
      if(analogRead(soapsensor)<soapmin) {State=DSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=DRinse;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case Toilet:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=TUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH) {dooropentime=millis(); State=TLeaving;}
      if(analogRead(soapsensor)<soapmin) {State=TSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=TWater;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      break;
    case DUnlock:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH &amp;&amp; digitalRead(doorswitch)==LOW)
      { lockbuttonpress=1; State=Flush; LockState=Manual; }
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=DLeaving; }
      if(analogRead(soapsensor)<soapmin) {State=DSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=DRinse;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case DLeaving:
      if(digitalRead(doorswitch)==LOW &amp;&amp; millis()-dooropentime<1000)
      { dooropentime=0; State=Flush;}
      if(millis()-dooropentime>1000) {dooropentime=0; State=Blank;}
      if(analogRead(soapsensor)<soapmin) {State=DSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=DRinse;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case DSoap:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=DUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=DLeaving; }
      if(analogRead(sinksensor)<sinkmin)
      { if(sinkontime==0) {sinkontime=millis();}
        if(millis()-sinkontime>1000) {sinkontime=0; State=Clean;} }
      if(analogRead(sinksensor)>sinkmax) {sinkontime=0;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case DRinse:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=DUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=DLeaving; }
      if(analogRead(soapsensor)<soapmin) {State=DSoap;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case Clean:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1;
        if(LockState==Manual) {LockState=Auto;}
        if(LockState==Auto &amp;&amp; digitalRead(doorswitch)==LOW) {State=Locked;} }
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=CLeaving; }
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case CLeaving:
      if(digitalRead(doorswitch)==LOW || millis()-dooropentime>1000)
      { dooropentime=0; State=Blank;}
      break;
    case TUnlock:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH &amp;&amp; digitalRead(doorswitch)==LOW)
      { lockbuttonpress=1; State=Toilet; LockState=Manual; }
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH) {dooropentime=millis(); State=TLeaving;}
      if(analogRead(soapsensor)<soapmin) {State=TSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=TWater;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case TLeaving:
      if(digitalRead(doorswitch)==LOW &amp;&amp; millis()-dooropentime<1000)
      { dooropentime=0; State=Toilet;}
      if(millis()-dooropentime>1000) {dooropentime=0; State=Blank;}
      if(analogRead(soapsensor)<soapmin) {State=TSoap;}
      if(analogRead(sinksensor)<sinkmin) {State=TWater;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case TSoap:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=TUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=TLeaving; }
      if(analogRead(sinksensor)<sinkmin) {State=TWater;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
    case TWater:
      if(lockbuttonpress==0 &amp;&amp; digitalRead(lockbutton)==HIGH)
      { lockbuttonpress=1; State=TUnlock;}
      if(digitalRead(lockbutton)==LOW) {lockbuttonpress=0;}
      if(digitalRead(doorswitch)==HIGH)
      { dooropentime=millis(); State=TLeaving; }
      if(analogRead(soapsensor)<soapmin) {State=TSoap;}
      if(digitalRead(flushbutton)==HIGH) {State=Flush;}
      if(digitalRead(toiletswitch)==HIGH) {State=Toilet;}
      break;
  }
 
  // SET CONDITIONS //
  switch(State)
  {
    case Blank:
      dooropentime = 0; sinkontime = 0;
      Reward = Off; Buzzer = Off;
      Sign = Bl_Bl;
      Soap = White; Sink = Off;
      Lock = Off;   LockState = Auto;
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
    case Locked:
      Reward = Off; Buzzer = Off;
      Sign = Bl_Bl;
      Soap = White; Sink = Off;
      Lock = On;    LockState = Manual;
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
    case Wash:
      Reward = Off; Buzzer = Off;
      Sign = Bl_Bl;
      Soap = White; Sink = Off;
      Lock = Off;   LockState = Auto;
      if(analogRead(soapsensor)<soapmin) {Soap = Green;}
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
    case LockWash:
      Reward = Off; Buzzer = Off;
      Sign = Bl_Bl;
      Soap = White; Sink = Off;
      Lock = On;    LockState = Manual;
      if(analogRead(soapsensor)<soapmin) {Soap = Green;}
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
    case Flush: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Wa_Bl;
      Soap = Red;   Sink = Off;
      Lock = On;
      break;
    case Toilet: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Fl_Bl;
      Soap = White; Sink = Off;
      Lock = On;
      break;
    case DUnlock:
      Reward = Off; Buzzer = Off;
      Sign = Wa_Di;
      Soap = Red;   Sink = Off;
      Lock = Off;   LockState = Auto;
      break;
    case DLeaving:
      Reward = Off; Buzzer = On;
      Sign = Wa_Di;
      Soap = Red;   Sink = Off;
      Lock = Off;   LockState = Auto;
      break;
    case DSoap: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Wa_Bl;
      Soap = Red;   Sink = Off;
      Lock = On;
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      if(analogRead(soapsensor)<soapmin) {Soap = Green;}
      break;
    case DRinse: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Ri_Bl;
      Soap = Red;   Sink = Off;
      Lock = On;
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
    case Clean:
      sinkontime = 0;
      Reward = Off; Buzzer = Off;
      Sign = Th_Cl;
      Soap = White; Sink = Off;
      if(analogRead(soapsensor)<soapmin) {Soap = Green;}
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      if(LockState==Auto) {Lock = Off;}
      else {Lock = On;}
      break;
    case CLeaving:
      Reward = On; Buzzer = Off;
      Sign = Th_Cl;
      Soap = White; Sink = Off;
      Lock = Off; LockState = Auto;
      break;
    case TUnlock:
      Reward = Off; Buzzer = Off;
      Sign = Fl_Fl;
      Soap = White; Sink = Off;
      Lock = Off;   LockState = Auto;
      break;
    case TLeaving:
      Reward = Off; Buzzer = On;
      Sign = Fl_Fl;
      Soap = White; Sink = Off;
      Lock = Off;   LockState = Auto;
      break;
    case TSoap: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Fl_Bl;
      Soap = White; Sink = Off;
      Lock = On;
      if(analogRead(soapsensor)<soapmin) {Soap = Green;}
      break;
    case TWater: // do not set LockState
      Reward = Off; Buzzer = Off;
      Sign = Fl_Bl;
      Soap = White; Sink = Off;
      Lock = On;
      if(analogRead(sinksensor)<sinkmin) {Sink = On;}
      break;
  }

  // EXECUTE CONDITIONS //
  if(Reward==On) {digitalWrite(bell, HIGH);}
  else {digitalWrite(bell, LOW);}
  if(Buzzer==On) {digitalWrite(speaker, HIGH);}
  else {digitalWrite(speaker, LOW);}
  switch(Sign)
  {
    case Bl_Bl: sign.write(Bl_Bl); break;
    case Wa_Bl: sign.write(Wa_Bl); break;
    case Wa_Di: sign.write(Wa_Di); break;
    case Ri_Bl: sign.write(Ri_Bl); break;
    case Fl_Bl: sign.write(Fl_Bl); break;
    case Fl_Fl: sign.write(Fl_Fl); break;
    case Th_Cl: sign.write(Th_Cl); break;
  }
  Servo::refresh();
  switch(Soap)
  {
    case White:
      digitalWrite(soapLED_R, LOW);
      digitalWrite(soapLED_G, HIGH);
      digitalWrite(soapLED_B, HIGH);
      break;
    case Red:
      digitalWrite(soapLED_R, HIGH);
      digitalWrite(soapLED_G, LOW);
      digitalWrite(soapLED_B, LOW);
      break;
    case Green:
      digitalWrite(soapLED_R, LOW);
      digitalWrite(soapLED_B, HIGH);  // B &amp; G pins reversed?
      digitalWrite(soapLED_G, LOW);
      break;
  }
  if(Sink==On) {digitalWrite(sinkLED, HIGH);}
  else {digitalWrite(sinkLED, LOW);}
  if(Lock==On &amp;&amp; digitalRead(doorswitch)==LOW) {digitalWrite(locksolenoid, HIGH);}
  else {digitalWrite(locksolenoid, LOW);}
}

April 15, 2008

Final Project

Currently I have a manually working plant which can rotate from left to right and move up and down with inputs from two potentiometers. I have been having difficulty working with the input values from the photosensor (eliminating noise) and then problems with the servo twitching and not responding correctly to the photosensor values.

int pulse = 0;
int StemServoPin = 10;
int BaseServoPin = 11;
int LED = 5;
long count = 0;
int phi[] = {100};
int theta[] = {180} ;
int buffer = 5000;

void setup() {
  pinMode(StemServoPin, OUTPUT);
  pinMode(BaseServoPin, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(0, INPUT);
  pinMode(1, INPUT);
  Serial.begin(9600);
  digitalWrite(13,HIGH);
  }

void pulseStemServo(int phi)
{
  int time;
  time = phi*10+1500;
  digitalWrite(StemServoPin, HIGH);
  delayMicroseconds(time);
  digitalWrite(StemServoPin, LOW);
}

void pulseBaseServo(int theta)
{
  int time;
  time = theta*0.555+1450;
  digitalWrite(BaseServoPin, HIGH);
  delayMicroseconds(time);
  digitalWrite(BaseServoPin, LOW);
}

int smooth(int buffer, int Pin){
  long sum = 0;
  for(int i = 0; i  100){
    count = 0;}
  count++;

  phi[count] = smooth(buffer, 0);
  theta[count] = smooth(buffer, 1);

  Serial.print(phi[count]);
  Serial.print(":");
  Serial.println(theta[count]);

  pulseBaseServo(theta[count]);
  pulseStemServo(phi[count]);

}

These photos are of my project from Saturday.

Laser Cut Parts before assembly

some of the mounting parts

The base assembled

closeup of the stem which shows the actuator cable

Initial version of the plant which broke

 

April 3, 2008

digital book – text display

Filed under: Assignments, Final Project, Nadeem Haidary — nhaidary @ 12:04 am

I have been doing research on electronic ink displays and exploring gestures for generating electricity. I have been working on the Processing end of things and figured out how to load, format and display a whole lot of text. For now, I’m using the < and > keys to navigate, but eventually it will be done tangibly. Here is a screenshot:

page example

And the code:

 /*
 *   Digital Book Reader
 *   State Machine
 *   Spring 2008
 *
 *   Nadeem Haidary
 */

//LIBRARIES
import processing.serial.*;

//GLOBAL VARIABLES
PFont title;                  // title font
PFont font;                   // text font
Serial port;                  // Create object from Serial class
int val;                      // Data received from the serial port
int x = 0;                    // stores nothing important right now
int page = 0;                 // page number
int spacer = 0;               // tracks line number within loop
int lineStart = -46;          // line that page starts at
int lineEnd = 0;              // line that page ends at
int linesPerPage = 46;        // the total amount of lines dispalyed up until a certain page
boolean saveImage = false;    // for saving a frame

void setup() {
  size (450, 600);
  frameRate(10);
  /*
  println(Serial.list());                                   // Set up the serial communication
   port = new Serial(this, Serial.list()[1], 9600);         // Open the port that the board is connected to (in this case COM4 = [1])
   // and use the same speed (9600 bps)
   */
  font = loadFont("BookAntiqua-10.vlw");
  title = loadFont("BookAntiqua-BoldItalic-48.vlw");
  String lines[] = loadStrings("ulysses_text only.txt");    // Loads the book from a text file and seperates each line into a String in an array
  println("there are " + lines.length + " lines");          // prints the number of lines
}

void draw() {
  background (250);                                         // sets the background color
  fill (0);                                                 // sets the text color
  smooth();                                                 // anti-aliasing
  String lines[] = loadStrings("ulysses_text only.txt");    // for some reason, the only way I can get this to work is by reloading the strings every frame

  // NAVIGATION
  if (keyPressed == true){
    if (key == '.') {                                       // press the > key to advance a page
      delay(40);
      page ++;
      lineStart += linesPerPage;
      lineEnd += linesPerPage;
    }
    if (key == ',' && page > 0) {                           // press the < key to go back a page
      delay(40);
      page--;
      lineStart -= linesPerPage;
      lineEnd -= linesPerPage;
    }
    if (key == 's') {                                       // press the s key to save a frame
      saveImage = true;
    }
    //println(lineStart + "   " + lineEnd);
  }

  if (page == 0) {                                          // display title page
    textFont(title, 48);                                    // sets the type to be used
    text("Ulysses", 250, 522);
    textFont(title, 18);
    text("James Joyce", 255, 480);
  }
  else {                                                    // display text pages
    textFont(font, 10);
    spacer = 0;
    for (int i=lineStart; i < lineEnd; i++) {               // display all the lines for this page
      text(lines[i], 20, 30 + (spacer*12));                 // starting corner and spaces between lines
      spacer++;                                             // count the lines
    }
    textFont(title, 10);
    text(page, 400, 20);                                    // display page number
  }

  if (saveImage == true) {                                  // save a frame
    save("page.tif");
  }

  /*
  if (0 < port.available()) {                       // If data is available,
   val = port.read();                              // read it and store it in val
   }

   if (val == 1) {
   x++;
   }
   */
}

March 27, 2008

light-aiming turret [related work]

Filed under: Final Project, Gaku Sato — ponkotsu @ 2:36 am

TECHNOLOGY

Light-Tracking Wheel
<http://www.youtube.com/watch?v=Y5qi711PRbI>
<http://www.physicsforums.com/showthread.php?p=1659156>
The basic control scheme for this device is the same as that intended for the turret control.  It rotates the wheel in the direction of the photosensor with the higher reading.  The movement is unfortunately very twitchy, and aside from the obvious reasons, it may be due to the large light source.

Sunlight-Tracking System
<http://www.wipo.int/pctdb/en/wo.jsp?wo=2006131028>
This system tracks sunlight in a similar fashion (by analyzing the difference between two separately located sensors).  It addresses the issue of having an incredibly large light source (the sun) is by filtering the light through a “microhole”.

Fuzzy Logic Light Tracker
<http://books.google.com/books?id=m8eVNWGnt5YC&pg=PA130&lpg=PA130&dq=light-tracker&source=web&ots=ItpZCLviYR&sig=L3CG8S0FvgupBvb0mkkeYz5FcXg&hl=en#PPA131,M1>
This is a device that accurately aims at light albeit in a narrow range with an ingenious light-blocking vane between the input sensors to exaggerate the light difference.

Optical Guidance System
<http://www.patentstorm.us/patents/6629028.html>
still decyphering…

Laserpointer-Tracking Program
<http://www.wipo.org/pctdb/en/wo.jsp?wo=2006085580>
still decyphering…
ENTERTAINMENT

Airsoft RC Tank
<http://www.hobbytron.com/AirsoftRCType90BattleTank.html>
320° turret (20° height) mounted on RC airsoft tank with 25m firing range and accurate 1/24-scale design!!

USB Missile Launcher
<http://www.thinkgeek.com/geektoys/warfare/8bc4/>
This is a stationary 180° turret (45° height) controlled by a computer via USB.

March 25, 2008

Final proposal

Filed under: Final Project, Lea — tovelet @ 1:45 pm

My project will be a panel of buttons, knobs, and switches, for a booth for CMU’s Spring Carnival.
The panel is supposed to be “science-y,” like a prop from 2001 or Star Trek, and it should invite exploratory interactions.  The board will react deterministically, but its responses might not always be directly obvious to the viewer.

The proposal is here: http://www.contrib.andrew.cmu.edu/~lea/mti-proposal-2.pdf

Physically Building Virtual Worlds – Proposal

Filed under: Final Project, Joshua Smith — jssmith44 @ 11:53 am

The Concept:A child is given a set of physical scaled Models( Ex: Buildings, Sky Scrapers, Bridges, Monsters, Boats, People, etc)The child can then create their own virtual world by arranging a set of their models within a given square on a table, and their virtual world model is automatically rendered in Google SketchUp for them to explore in more detail.Parts List:

  • Table with Glass Square
  • Camera
  • Scaled Models (either purchased or made from craft material)-
  • Processing Computer
  • Fiducial Stickers

Technical Specifics: The only real hardware component to this project will be a camera and glass table. The rest is mainly software based. A camera will be mounted under the table, facing upwards. Each object will have its own fiducial ( see examples below) sticker on its base, so using the camera… its absolute position and orientation can be registered using an Open-Source Fiducial Recognition Framework. The application will then pass these position and orientation values to a Google SketchUp file preloaded with the coresponding digital models for each physical model. SketchUp will then render the world based on the position and orientation values. There will also be a space in the upper corner of the table, for a child to pick materials. For instance they can put a Grass Square in the upper corner, for the world to be built on grass, or water, etc. The system will completey expandable, so that as long as someone wants to build their own physical model, and corresponding digital model, any environment can be rendered.Fiducial Example: fiducial1I am also considering creating this same model with 3 cameras instead of 1. This would allow the software to recognize not just the absolute position on the x axis, but on the Y and Z as well, so a child could place buildings on top of one another. Below is a basic state diagram:PhysWorld State DiagramSpecific Software List:ProcessingreacTIVisionFrameworkRuby SketchUp APIFurther Down The Road: Rather then just build a snap shot of a Virtual World at one point, children could use this to script and direct their own movies. They could press a record button, and it would record the moving of their boat from point A to B, and then the person getting out of the boat and walking into the building. Add the functionality of recording sound, and they can create some great movies very simply.

vehicle-mounted light-aiming turret

Filed under: Final Project, Gaku Sato — ponkotsu @ 8:07 am

For the final project, I propose a light-chasing application similar to my midterm project (lightchaser).  This time, it will be an auto turret that aims at light.  A 360deg servo will be the base platform onto which the firing mechanism will be mounted.  There will be 4 light sensors affixed at 90degs facing outward.
turret2.pdf

My primary objective is to be able to shoot down various stationary targets from a fixed position (as drawn).  Once that is working accurately and fast enough, my secondary objective is to be able to shoot down moving targets.  Ultimately I will mount the turret on an RC car and shoot down target cars (also RC).If things go magically well, I want to make two of these turret cars which could play Tag by alternating being the light source.  It would alternate when the target car sensed that it had been hit, which I’m not sure how to do, nor do I know how to send that “hit” signal to the chaser car.  So for this I think I would need some type of wireless signal.  I don’t think this would be possible by the end of the semester, so I also had the idea of mounting the turret onto the lightchaser (will be changed to IR lightchaser), and that may be better not only for feasibility, but for entertainment purposes, since it is intended to be a toy.

From working on the lightchaser I know that photoresistor inputs are tricky (especially in calibration when comparing multiple sensor inputs) so I may use pairs of sensors.  Also, a small solenoid is an inadequate firing mechanism, so I will opt for a larger one or a different assembly altogether.

« Previous Page

Blog at WordPress.com.