Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
11 views

Arduino Code

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Arduino Code

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

ARDUINO CODE

#include <Servo.h>
#include <math.h>

//Servo[0]=TopArm
//Servo[1]=MiddleArm
//Servo[2]=Grip

Servo servo[3];

// setup Pins
const int servo_Pin[] = {6, 7, 4}; //top,middle,grip
//const int servoGrip_val[]= {145,105,145}; //open/max, close/min, default
const int servoGrip_val[]= {170,125,170}; //open/max, close/min, default
const int stepper_dirPin[] = {8};
const int stepper_stepPin[] = {9};

// servo Angles
double angle_current[] = {90, 90, 145};
double angle_next[] = {90, 90, 145};

// starting arm Coordinates


const double XYZ_base[] = {0, 0, -6, 1, 0, 0, 1}; //x,y,z, bool_move, bool_open, delay_to_next,
type_of_action
double XYZ_current[] = {0, 0, -9, 1, 0, 1}; //x,y,z, bool_move, bool_open, delay_to_next,
type_of_action
double XYZ_next[] = {0, 0, -9, 1, 0, 1}; //x,y,z, bool_move, bool_open, delay_to_next, type_of_action

// operating Constraints
const int stepper_delay[] = {27 * 28}; // 27 for sixteen, 27*22 for full step
const int stepper_maxsteps[] = {4000};
const double STEPS_PER_CM[] ={50.335}; //1500 total travel steps for ~29.8 cm = 50.335 steps per
cm
double stepper_correction[]={0};

// make sure that the servo angle position, correctly translates to the trigonometric formulas of the
arm position (see docs)
// set the servo to 90 degress, then measure the real angle of the arm.
// the calibration value is (90 - {position of arm vs reference at servo 90}), which then helps all values
translate to sevo position.
const double calibrate_TopArm=90-35.7;
const double calibrate_MiddleArm=90-41.4;
//compensate for Grip Height (vs. middle arm end) on Z-axis
const double calibrate_Z=8.5;

// communication
const byte numChars = 32;
char receivedChars[numChars];

boolean newData = false;

