Tuesday, February 16, 2010
Thursday, February 11, 2010
Saturday, February 6, 2010
ScanTer Experiments 3
In this last piece of code (which went through a lot of debugging) we finally managed to crack a lot of problems we had in the past examples. Basically all you need to do is run the code in processing after uploading the firmata code (from the arduino library) to the arduino board.
Next step is to draw or write something -> the result, after pressing ENTER, is the initial input.
Here is the fully commented script:
/*
Dessau Institute of Architecture - WS09
The ScanTer
This script is ment to control/link processing with the arduino board in order to control the motion of a RCTank
The user gets to choose between a square and a circle. once he made his choice, the tank starts performing that particular shape.
Created 27 January 2010
By Pula_Team; Tudor Cosmatu & Grygorii Zotov
based, more or less, on the arduino "Blink" example
*/
//import the serial function
import processing.serial.*;
//import the arduino library
import cc.arduino.*;
Arduino arduino;
//declare the pin number
int LFPin = 5;
int RFPin = 4;
//declare the 2D array which stores the data from the IRpen movement
float[][] Small = new float[1000][5];
//previous previous x and y pos
float ppx = width/2;
float ppy = height/2;
//declare counter
int counter = 0;
void setup(){
size(800,800);
background(0);
//set FrameRate -> changing this will result in a malfunction of the tanks movement
frameRate(20);
//set the arduino
println(Arduino.list());
arduino = new Arduino(this, Arduino.list()[0], 57600);
//setting up the pins as outputs
arduino.pinMode(LFPin, Arduino.OUTPUT);
arduino.pinMode(RFPin, Arduino.OUTPUT);
}
void draw(){
//if mouse is pressed then do the rest
if (mousePressed ==true){
//this allows a maximum of 1000 control points
if (counter < 999){
// declare the x and y values - IRpen
float x = mouseX;
float y = mouseY;
// declare the previous x and y positions of the IRpen
float px = pmouseX;
float py = pmouseY;
//if px and py are not equal to x and y, then do the rest (if px=x and py=y the resulting movement has to suffer from it since when keeping the IRpen in the same position for too long the resulting vectors are null)
// generally skipping the null vectors
if (px!=x || py!=y){
stroke (255);
line(px, py, x, y);
//setting boolean values for motion
int lfPinA = 1;
int rfPinA = 1;
//setting the initial delay to 0
float del = 0;
//the distance between two points helps setting the delay for straight movement (forward)
float distance = dist (px, py, x, y);
// for this specific RCtank the value needs to be increased (therefore whenever replacing the RCtank a new calibration process needs to happen)
del = distance*8;
//storing data to the list
Small[counter][0]= lfPinA;
Small[counter][1]= rfPinA;
Small[counter][2]= del;
Small[counter][3]= x;
Small[counter][4]= y;
//creating 3 vectors for calculating the rotation
PVector v0, v1, v2;
//0 vector -> all angle calculations are made according to this vector
v0 = new PVector(0, 1);
v2 = new PVector(x-px, y-py);
v1 = new PVector(px-ppx, py-ppy);
//calculating the angle between the vectors in order to set the correct delay for the motors (1st and then 2nd one)
float L1 = PVector.angleBetween(v0, v1);
L1 = degrees(L1);
float L2 = PVector.angleBetween(v0, v2);
L2 = degrees(L2);
//some math in order to set the correct turning direction
if ((px-ppx)<0){
L1 = -L1;
}
if ((x-px)<0){
L2 = -L2;
}
// sum of the angles
float L = 360-L1+L2;
if (L>360){
L=L-360;
}
// check angles
//println ("WWW");
//println (L);
//left and right turns
if (L < 180){
L = L;
lfPinA = 0;
rfPinA = 1;
del = (1500/180)*L;
}
if (L>180){
L=360-L;
lfPinA = 1;
rfPinA = 0;
del = (1500/180)*L;
}
//print delay value
//println (del);
//store the above in the list
Small[counter+1][0]= lfPinA;
Small[counter+1][1]= rfPinA;
Small[counter+1][2]= del;
counter = counter+2;
//set the previous x and y pos to previous previous x and y pos and start the loop over
ppx = px;
ppy = py;
}
}
}
}
//set the counter to skip first 2 steps
int a=2;
void keyPressed(){
//if enter is pressed he is continuing with the next loop (if not, the tank performs a circular motion in the control last point)
if (keyCode == ENTER) {
while (Small[a][0]>0 || Small[a][1]>0 || Small[a][2]>0){
//create visible dots for previewing the steps
fill(255);
ellipseMode(CENTER);
ellipse(Small[a][3],Small[a][4],5,5);
// Both motors ON
if (Small[a][0] == 1 && Small[a][1] == 1){
arduino.digitalWrite(LFPin, Arduino.HIGH); // set the motor on
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the motor on
delay(int(Small[a][2]));
}
// Left motor OFF
if (Small[a][0] == 0 && Small[a][1] == 1){
arduino.digitalWrite(LFPin, Arduino.LOW); // set the motor off
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the motor on
delay(int(Small[a][2]));
}
// Right motor OFF
if (Small[a][0] == 1 && Small[a][1] == 0){
arduino.digitalWrite(LFPin, Arduino.HIGH); // set the motor on
arduino.digitalWrite(RFPin, Arduino.LOW); // set the motor off
delay(int(Small[a][2]));
}
// Both motors OFF
if (Small[a][0] == 0 && Small[a][1] == 0){
arduino.digitalWrite(LFPin, Arduino.LOW); // set the motor off
arduino.digitalWrite(RFPin, Arduino.LOW); // set the motor off
delay(int(Small[a][2]));
}
a=a+1;
}
}
//after the Enter loop finishes stop both motors
arduino.digitalWrite(LFPin, Arduino.LOW);
arduino.digitalWrite(RFPin, Arduino.LOW);
}
Videos and images will follow...
Next step is to draw or write something -> the result, after pressing ENTER, is the initial input.
Here is the fully commented script:
/*
Dessau Institute of Architecture - WS09
The ScanTer
This script is ment to control/link processing with the arduino board in order to control the motion of a RCTank
The user gets to choose between a square and a circle. once he made his choice, the tank starts performing that particular shape.
Created 27 January 2010
By Pula_Team; Tudor Cosmatu & Grygorii Zotov
based, more or less, on the arduino "Blink" example
*/
//import the serial function
import processing.serial.*;
//import the arduino library
import cc.arduino.*;
Arduino arduino;
//declare the pin number
int LFPin = 5;
int RFPin = 4;
//declare the 2D array which stores the data from the IRpen movement
float[][] Small = new float[1000][5];
//previous previous x and y pos
float ppx = width/2;
float ppy = height/2;
//declare counter
int counter = 0;
void setup(){
size(800,800);
background(0);
//set FrameRate -> changing this will result in a malfunction of the tanks movement
frameRate(20);
//set the arduino
println(Arduino.list());
arduino = new Arduino(this, Arduino.list()[0], 57600);
//setting up the pins as outputs
arduino.pinMode(LFPin, Arduino.OUTPUT);
arduino.pinMode(RFPin, Arduino.OUTPUT);
}
void draw(){
//if mouse is pressed then do the rest
if (mousePressed ==true){
//this allows a maximum of 1000 control points
if (counter < 999){
// declare the x and y values - IRpen
float x = mouseX;
float y = mouseY;
// declare the previous x and y positions of the IRpen
float px = pmouseX;
float py = pmouseY;
//if px and py are not equal to x and y, then do the rest (if px=x and py=y the resulting movement has to suffer from it since when keeping the IRpen in the same position for too long the resulting vectors are null)
// generally skipping the null vectors
if (px!=x || py!=y){
stroke (255);
line(px, py, x, y);
//setting boolean values for motion
int lfPinA = 1;
int rfPinA = 1;
//setting the initial delay to 0
float del = 0;
//the distance between two points helps setting the delay for straight movement (forward)
float distance = dist (px, py, x, y);
// for this specific RCtank the value needs to be increased (therefore whenever replacing the RCtank a new calibration process needs to happen)
del = distance*8;
//storing data to the list
Small[counter][0]= lfPinA;
Small[counter][1]= rfPinA;
Small[counter][2]= del;
Small[counter][3]= x;
Small[counter][4]= y;
//creating 3 vectors for calculating the rotation
PVector v0, v1, v2;
//0 vector -> all angle calculations are made according to this vector
v0 = new PVector(0, 1);
v2 = new PVector(x-px, y-py);
v1 = new PVector(px-ppx, py-ppy);
//calculating the angle between the vectors in order to set the correct delay for the motors (1st and then 2nd one)
float L1 = PVector.angleBetween(v0, v1);
L1 = degrees(L1);
float L2 = PVector.angleBetween(v0, v2);
L2 = degrees(L2);
//some math in order to set the correct turning direction
if ((px-ppx)<0){
L1 = -L1;
}
if ((x-px)<0){
L2 = -L2;
}
// sum of the angles
float L = 360-L1+L2;
if (L>360){
L=L-360;
}
// check angles
//println ("WWW");
//println (L);
//left and right turns
if (L < 180){
L = L;
lfPinA = 0;
rfPinA = 1;
del = (1500/180)*L;
}
if (L>180){
L=360-L;
lfPinA = 1;
rfPinA = 0;
del = (1500/180)*L;
}
//print delay value
//println (del);
//store the above in the list
Small[counter+1][0]= lfPinA;
Small[counter+1][1]= rfPinA;
Small[counter+1][2]= del;
counter = counter+2;
//set the previous x and y pos to previous previous x and y pos and start the loop over
ppx = px;
ppy = py;
}
}
}
}
//set the counter to skip first 2 steps
int a=2;
void keyPressed(){
//if enter is pressed he is continuing with the next loop (if not, the tank performs a circular motion in the control last point)
if (keyCode == ENTER) {
while (Small[a][0]>0 || Small[a][1]>0 || Small[a][2]>0){
//create visible dots for previewing the steps
fill(255);
ellipseMode(CENTER);
ellipse(Small[a][3],Small[a][4],5,5);
// Both motors ON
if (Small[a][0] == 1 && Small[a][1] == 1){
arduino.digitalWrite(LFPin, Arduino.HIGH); // set the motor on
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the motor on
delay(int(Small[a][2]));
}
// Left motor OFF
if (Small[a][0] == 0 && Small[a][1] == 1){
arduino.digitalWrite(LFPin, Arduino.LOW); // set the motor off
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the motor on
delay(int(Small[a][2]));
}
// Right motor OFF
if (Small[a][0] == 1 && Small[a][1] == 0){
arduino.digitalWrite(LFPin, Arduino.HIGH); // set the motor on
arduino.digitalWrite(RFPin, Arduino.LOW); // set the motor off
delay(int(Small[a][2]));
}
// Both motors OFF
if (Small[a][0] == 0 && Small[a][1] == 0){
arduino.digitalWrite(LFPin, Arduino.LOW); // set the motor off
arduino.digitalWrite(RFPin, Arduino.LOW); // set the motor off
delay(int(Small[a][2]));
}
a=a+1;
}
}
//after the Enter loop finishes stop both motors
arduino.digitalWrite(LFPin, Arduino.LOW);
arduino.digitalWrite(RFPin, Arduino.LOW);
}
Videos and images will follow...
Wednesday, February 3, 2010
ScanTer Experiments 2
The ScanTer from Tudor Cosmatu on Vimeo.
The next step after establishing the vital "communication" with the arduino board through the arduino software was to manage to get processing to work with the arduino board.
After numerous failed attempts to do so, we finally came across some very usefull sites and informations (with a little help from our friends).
Therefore here they are:
http://www.arduino.cc/playground/Interfacing/Processing
http://robot-overlord.blogspot.com/2009/04/arduinoprocessing-tutorial.html
http://itp.nyu.edu/physcomp/Tutorials/Tutorials
http://www.dannyg.com/examples/res2/resistor.htm
There were also some failed attempts in trying to communicate with the arduino through the messenger library from the arduino.cc site.
And here a small abstract of what it actually exists for:
Messenger is a "toolkit" that facilitates the parsing of ASCII messages. Messenger processes characters until it receives a carriage return (CR). It then considers the message complete and available. The message is split into many elements as defined by a separator. The default separator is the space character, but can be any character other than NULL, LF or CR.
In order to make processing work with the arduino board all you need to do is load the firmata example, from arduino, to the arduino board, and then write this code in processing:
/*
Dessau Institute of Architecture - WS09
The ScanTer
This script is ment to control/link processing with the arduino board in order to control the motion of a RCTank
The user gets to choose between a square and a circle. once he made his choice, the tank starts performing that particular shape.
Created 27 January 2010
By Pula_Team; Tudor Cosmatu & Grygorii Zotov
based, more or less, on the arduino "Blink" example
*/
//import the serial function
import processing.serial.*;
//import the arduino library
import cc.arduino.*;
Arduino arduino;
//declare the pin number
int LFPin = 5;
int RFPin = 4;
int var = 0;
//declare the PImage
PImage b;
void setup() {
size(1000, 1000);
//load the PImage
b = loadImage("PulaTank.jpg");
//Set the arduino
println(Arduino.list());
arduino = new Arduino(this, Arduino.list()[0], 57600);
//declare the pinMode for the pins that are going to be used
arduino.pinMode(LFPin, Arduino.OUTPUT);
arduino.pinMode(RFPin, Arduino.OUTPUT);
}
void draw() {
background(0);
stroke(155);
noFill();
rectMode(CENTER);
rect(width/4, height/2,width/3, width/3);
ellipseMode(CENTER);
ellipse((width*3)/4, height/2, width/3, width/3);
}
void mousePressed()
{
if (mouseX
//insert this image when mouse is pressed
image(b,width/4-100, height/2-85);
// and move the tank in a square
while (var<3){
//set both motors on
arduino.digitalWrite(LFPin, Arduino.HIGH);
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the LED off
//unfortunately since the delay gets called within the draw function, the whole application has quite a lag
delay(700);
//turn off one of the motors so that the tank turns slightly
arduino.digitalWrite(LFPin, Arduino.LOW);
delay(350);
var++;
}
//turn off the right motor
arduino.digitalWrite(RFPin, Arduino.LOW);
//var gets reset to 0 so that the whole operation can be re-done
var = 0;
}
else{
//insert this image when mouse is pressed
image(b,(width*3)/4-100, height/2-60);
// and move the tank in a square
while (var<28){
//set both motors on
arduino.digitalWrite(LFPin, Arduino.HIGH);
arduino.digitalWrite(RFPin, Arduino.HIGH); // set the LED off
//unfortunately since the delay gets called within the draw function, the whole application has quite a lag
delay(100);
//turn off one of the motors so that the tank turns slightly
arduino.digitalWrite(RFPin, Arduino.LOW);
arduino.digitalWrite(LFPin, Arduino.HIGH);
delay(50);
var++;
}
//turn off the left motor
arduino.digitalWrite(LFPin, Arduino.LOW);
//var gets reset to 0 so that the whole operation can be re-done
var = 0;
}
}
We took the time to comment everything (so that it's all clear)
By having done this step we're slowly but surely moving towards coding the last bits and pieces for the whole process to become (more or less) real-time.
The hardware problem we have is already visible. As we were mentioning in previous posts the motors of the tank don t have the same speed...
To be continued....
Subscribe to:
Posts (Atom)