Making Furniture Interactive

December 17, 2007

Final Project: Pinwheels

Filed under: Final Project,Joe Iloreta — jilore @ 4:38 pm

Abstract:

A kinetic object responds to movement both across its face as well as towards and away from it. Like a simple mechanical pet or a sunflower, it reacts to a body along a path, following one longingly as it passes; it may even show excitement when approached.

With this project I sought to build on skills learned over the semester, and elaborate on the four-state machine practiced earlier in the year, engaging the possibilities of passive, casual movement as interaction with an artifact.

Each pinwheel possesses two ultrasonic rangefinders in order to determine the presence of an object in its field of vision calculating distance of passing objects through each rangefinder, thus allowing it to calculate the angle at which the pinwheel pivots towards the movement.

Poster here

#include // (no semicolon)

int milliSecCounter = 0; // countshow many times we’ve gone through the sendServoAngle() function
int timesThruLoop = 0; //coutns how many times we’ve read for a new angle
int holdDuration = 100; //in milliseconds, stores how long we wait before taking another reading….this is to give the servo enough time to go to the angle
int newestAngle;
int newestDistance;
int valA;
int valB;

int myAngle;
int pulseWidth;

int potPin = 0; // Analog in 0 connected to the potentiometer
int transistorPin = 9; // connected to the base of the transistor for EACH MOTOR
int alphaMotorPin = 9;
int potValue = 0; // value returned from the potentiometer

// ——-IR _ STUFF

// pin values
int ultraSoundSignalLeft = 8; // Ultrasound signal pin
int ultraSoundSignalRight = 7; // Ultrasound signal pin

int val = 0;
int valRight = 0;

int irValA;
int irValB;

int ultrasoundValue = 0;
int ultrasoundValueRight = 0;

int timecount = 0; // Echo counter
int timecountRight = 0; // Echo counter

int ledPin = 13; // LED connected to digital pin 13

int sensorDistance = 100; //distance between sensors, should be in same units (response time) that sensor detects in.
int absDistance;
int maxDistance = 5000; //value to cap detectable distance

// CALC ANGLE
int disLeft; //calculated distance from left sensor
int disRight; //calculated distance from right sensor
int newAngle; //calculated angle from IR readings

int angleSlightLeft = 100; //lower limit angle read to turn the extreme left
int angleMoreLeft = 122; //upper limit angle read to turn the the left
int angleMostLeft = 145;
int angleCenter = 90;
int angleSlightRight = 77; //upper limit angle to read to turn to the right
int angleMoreRight = 55;
int angleMostRight = 32; //upper limit angle read to turn to the far right

int movetoUnits = 128; //values as anaolong input to the servo.
//multiply this value by the values below to obtain analong input to servo

int movetoMostLeft = 7; //degree value of far left angle to move to
int movetoMoreLeft = 6; //degree valeu of left angle to move to
int movetoSlightLeft = 5;
int movetoCenter = 4;
int movetoMostRight = 3; //degree value of right angle to move to
int movetoMoreRight = 2;
int movetoSlightRight =1 ; //degree value of far right angle to move to

//SERVO STUFF ————————
int alphaServoPin = 2;
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
int pulseRange = 2000;

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

int analogValue = 0; // the value returned from the analog sensor
int analogPin = 1; // the analog pin that the sensor’s on

boolean firstTime = true;

// MOTOR VARIABLES
int speedHigh = 150; //designated range for high, med, and low motor speed
int speedMed = 100;
int speedLow = 230;

int farDist = 1400;
int medDist = 400;

// COUNTERS
int holdValuesCounter; //counts how many times the entire loop (all four sensors have been read) has been done
int holdValuesTill; //holds the counter value which decides when to change motor speed and servo position (look elsewhere)

int latentTimeCounter; //counts how many seconods of no movement
int latentTimeLimit; //determines how many seconds of no activity until “sleep” behavior occurs

int count = 1;

// ———————————–

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

// set the transistor pin as output:
pinMode(transistorPin, OUTPUT);
pinMode(ledPin, OUTPUT); // Sets the digital pin as output
Serial.begin(9600);

}

