Showing posts with label In-Class Project 3. Show all posts
Showing posts with label In-Class Project 3. Show all posts

Monday, October 5, 2009

Here Comes The Sun: Processing Code

As promised, though a little late, here is the Processing code.

// The Import Libraries
import netscape.javascript.*;
import java.util.Calendar.*;
import java.lang.Math.*;
import processing.serial.*;

// Variables Galore
int Hour = hour();
int Min = minute();
int Sec = second();
int doy = 0;
float latitude = (float)Math.toRadians(42.220); // Ann Arbor
float longitude = 83.75; // Ann Arbor
float YrFract = 0;
float eqtime = 0;
float decl = 0;
float time_offset = 0;
float tst = 0;
float ha = 0;
float za = 0;
float azim = 0;
float alt = 0;
int azimswitch=0;

int spos=0;
int wpos=0;

Serial port; // The serial port

void setup()
{
port = new Serial(this, Serial.list()[0], 9600); // Open the serial port.
azimswitch=0; // Make sure the switch is zeroed.
}

void draw()
{
Calendar cal = Calendar.getInstance();
doy = cal.get(Calendar.DAY_OF_YEAR);
Hour = hour();
Min = minute();
Sec = second();
YrFract = 2*PI/365*(doy-1+(Hour-12)/24); // Fractional Year, Radians
eqtime = 229.18*(0.000075+0.001868*cos(YrFract)-0.032077*sin(YrFract)-0.014615*cos(2*YrFract)-0.040849*sin(2*YrFract)); // Equation of Time, Minutes
decl = 0.006918-0.399912*cos(YrFract)+0.070257*sin(YrFract)-0.006758*cos(2*YrFract)+0.000907*sin(2*YrFract)-0.002697*cos(3*YrFract)+0.00148*sin(3*YrFract); // Declination, Radians
time_offset = eqtime-4*longitude+60*5; // Solar Time Offset, Minutes
tst = Hour*60+Min+Sec/60+time_offset; // True Solar Time, Minutes
ha = (float)Math.toRadians((tst/4)-180); // Solar Hour Angle, Radians
za = acos(sin(latitude)*sin(decl)+cos(latitude)*cos(decl)*cos(ha)); // Zenith Angle, Radians
azim = acos(-(sin(latitude)*cos(za)-sin(decl))/(cos(latitude)*sin(za))); // Azimuth, Radians, Clockwise from North
azim = (int)(float)Math.toDegrees(azim);

// Utilize a switching process to determine if it is before or after zenith.
if (azimswitch==0){
azim = azim - 90;
}
else if (azimswitch==1){
azim = 270 - azim;
}

// Change switch when necessary.
if ((int)azim==90){
azimswitch = 1;
}
else if ((int)azim==180){
azimswitch = 0;
}

alt = (float)(Math.toDegrees(za)); // Calculate altitude from Zenith Angle

// Print out to check whether or not calculations are correct.
println(alt);
println(azim);
println(azimswitch);

// Stop the machine from turning too far.
if((int)azim < azim =" 0;"> 180){
azim = 180;
}

alt = alt/2; // Mirror-aiming correction

update((int)alt,180-(int)azim); // Run the update to write to the servo.

delay(1000); // Only read once a second.
}

void update(int spos, int wpos)
{
//Output the servo position ( from 0 to 180)
port.write(spos+"s");
port.write(wpos+"w");
}
Took awhile to write, but it works well. I also had a gimmicky little touchpad controller code:

/**
* Servocontrol (derived from processing Mouse 1D example.)
*
* Updated 24 November 2007
*/


// Use the included processing code serial library
import processing.serial.*;


int gx = 15;
int gy = 35;
int spos=90;
int wpos=90;

float leftColor = 0.0;
float rightColor = 0.0;
Serial port; // The serial port



void setup()
{
size(720, 720);
colorMode(RGB, 1.0);
noStroke();
rectMode(CENTER);
frameRate(100);

println(Serial.list()); // List COM-ports

//select second com-port from the list
port = new Serial(this, Serial.list()[0], 9600);
}

void draw()
{
background(0.0);
update(mouseX,mouseY);
fill(mouseX/4);
rect(150, 320, gx*2, gx*2);
fill(180 - (mouseX/4));
rect(450, 320, gy*2, gy*2);
}

