Making Things Interactive

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

 

Final Project: Light Plant

Filed under: Assignments, Thomas Hendrickson — tphendrickson @ 11:54 am

My last midterm project (the interactive indo board) was cumbersome and hard to set up/transport, so for this project I wanted to make something that was easy to install and simple to set up. I thought of something that could sit in a room that people could interact with but not take up too much room or be too distracting, like an interactive decoration. So my idea was to have something that reflected a plant’s behavior, that would sense light and react.

A photosensor gets a reading of what the light is in the surrounding environment initially, and then calibrates an activation value based on this reading. When the light reaches a value that is higher than the activation value, the servo rotates a fabricated wooden gear and wooden column with a hexagonal top rises. LEDs protruding from the column light up, and the photosensor is at the top, all soldered to longer jumper wires. There are four cases to the code:

Case 1: Light is sensed as above the activation and the column is down.

  • The servo rotates the column up.
  • The LEDs light up.

Case 2: Light is sensed as above the activation value and the column is up.

  • The servo does not rotate.
  • The LEDs stay light.

Case 3: Light is sensed as below the activation value and the column is up.

  • The servo rotates the column down.
  • The LEDs turn off.

Case 4: Light is sensed as below the activation value and the column is down.

  • The servo does not rotate.
  • the LEDs stay off.

Code:


Servo servo1;

int ledPin1 = 13;
int photoPin = 0;
int ledPin2 = 2;
int ledPin3 = 3;
int ledPin4 = 4;
int ledPin5 = 5;
int readIn = 0;
int initialRead = 0;
int activateVal = 0;
int status = 0;

void setup()
{
  Serial.begin(19200);

  servo1.attach(15);
  servo1.setMinimumPulse(800);
  servo1.setMaximumPulse(2000);

  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
  pinMode(photoPin, INPUT);

  blink();     //blinks the status LED
  initialRead = analogRead(photoPin); //gets initial reading for photosensor
  activateVal = (initialRead * 2) + 5;      //the activation value will be double the initial
  blink();

}

void loop()
{
    Servo::refresh();

    readIn = analogRead(photoPin);

    //Case 1: Light Turned On (Servo move up, LEDs on)
    if ((readIn >= activateVal))
    {
      servo1.write(0);
      status = 1;
      digitalWrite(ledPin1, HIGH);
      lightLeds();
    }

    //Case 2: Light Turned Off (Servo move down, LEDs off)
    if ((readIn < activateVal) &amp;amp;&amp;amp; (status == 1))
    {
      servo1.write(90);
      status = 0;
      digitalWrite(ledPin1, LOW);
      turnOffLeds();
    }

    //Case 3: Lighting the same and off (Servo off, LEDs off)
   if ((readIn < activateVal) &amp;amp;&amp;amp; (status == 0))
    {
      status = 0;
      digitalWrite(ledPin1, LOW);
      turnOffLeds();
    }

    //Case 4: Lighting the same and on (Servo off, LEDs on)
    if ((readIn >= activateVal) &amp;amp;&amp;amp; (status == 1))
    {
      status = 1;
      digitalWrite(ledPin1, HIGH);
      lightLeds();
    }

    Servo::refresh();

}

void blink()
{
    digitalWrite(ledPin1, HIGH);
    delay(100);
    digitalWrite(ledPin1, LOW);
    delay(100);

}

void lightLeds()
{
    for (int i = 2; i < 6; i++)
    {
      digitalWrite(i, HIGH);
    }
}

void turnOffLeds()
{
    for (int i = 2; i < 6; i++)
    {
      digitalWrite(i, LOW);
    }
}

The code should read ‘#include ‘ which was an imported package used to code the servo’s rotation.

The wiring before soldering the LEDs and photosensor.

The servo attached to the gear.

The wiring after soldering.

The final product after hiding the hardware.

Parts List:

  • 5 1 kilo ohm resistors
  • 4 LEDs
  • 1 photosensor
  • 1 Hi-Tec Standard Servo
  • Breadboard
  • Arduino
  • Jumper wire
  • Bass wood, PCM board, balsa wood
  • Flowerpot

Here is the youtube link, but I couldn’t rotate the video after it was imported:

April 10, 2008

URBI Studio

Filed under: 1: Post Something Interesting, Gaku Sato — ponkotsu @ 1:51 pm

http://www.gostai.com/studio.html

This is fantastic.  It’s hard to explain.  It’s basically a prototyping framework.  Check it out.

- You can graphically create a state diagram and it’ll convert the logic to code automatically.  Each state/node has code in it to execute and you can obviously set the conditions for state change and such.  All this is dynamic (realtime & pause/resumable) and you can set nodes within nodes.  This executes in exactly the same way it would had you coded all this manually, as I’ve been having to do.
- You can sequence motion graphically as well as record motion for repeat.  Again, code is automatic.  So if you want the camera to pan left<—>right at various speeds, it would be insanely simple.
- You can create a control panel with specified widgets to control things.  This is also dynamic.  You can use a slider gui to manually control a servo or something.
- It also has its own parallel-execution language but it can interface with other programs as in it can be used in conjunction with some other coding structure.

It’s really hard to explain in words.  I met with a guy from URBI that demoed (sp?) it for us using an Aibo and it really made everything from control/actuation to debugging to editing incredibly simple, visible, and IMMEDIATE.

Other logic/control gui programs may already be out there that I totally don’t know about, but this one looked excellent.  If no one else, I really recommend Mark and Jet check it out!

April 9, 2008

Touch-screen OLED for Arduino!

Filed under: Course Materials, References — jet @ 5:00 pm

Ok,  it’s ~ US$100, but still…

<a href=”http://www.liquidware.com”>LiquidWare</a> makes it and the backorder is already in the weeks.

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++;
   }
   */
}
« Previous Page

Blog at WordPress.com.