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
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; (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; (status == 0))
{
status = 0;
digitalWrite(ledPin1, LOW);
turnOffLeds();
}
//Case 4: Lighting the same and on (Servo off, LEDs on)
if ((readIn >= activateVal) &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:
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!
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:
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++;
}
*/
}