void setup() {

// Setup Communication
Serial.begin(9600);
//Serial.println("#====# Setup Start #====#");
Serial.println("start");

// Setup Pin Modes


pinMode(stepper_dirPin[0], OUTPUT);
pinMode(stepper_stepPin[0], OUTPUT);
int i = 0;
for (i = 0; i < 3; i++) {
pinMode(servo_Pin[i], OUTPUT);
}

// Setup initial Servo Angles


//for(i=0; i<2; i++) { servo[i].write(90); angle_current[i]=90; }
servo[2].write(servoGrip_val[2]); angle_current[2] = servoGrip_val[2];
// Set Coordinates a Base
int y = 0;
int z = -6;
coordinate_move(0, y, z, false);

// setup servos
for (i = 0; i < 3; i++) {
servo[i].attach(servo_Pin[i], 500, 2500);
}

//=========run tests (make sure to set "loop" bolean to false)


//test_stepper();
//test_servo(0);
//test_servo(1);
//test_servo(2);
//test_servo_home(0);
//test_servo_home(1);
//test_servo_home(2);
//test_getangles(-5,-20); free-movement
//test_getangles(5,-20);
//test_getangles(-5,-9);
//test_getangles(5,-9);
//test_getangles(0,-13);

//coordinate_move(0,-9,0);
//delay(500);50
//coordinate_move(0, y, 0, false);
//delay(500);

//Serial.println("#====# Arduino Ready #====#");


Serial.println("ready");

void loop() {

// put your main code here, to run repeatedly:


bool loop=true;

recvWithStartEndMarkers();
showNewData();
//delay(5000);

//data format <x,y,z,bool_move,bool_open,delayms,type_int> = <23,56,89,1,1,3456,3> {17}


//X: 7.00 Y: 8.00 Z: 9.00 bool_move: 1.00 bool_open: 0.00 delay_ms: 10.00 move_type: 1.00

//the bool_move controls if the arm moves linearly to the position or performs a pick/grab motions
(move x first/y second etc)

//<0,0,-9,1,1,1>

if (newData==true && loop==true) {


coordinate_move(XYZ_next[0],XYZ_next[1],XYZ_next[2],XYZ_next[3]);
servo_Open(XYZ_next[4]);
delay(XYZ_next[5]);
newData=false;
Serial.println("done");
}

void get_angles_from_yz(double y, double z) {

//refer to trigonometry illustration for variable description

double H, s1, s2, aB, aA, aQ, servo1angle, servo2angle, y2, z2, y3, z3;

//arm length in cm
int L = 13;
H= sqrt (pow(y,2) + pow(z,2));
s1=H/2;
s2=sqrt (pow(L,2) - pow(s1,2));

aB=atan(s2/s1);
y2=y/2;
z2=z/2;
aA=atan(y2/z2);

servo1angle=aA+aB;
servo1angle= (servo1angle/ (2 * M_PI)) * 360;

//matrix multiplication - counterclockwise rotation


y3 = -L*sin(aA+aB);
z3 = -L* cos(aA+aB);

servo2angle=atan((y-y3)/(z-z3));

servo2angle= (servo2angle / (2 * M_PI)) * 360;


//tangent calculation changes when servo2 exceeds 90 degrees, correction below
if ((z-z3)>0) {
servo2angle=servo2angle-180;
}

//Absolute Top Arm Angle


//Top Arm moves 0 to +90
angle_next[0] = servo1angle;

//Absolute Middle Arm Angle


//Midle Arm moves 0 to +90
angle_next[1] = -servo2angle;

//Convert to SERVO Angle


//in this case, a 90 servo position is equal to 71 degrees for Top arm
//90 servo position is equal to 65 Middle Arm
angle_next[0] = angle_next[0] + calibrate_TopArm;
angle_next[1] = angle_next[1] + calibrate_MiddleArm;

void coordinate_move(double xEnd, double yEnd, double zEnd, bool liftgrab_motion) {

double xStart = XYZ_current[0];


double yStart = XYZ_current[1];
double zStart = XYZ_current[2];
//Serial.println("/ Coord Move Start /");

//calibrate stepper steps into cms (for x axis)

double x_to_steps = STEPS_PER_CM[0];

//identify if there is movement in the y Axis


double zDelta = zEnd - zStart;
//identify if there is movement in the z Axis
double xDelta = xEnd - xStart;

double x_stepper_steps = x_to_steps * abs(xDelta);

if (xDelta != 0) {
if (xDelta > 0) {
stepper_advance(0, x_stepper_steps, 0);
} else {
stepper_advance(0, x_stepper_steps, 1);
}
}

//the liftbrab_motion bool is equivalent to the bool_move paramter


// controls if the arm moves linearly to the position or performs a pick/grab motions (move Y first/z
second etc)

if (liftgrab_motion == true) {
if (zDelta < 0) {
//arm is going to move down, move Y first

// move arms in Y direction


get_angles_from_yz(yEnd, zStart);
twoarm_step_coordinate(angle_next[0], angle_next[1]);

// move arms in Z direction


get_angles_from_yz(yEnd, zEnd);
twoarm_step_coordinate(angle_next[0], angle_next[1]);

} else {
//arm is moving up, perform Y movement first.

// move arms in Z direction


get_angles_from_yz(yStart, zEnd);
twoarm_step_coordinate(angle_next[0], angle_next[1]);

// move arms in Y direction


get_angles_from_yz(yEnd, zEnd);
twoarm_step_coordinate(angle_next[0], angle_next[1]);
}

} else {
get_angles_from_yz(yEnd, zEnd);
twoarm_step_coordinate(angle_next[0], angle_next[1]);
}

//Serial.println("/ Coord Move End /");

//Serial.println(" //////// ");


//Serial.print(" xStart= "); Serial.print(xStart); Serial.print(" yStart= "); Serial.println(yStart);
//Serial.print("Angle Top Arm="); Serial.print(angle_TopArm); Serial.print(" Angle Middle Arm= ");
Serial.println(angle_MiddleArm);
//Serial.print("Angle Top Arm_next="); Serial.print(angle_TopArm_next); Serial.print(" Angle Middle
Arm_next= "); Serial.println(angle_MiddleArm_next);
//Serial.print(" xEnd= "); Serial.print(xEnd); Serial.print(" yEnd= "); Serial.println(yEnd);

XYZ_current[0] = xEnd;
XYZ_current[1] = yEnd;
XYZ_current[2] = zEnd;
XYZ_current[3] = liftgrab_motion;
}

void stepper_advance(int stepper_num, double steps, int dir) {

// generates the pulso for the Pololu controller to move the stepper.
// this is helpful, given the delay has to change if you want to modifiy your stepper to operate at
Full/Half steps etc.

// check to see if a full step needs to be corrected


if (abs(stepper_correction[stepper_num]) > 1) {
if (stepper_correction[stepper_num]>1){
//add one steps if correction is >1
//steps++;
//remove that step from the correction log
//stepper_correction[stepper_num]--;
} else {
//steps--;
//stepper_correction[stepper_num]++;
}
}

// set direction
if (dir == 0) {
digitalWrite(stepper_dirPin[stepper_num], HIGH);
} else {
digitalWrite(stepper_dirPin[stepper_num], LOW);
}

// send pulse signal to stepper


while (1) {
digitalWrite(stepper_stepPin[stepper_num], HIGH);
delayMicroseconds(stepper_delay[stepper_num]);

digitalWrite(stepper_stepPin[stepper_num], LOW);
delayMicroseconds(stepper_delay[stepper_num]);

steps--;
if (steps < 1) break;
}

// accumulate correction on the remainder of steps to avoid de-calibration


if (steps > 0 && steps <1) {
if (dir ==0) {
stepper_correction[stepper_num]+=steps;
} else {
stepper_correction[stepper_num]-=steps;
}
}

Serial.print("Stepper Remainder ");


Serial.println(stepper_correction[stepper_num]);

void servo_steps(int servo_num, double angle_target, double incr_step = 10, int step_delay = 50) {
// Using LD-20MG Servos with an Arduino Mega 2560, they only work smoothly on maximum 25
degree instructions at a time.
// I haven't debugged the hardware, but this functions solves the issue.

// This function helps you send commands to servos to move in a set of degrees at at a time.

int set_angle;
int angle_start = angle_current[servo_num];

if (angle_start > angle_target) {


//start from angle_start, and then move the servo by incr_steps into the angle_target
//stepping down to target
for (set_angle = angle_start; set_angle >= angle_target; set_angle -= incr_step) {
servo[servo_num].write(set_angle);
//Serial.println(set_angle);
delay(step_delay);
}
} else {
//stepping up to target
for (set_angle = angle_start; set_angle <= angle_target; set_angle += incr_step) {
servo[servo_num].write(set_angle);
//Serial.println(set_angle);
delay(step_delay);
}
}

// make sure the servo arrives at the target


servo[servo_num].write(angle_target);
//update the current angle
angle_current[servo_num] = angle_target;

void twoarm_step_coordinate(double toparm_target, double middlearm_target) {

//Serial.println("--> two arm step Start /");

double incr_steps0=1;
double incr_steps1= 1;
int inner_step_delay0 = 0;
int inner_step_delay1 = 0;
int outer_step_delay = 30;
double i, j;
int e0 = 0;
int e1 = 0;

//Reference to function: servo_steps(int servo_num, int angle_target, int incr_step=10, int


step_delay=50)

//identify which of the arms has a greater delta in terms of degress to move
double delta0 = abs(angle_current[0] - toparm_target);
double delta1 = abs(angle_current[1] - middlearm_target);

//coordinate the speed of the two access through the incremental steps, so they can move
smoothly in the x/y plane
// (this avoids one arm finishing its movements first, and generating huge variagtionsin the real
x/y position of the endpoint)
if (delta0!=0 && delta1!=0) {
if (delta0 >= delta1) {
incr_steps0 = (delta0 / delta1)*incr_steps1;
//slow down motion as steps increase (just in case big jump in steps)
inner_step_delay0=(delta0/delta1)*0.5;
//reduce the outer step
outer_step_delay=outer_step_delay-inner_step_delay0;
} else {
incr_steps1 = (delta1 / delta0)*incr_steps0;
//slow down motion as steps increase (just in case big jump in steps)
inner_step_delay1=(delta1/delta0)*0.5;
//reduce the outer step
outer_step_delay=outer_step_delay-inner_step_delay1;
}
}
//set to zero if negative value on outer delay
if (outer_step_delay<0) {
outer_step_delay=0;
}

//identify the direction of steps


if (angle_current[0] > toparm_target) {
i = -incr_steps0;
} else {
i = incr_steps0;
}
if (angle_current[1] > middlearm_target) {
j = -incr_steps1;
} else {
j = incr_steps1;
}

// user the servo step functions, doing inter-twined steps until the gaps are reached.
// we send a delay of 0 to the servo step function, given we'll control the delay in this outer loop.
while (1) {
// top arm moves
if (abs(angle_current[0] - toparm_target) > incr_steps0) {
servo_steps(0, angle_current[0] + i, incr_steps0, inner_step_delay0);
} else {
servo_steps(0, toparm_target, incr_steps0, inner_step_delay0);
e0 = 1;
}
// middle arm moves
if (abs(angle_current[1] - middlearm_target) > incr_steps1) {
servo_steps(1, angle_current[1] + j, incr_steps1, inner_step_delay1);
} else {
servo_steps(1, middlearm_target, incr_steps1, inner_step_delay1);
e1 = 1;
}
delay(outer_step_delay);
if ((e0 + e1) >= 2) break;

//Serial.println("--> two arm step End /");


}

void servo_Open(bool openVal) {

int servo_num = 2;
int open_angle = servoGrip_val[0];
int close_angle = servoGrip_val[1];

//Reference to function: servo_steps(int servo_num, int angle_target, int incr_step=10, int


step_delay=50)

if (openVal == true) {
servo_steps(servo_num, open_angle, 1, 5);
} else {
servo_steps(servo_num, close_angle, 1, 5);
}

XYZ_current[4] = openVal;
}

void test_stepper() {

stepper_advance(0, stepper_maxsteps[0], 0);


delay(2500);
stepper_advance(0, stepper_maxsteps[0], 1);

}
void test_servo(int servo_num) {

int angle_max = 0;
int angle_min = 0;
int angle_default = 0;

//ref servo_steps(int servo_num, int angle_target, int incr_step=10, int step_delay=50)

//top servo
if (servo_num == 0) {
//max design free-movement limits (your actual setup limits may be different!)
angle_max = 100;
angle_min = 10;
angle_default = 90;
}
//middle servo
if (servo_num == 1) {
//max design free-movementlimits (your actual setup limits may be different!)
angle_max = 120;
angle_min = 30;
angle_default = 90;
}
//grip servo
if (servo_num == 2) {
angle_max = servoGrip_val[0];
angle_min = servoGrip_val[1];
angle_default = servoGrip_val[2];
}

servo_steps(servo_num, angle_max);
delay(1000);
servo_steps(servo_num, angle_min);
delay(1000);
servo_steps(servo_num, angle_default);

void test_servo_home(int servo_num) {

int angle_default = 0;

//ref servo_steps(int servo_num, int angle_target, int incr_step=10, int step_delay=50)

//top servo
if (servo_num == 0) {
angle_default = 90;
}
//middle servo
if (servo_num == 1) {
angle_default = 90;
}
//grip servo
if (servo_num == 2) {
angle_default = servoGrip_val[2];
}

servo_steps(servo_num, angle_default);

void test_getangles(double y, double z) {

get_angles_from_yz(y,z);

Serial.print("Y: ");
Serial.print(y);
Serial.print(" Z: ");
Serial.println(z);

Serial.print("servo1: ");
Serial.print(angle_next[0]-calibrate_TopArm);
Serial.print(" servo2: ");
Serial.println(angle_next[1]-calibrate_MiddleArm);

Serial.print("servo1 calibrated: ");


Serial.print(angle_next[0]);
Serial.print(" servo2 calibrated: ");
Serial.println(angle_next[1]);

//from http://forum.arduino.cc/index.php?topic=288234.0

void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;

// if (Serial.available() > 0) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.println(receivedChars);
parseData();

bool printmsg=false;
if (printmsg == true) {
Serial.print("X: ");
Serial.print(XYZ_next[0]);
Serial.print(" Y: ");
Serial.print(XYZ_next[1]);
Serial.print(" Z: ");
Serial.print(XYZ_next[2]);
Serial.print(" bool_move: ");
Serial.print(XYZ_next[3]);
Serial.print(" bool_open: ");
Serial.print(XYZ_next[4]);
Serial.print(" delay_ms: ");
Serial.print(XYZ_next[5]);
Serial.print(" move_type: ");
Serial.println(XYZ_next[6]);
}
//newData = false;
}
}

void parseData() {

// split the data into its parts

//data format <x,y,z,bool_move,bool_open,delayms,type_int> = <23,56,89,1,1,3456,3> {17}


//X: 7.00 Y: 8.00 Z: 9.00 bool_move: 1.00 bool_open: 0.00 delay_ms: 10.00 move_type: 1.00

char * strtokIndx; // this is used by strtok() as an index

//grab X
strtokIndx = strtok(receivedChars,","); // get the first part - the string
XYZ_next[0] = atof(strtokIndx); // convert this part to a float
//grab Y
strtokIndx = strtok(NULL, ",");
XYZ_next[1] = atof(strtokIndx); // convert this part to a float
//grab Z
strtokIndx = strtok(NULL, ",");
XYZ_next[2] = atof(strtokIndx); // convert this part to a float
//grab bool_move
strtokIndx = strtok(NULL, ",");
XYZ_next[3] = atoi(strtokIndx); // convert this part to a integer
//grab bool_open
strtokIndx = strtok(NULL, ",");
XYZ_next[4] = atoi(strtokIndx); // convert this part to a integer
//grab delayms
strtokIndx = strtok(NULL, ",");
XYZ_next[5] = atoi(strtokIndx); // convert this part to a integer
//type of action
strtokIndx = strtok(NULL, ",");
XYZ_next[6] = atoi(strtokIndx); // convert this part to a integer

You might also like