void servoPulse(int servoPin, int myAngle){
pulseWidth = (myAngle*11) + 500;
digitalWrite(servoPin, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(servoPin, LOW);
delay(20);
}

void loop() {

timecount = 0;
timecountRight = 0;
val = 0;
valRight = 0;
ultrasoundValue = 0;
ultrasoundValueRight = 0;

//IR stuff
pinMode(ultraSoundSignalLeft, OUTPUT); // Switch signalpin to output
pinMode(ultraSoundSignalRight, OUTPUT); // Switch signalpin to output

//test every 1000th millisecond
// ENTER if (milliSecCounter

if (milliSecCounter == 0 || milliSecCounter == timesThruLoop*holdDuration){
timesThruLoop++; ///count how many times did we go through loop?
Serial.println(“inloop”);
//if true, read for new angle
valA = readIR(ultraSoundSignalLeft, val, ultrasoundValue, timecount);
valB = readIR(ultraSoundSignalRight, valRight, ultrasoundValueRight, timecountRight);
newestAngle = getAngleSimple( valA, valB );
newestDistance = getSmallestDistance(valA, valB);
// Serial.println(“newestAngle”);
Serial.println(newestAngle);
sendMotor(alphaMotorPin, newestDistance);
}

//else save last angle and let testServoAngle pulse to the next one
testServoAngle(newestAngle);
milliSecCounter = milliSecCounter + 1;
}

//—–INDIVIDUAL FUNCTIONS——————-
// DC MOTOR
void testMotor(){

// read the potentiometer, convert it to 0 – 255:

potValue = analogRead(potPin) / 4;
Serial.println(“POTVALUE”);
Serial.println(potValue);
// use that to control the transistor:
analogWrite(9, potValue);
}

// SERVO FUNCTIONS
void moveServo(int angle){

// SERVO STUFF
//the servo is initialized at the center, record this position, and then move between the two throughout the program

//analogValue = analogRead(analogPin); // read the analog input
//pulse = (angle * 19) / 10 + minPulse; // convert the analog value
// to a range between minPulse
// and maxPulse.
pulse = (angle*2000 ) / 180 + pulseRange;
Serial.println(“ANGLE”);
Serial.println(pulse);

// 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
}
}

void testServo(){

// SERVO STUFF
//the servo is initialized at the center, record this position, and then move between the two throughout the program

//analogValue = 1023;
analogValue = analogRead(analogPin); // read the analog input
pulse = (analogValue * 19) / 10 + minPulse; // convert the analog value
// to a range between minPulse
// and maxPulse.
Serial.println(“ANGLE”);
Serial.println(pulse);
Serial.println(analogValue);
Serial.println(“count”);
Serial.println(count);

// 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
}

}
void testServoAngle (int angle){

// SERVO STUFF
//the servo is initialized at the center, record this position, and then move between the two throughout the program

//analogValue = 1023;
// pulse = analogVal;
// analogValue = analogVal; // read the analog input 0 – 1023

//convert degrees to analogVal inputs (0-1023)
//pulse = (bucketAngle(analogVal)* 19) / 10 + minPulse;

// pulse = (analogValue * 19) / 10 + minPulse; // convert the analog value
// to a range between minPulse
// and maxPulse.

///1. CONVERT ANGLE TO ANALOG 0-1023
pulse = (angle*11) + 500;
//2. CONVERT ANALOG TO PULSE
Serial.println(“Angle is”);
Serial.println(angle);
Serial.println(“PULSE”);
Serial.println(pulse);

// pulse the servo again if rhe refresh time (20 ms) have passed:
while (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
}

}