void update(int x, int y)
{
//Calculate servo postion from mouseX
spos= x/4;
wpos= y/4;

//Output the servo position ( from 0 to 180)
port.write(spos+"s");
port.write(wpos+"w");
// Just some graphics
leftColor = -0.002 * x/2 + 0.06;
rightColor = 0.002 * x/2 + 0.06;

gx = x/2;
gy = 100-x/2;

}
I'll post information on the two-week project soon.

Thursday, October 1, 2009

Here Comes The Sun

Our team project for the week was to design and implement a modular, scalable solar tracker.

The project started out the same way that last week's project did - I stepped into coding like it is my true calling or something. The sun follows a path defined by two variables - azimuth and altitude. Therefore, we developed a design very similar to the design that Eric's group and my group both utilized last week, with two axes - rotation and tilt. We chose to utilize the base scheme that his group developed, as it was much more stable and easier to work with for this implementation.

The Arduino code for our project is as follows:

#include
#include

Servo servo1; Servo servo2;
Potentiometer potentiometer1 = Potentiometer(3);
Potentiometer potentiometer2 = Potentiometer(4);

void setup() {
servo1.attach(9);
servo2.attach(10);
pinMode(13,OUTPUT);
Serial.begin(9600);
Serial.println("Ready");
potentiometer1.setSectors(180);
potentiometer2.setSectors(180);
}

void loop() {

static int v = 0;
if (Serial.available()) {
char ch = Serial.read();

switch(ch) {
case '0'...'9':
v = v * 10 + ch - '0';
digitalWrite(13,LOW);
break;
case 's':
servo1.write(v);
v = 0;
break;
case 'w':
servo2.write(v);
v = 0;
break;
case 'p':
do{
servo1.write(potentiometer1.getSector());
servo2.write(potentiometer2.getSector());
digitalWrite(13,HIGH);
}
while(Serial.read()!='i');
break;
}
}
}

It allows for both serial input and potentiometer utilization to control the servos. Really quite simple, but it does so much. I prefer to have the Arduino as simple as possible whenever possible, and to utilize the computer to do any real processing and calculations. Therefore, the remainder of the code was written in Processing. Here is a snippet from the Processing code.

YrFract = 2*PI/365*(doy-1+(Hour-12)/24); // Fractional Year, Radians
eqtime = 229.18*(0.000075+0.001868*cos(YrFract)-0.032077*sin(YrFract)-0.014615*cos(2*YrFract)-0.040849*sin(2*YrFract)); // Equation of Time, Minutes
decl = 0.006918-0.399912*cos(YrFract)+0.070257*sin(YrFract)-0.006758*cos(2*YrFract)+0.000907*sin(2*YrFract)-0.002697*cos(3*YrFract)+0.00148*sin(3*YrFract); // Declination, Radians
time_offset = eqtime-4*longitude+60*5; // Solar Time Offset, Minutes
tst = Hour*60+Min+Sec/60+time_offset; // True Solar Time, Minutes
ha = (float)Math.toRadians((tst/4)-180); // Solar Hour Angle, Radians
za = acos(sin(latitude)*sin(decl)+cos(latitude)*cos(decl)*cos(ha)); // Zenith Angle, Radians
azim = acos(-(sin(latitude)*cos(za)-sin(decl))/(cos(latitude)*sin(za))); // Azimuth, Radians, Clockwise from North

This code is the calculation for solar position, given inputs (doy is day of year, the rest is fairly self-explanatory). The azimuth is always positive, so a switch in the code must be utilized to switch between rising and setting. I'll post the full code on Friday morning at the start of class, it's not 100% yet.

I feel like this team has meshed the best out of all the teams that I have worked with so far. Neil and I worked on the electronics portion, and we work very well together. The design process was universal, with everyone inputting, but the implementation process essentially was niche, with engineers doing circuitry and coding, architects doing Schmigital Schmroject and some construction, and artists doing construction. Overall, the project has worked really well, and I look forward to the final result.

Wednesday, September 30, 2009

SmartSurfaces, Day Three, 9/25

Day Three wasn't really anything substantial in-class. We did more work with Schmigital Schmroject, showed off our (extremely neat) light tracker, and that's about it. However, we were assigned an out-of-class project to create a solar tracker. I will not be discussing this project in detail until Thursday or Friday. I will say that we are not using light sensitivity, but instead are using a predetermined equation.

I will say that I still think that Schmigital Schmroject is extremely clumsy, unintuitive, poorly designed, and overall not a quality program for use in the student environment.