// IR FUNCTIONS
int readIR(int pinIR, int value, int soundValue, int time){

// Send low-high-low pulse to activate the trigger pulse of the sensor
// ——————————————————————-

digitalWrite(pinIR, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(pinIR, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(pinIR, LOW); // Holdoff

// Listening for echo pulse
// ——————————————————————-

pinMode(pinIR, INPUT); // Switch signalpin to input
value = digitalRead(pinIR); // Append signal value to val
while(value == LOW) { // Loop until pin reads a high value
value = digitalRead(pinIR);

}

while(value == HIGH) { // Loop until pin reads a high value
value = digitalRead(pinIR);
time = time +1; // Count echo pulse time

}
// Writing out values to the serial port
// ——————————————————————-
//
if (time > maxDistance){ time = maxDistance;} //cap max distance if readings too much
soundValue = time; // Append echo pulse time to ultrasoundValue
//

if(time > 0){
digitalWrite(ledPin, HIGH);
}

// Delay of program

delay(200);

return soundValue; // is distance
}

int getAngleSimple(int left, int right){ // funciton outputs degrees
//calc distance, put in a range, then figure angle.

if (abs(left – right) < 5) //qualify a difference between left and right then,calc distance { Serial.println("equal distances"); newAngle = 90; } if (left > right){
absDistance = left – right;
newAngle = 57.3*atan2(absDistance,sensorDistance);
}
if (left < right){ absDistance = right - left; newAngle = 90 + (57.3*atan2(absDistance,sensorDistance)); } // Serial.println ("Angle"); return newAngle; // moveServo(newAngle); // newAngle = 0; } void calcAngle(){ // funciton outputs degrees //calc distance, put in a range, then figure angle. if (abs(disLeft-disRight) < 5) //qualify a difference between left and right then,calc distance { Serial.println("equal distances"); newAngle = 90; } if (disLeft > disRight){
Serial.println(“left greater”);
//calcMotor(disRight); //send shortest distance to determine motor RPMs
absDistance = disLeft – disRight;
////newAngle = 180;
//newAngle = 180 – (57.3*atan2(absDistance,sensorDistance));
newAngle = 57.3*atan2(absDistance,sensorDistance);
//newAngle = 57*atan2(calcAbsDist(disLeft,disRight),sensorDistance);
}
if (disLeft < disRight){ Serial.println("right greater"); //calcMotor(disLeft); //send shortest distance to determine motor RPMs absDistance = disRight - disLeft; ////newAngle = 0; //newAngle = 270 - (57.3*atan2(absDistance,sensorDistance)); newAngle = 90 + (57.3*atan2(absDistance,sensorDistance)); //newAngle = 90 + 57*atan2(calcAbsDist(disRight,disLeft),sensorDistance); } Serial.println ("Angle"); Serial.println (newAngle); // moveServo(newAngle); // newAngle = 0; } int calcClosest(int left, int right){ if (left > right){ return left;}
else if (left < right) {return right;} else { return left; } } int calcAbsDist( int x, int y){ absDistValue = x - y; return absDistValue; } void sendServo (int pinServo, int angle){ //the servo is initialized at the center, record this position, and then move between the two throughout the program analogValue = analogRead(analogPin); //test to read from analog potentiometer //analogValue = bucketAngle(angle); // read the analog input pulse = (analogValue * 19) / 10 + minPulse; // convert the analog value // to a range between minPulse // and maxPulse. Serial.println("ANGLE"); Serial.println(analogValue); // pulse the servo again if rhe refresh time (20 ms) have passed: while (millis() - lastPulse >= refreshTime) {
digitalWrite(pinServo, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(pinServo, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}

}

int bucketAngle(int z){ //convert raw angle into generalized angle
if (z <= angleMostRight){ z = movetoMostRight;} if (z > angleMostRight && z <= angleMoreRight){ z = movetoMoreRight;} if (z > angleMoreRight && z <= angleSlightRight){ z = movetoSlightRight;} if (z > angleSlightRight && z<= angleSlightLeft){ z = movetoCenter;} if (z > angleSlightLeft && z<= angleMoreLeft){ z = movetoSlightLeft;} if (z > angleMoreLeft && z<= angleMostLeft){ z = movetoMoreLeft;} if (z > angleMostLeft){ z = movetoMostLeft;}

z = z*movetoUnits; //z*128 = analog input to servo

return z;
}

void sendMotor (int pinMotor, int distance){
Serial.println(“in send motor”);
if (distance > farDist){ potValue = speedHigh;}
if (distance > medDist && distance <= farDist){ potValue = speedMed;} if (distance < medDist){ potValue = speedLow;} analogWrite(pinMotor, potValue); } int getSmallestDistance (int a, int b){ if (a > b) {return a;}
if (a < b) { return b;} if ( a == b){return a;} }[/sourcecode]

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: