# Difference between revisions of "Robotic Arm: Team Stealth Squad"

(11 intermediate revisions by 2 users not shown) | |||

Line 8: | Line 8: | ||

Our team created a dual-jointed robotic arm that would hold a pencil and draw a circle within a square within another circle. To do this we used a variety of Lynxmotion parts from the Engineering Lab classroom. The arm is attached to a surface using a c-clamp and is moved using two servo motors. The motors are controlled through a circuit board run with Matlab code. After calibrating the motors we went about creating an arm using aluminum tubes, servo brackets, and hubs. We initially used long (4"-6")tubes for the "upper arm" segment of our robotic arm, however this caused poor distibution of mass and led to an unbalanced and shaky product. Our final construct used 2" tubes for both segments of our robotic arm. After constructing the arm our team began to work on making a SolidWorks Model and creating Matlab commands that would control the arm and run the functions which we wanted with appropriate scale, speed, and accuracy. | Our team created a dual-jointed robotic arm that would hold a pencil and draw a circle within a square within another circle. To do this we used a variety of Lynxmotion parts from the Engineering Lab classroom. The arm is attached to a surface using a c-clamp and is moved using two servo motors. The motors are controlled through a circuit board run with Matlab code. After calibrating the motors we went about creating an arm using aluminum tubes, servo brackets, and hubs. We initially used long (4"-6")tubes for the "upper arm" segment of our robotic arm, however this caused poor distibution of mass and led to an unbalanced and shaky product. Our final construct used 2" tubes for both segments of our robotic arm. After constructing the arm our team began to work on making a SolidWorks Model and creating Matlab commands that would control the arm and run the functions which we wanted with appropriate scale, speed, and accuracy. | ||

+ | |||

+ | [[Image: Stealth Squad Robot Arm.jpg|300px|thumb|left| Robot Arm]] [[Image: Stealth Squad Robot Arm Drawing.jpg|300px|thumb|right| Robot Arm Drawing]] | ||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

+ | |||

==Solid Works== | ==Solid Works== | ||

Line 18: | Line 43: | ||

:*Our SolidWorks model shows the basic design and assembly of our robotic arm. | :*Our SolidWorks model shows the basic design and assembly of our robotic arm. | ||

− | + | :*Fastners, pencil, and c-clamp are not included. | |

− | + | :*The SolidWorks file was created after completion of the physical arm. | |

− | + | :*It is thus more of a model/simulation than a design aid. | |

Line 33: | Line 58: | ||

===Simulation=== | ===Simulation=== | ||

+ | |||

+ | [[Image: StealthSquadSim.jpg|475px|thumb|right|Simulated Circle]] | ||

%Define the arm | %Define the arm | ||

la=4.5; lb=4.3025; | la=4.5; lb=4.3025; | ||

− | + | ||

%Draw and animate the arm; | %Draw and animate the arm; | ||

numPts = 20; %the number of points in the animation | numPts = 20; %the number of points in the animation | ||

phi = linspace(0,2*pi,numPts); %angle goes from 0 to 2*pi. | phi = linspace(0,2*pi,numPts); %angle goes from 0 to 2*pi. | ||

− | + | ||

clf % clear the figure. | clf % clear the figure. | ||

− | + | ||

x0=0; %Define center (x0,y0) of circle and radius (r) | x0=0; %Define center (x0,y0) of circle and radius (r) | ||

y0=7; | y0=7; | ||

r=1; | r=1; | ||

− | + | ||

% loop through all the values of phi | % loop through all the values of phi | ||

for i=1:length(phi), | for i=1:length(phi), | ||

x2=x0+r*cos(phi(i)); %x2 and y2 trace out a circle. | x2=x0+r*cos(phi(i)); %x2 and y2 trace out a circle. | ||

y2=y0+r*sin(phi(i)); | y2=y0+r*sin(phi(i)); | ||

− | + | ||

%First do inverse kinematics to find angles... | %First do inverse kinematics to find angles... | ||

[theta_a, theta_b]= InverseKinematics(la, lb, x2, y2); | [theta_a, theta_b]= InverseKinematics(la, lb, x2, y2); | ||

− | + | ||

%Then do forward kinematics to find arm locations. | %Then do forward kinematics to find arm locations. | ||

[xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); | [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); | ||

Line 71: | Line 98: | ||

This code simulates our robotic arm drawing a circle in MatLab. The code is essentially the same as the simulation from MatLab Lab 1, only with the arm lengths changed to correspond with the arm lengths of our robot. | This code simulates our robotic arm drawing a circle in MatLab. The code is essentially the same as the simulation from MatLab Lab 1, only with the arm lengths changed to correspond with the arm lengths of our robot. | ||

+ | |||

+ | ===Control Script=== | ||

+ | |||

+ | To draw a circle within a square within a circle, we first created a function to move the pencil to a certain point. To do this, we used our inverse kinematics function from the previous lab to find the necessary angles, then used the function derived in the servo calibration lab to set the appropriate pulse widths. A difficulty that we encountered here was that our inverse kinematics function calculated the angle for the second motor in relation to the x axis, whereas the angle of the upper arm would be in relation to the lower arm. To compensate for this, we added the angle found for the shoulder on to the angle found for the elbow and set the appropriate pulse widths. The function then sent a string with the calculated pulse widths to the servo controller, which then moved the pencil to the appropriate point. Then, we created a function to draw a line from two endpoints and a function to draw a circle from a center point and a radius. These functions were generated by taking the code for the simulations, replacing the values of the line and circle with variables defined by the inputs, and replacing the part that plotted the figure with a loop that sent strings to the servo controller for each point on the line or circle. Then, we created a script that first drew a circle with radius 1, the the lines that defined a tangential square, and then another circle of radius sqrt(2) that circumscribed the square. | ||

+ | |||

+ | MoveArm.m: | ||

+ | |||

+ | function [a, b] = MoveArm(x, y) | ||

+ | |||

+ | s=instrfind; %Find any serial links (we can have only 1) | ||

+ | delete(s); %... and delete. | ||

+ | |||

+ | %Create a new serial communications link | ||

+ | s=serial('COM1','Baudrate',115200,'Terminator','CR'); | ||

+ | fopen(s); %... and open it | ||

+ | |||

+ | %Set arm lengths | ||

+ | la=4.5; | ||

+ | lb=4.3025; | ||

+ | |||

+ | %Find arm angles relative to fixed plane | ||

+ | [theta_a, theta_b] = inverseKinematics(la, lb, x, y); | ||

+ | |||

+ | %Convert to angles to input to servos | ||

+ | a=theta_a; | ||

+ | b=90-a+theta_b; | ||

+ | |||

+ | %Find appropriate pulse widths for each angle | ||

+ | %(This function was derived in the servo calibration lab) | ||

+ | pw_a=2450-10*a; | ||

+ | pw_b=2475-10*b; | ||

+ | |||

+ | %Send strings to servos | ||

+ | fprintf(s,['#1P',num2str(pw_a),'T200']) | ||

+ | fprintf(s,['#2P',num2str(pw_b),'T200']) | ||

+ | |||

+ | ArmDrawLine.m: | ||

+ | |||

+ | function [xi,yi,xf,yf] = ArmDrawLine(xi,yi,xf,yf) | ||

+ | |||

+ | %Define the arm | ||

+ | la=4.5; lb=4.3025; | ||

+ | |||

+ | %Define the line; | ||

+ | numPts = 25; %the number of points in the line | ||

+ | x2=linspace(xi,xf,numPts); %generate an array of x2 ... | ||

+ | y2=linspace(yi,yf,numPts); %... and y2 values to define a line. | ||

+ | |||

+ | % loop through all the values of x2 and y2 | ||

+ | for i=1:length(x2), | ||

+ | |||

+ | %First do inverse kinematics to find angles... | ||

+ | [theta_a, theta_b]= InverseKinematics(la, lb, x2(i), y2(i)); | ||

+ | |||

+ | %Then do forward kinematics to find arm locations. | ||

+ | [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); | ||

+ | |||

+ | %Move arm to next point on the line. | ||

+ | MoveArm(xb, yb); | ||

+ | |||

+ | pause(0.1); %delay 1/10 second | ||

+ | end | ||

+ | |||

+ | ArmDrawCircle.m: | ||

+ | |||

+ | function [x0,y0,r] = ArmDrawCircle(x0,y0,r) | ||

+ | |||

+ | %Define the arm | ||

+ | la=4.5; lb=4.3025; | ||

+ | |||

+ | %Define the circle; | ||

+ | numPts = 50; %the number of points in the circle | ||

+ | phi = linspace(0,2*pi,numPts); %angle goes from 0 to 2*pi. | ||

+ | |||

+ | % loop through all the values of phi | ||

+ | for i=1:length(phi), | ||

+ | x2=x0+r*cos(phi(i)); %x2 and y2 trace out a circle. | ||

+ | y2=y0+r*sin(phi(i)); | ||

+ | |||

+ | %First do inverse kinematics to find angles... | ||

+ | [theta_a, theta_b]= InverseKinematics(la, lb, x2, y2); | ||

+ | |||

+ | %Then do forward kinematics to find arm locations. | ||

+ | [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); | ||

+ | |||

+ | MoveArm(xb,yb); | ||

+ | |||

+ | pause(0.1); %delay 1/10 second | ||

+ | end | ||

+ | |||

+ | CwiaSwiaC.m (Circle within a Square within a Circle): | ||

+ | |||

+ | %Draw first circle | ||

+ | ArmDrawCircle(0,7,1) | ||

+ | |||

+ | %Starting from the end of the circle, draw a tangential square | ||

+ | ArmDrawLine(1,7,1,8) | ||

+ | ArmDrawLine(1,8,-1,8) | ||

+ | ArmDrawLine(-1,8,-1,6) | ||

+ | ArmDrawLine(-1,6,1,6) | ||

+ | ArmDrawLine(1,6,1,7) | ||

+ | |||

+ | %Circumscribe the square | ||

+ | ArmDrawCircle(0,7,1.41) |

## Latest revision as of 16:31, 17 November 2008

**Team Stealth Squad:**

## Overview

Our team created a dual-jointed robotic arm that would hold a pencil and draw a circle within a square within another circle. To do this we used a variety of Lynxmotion parts from the Engineering Lab classroom. The arm is attached to a surface using a c-clamp and is moved using two servo motors. The motors are controlled through a circuit board run with Matlab code. After calibrating the motors we went about creating an arm using aluminum tubes, servo brackets, and hubs. We initially used long (4"-6")tubes for the "upper arm" segment of our robotic arm, however this caused poor distibution of mass and led to an unbalanced and shaky product. Our final construct used 2" tubes for both segments of our robotic arm. After constructing the arm our team began to work on making a SolidWorks Model and creating Matlab commands that would control the arm and run the functions which we wanted with appropriate scale, speed, and accuracy.

## Solid Works

- Our SolidWorks model shows the basic design and assembly of our robotic arm.
- Fastners, pencil, and c-clamp are not included.
- The SolidWorks file was created after completion of the physical arm.
- It is thus more of a model/simulation than a design aid.

## Matlab

### Simulation

%Define the arm la=4.5; lb=4.3025; %Draw and animate the arm; numPts = 20; %the number of points in the animation phi = linspace(0,2*pi,numPts); %angle goes from 0 to 2*pi. clf % clear the figure. x0=0; %Define center (x0,y0) of circle and radius (r) y0=7; r=1; % loop through all the values of phi for i=1:length(phi), x2=x0+r*cos(phi(i)); %x2 and y2 trace out a circle. y2=y0+r*sin(phi(i)); %First do inverse kinematics to find angles... [theta_a, theta_b]= InverseKinematics(la, lb, x2, y2); %Then do forward kinematics to find arm locations. [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); subplot(1,2,1); %generate 1x2 plots, choose plot 1 plot([0 xa xb],[0 ya yb],'b','LineWidth',2); axis([-10 10 0 10]); subplot(1,2,2); %choose second plot plot(xb,yb,'ro') %plot red circle axis([-10 10 0 10]); hold on; %don't erase this plot. pause(0.1); %delay 1/10 second end

This code simulates our robotic arm drawing a circle in MatLab. The code is essentially the same as the simulation from MatLab Lab 1, only with the arm lengths changed to correspond with the arm lengths of our robot.

### Control Script

To draw a circle within a square within a circle, we first created a function to move the pencil to a certain point. To do this, we used our inverse kinematics function from the previous lab to find the necessary angles, then used the function derived in the servo calibration lab to set the appropriate pulse widths. A difficulty that we encountered here was that our inverse kinematics function calculated the angle for the second motor in relation to the x axis, whereas the angle of the upper arm would be in relation to the lower arm. To compensate for this, we added the angle found for the shoulder on to the angle found for the elbow and set the appropriate pulse widths. The function then sent a string with the calculated pulse widths to the servo controller, which then moved the pencil to the appropriate point. Then, we created a function to draw a line from two endpoints and a function to draw a circle from a center point and a radius. These functions were generated by taking the code for the simulations, replacing the values of the line and circle with variables defined by the inputs, and replacing the part that plotted the figure with a loop that sent strings to the servo controller for each point on the line or circle. Then, we created a script that first drew a circle with radius 1, the the lines that defined a tangential square, and then another circle of radius sqrt(2) that circumscribed the square.

MoveArm.m:

function [a, b] = MoveArm(x, y) s=instrfind; %Find any serial links (we can have only 1) delete(s); %... and delete. %Create a new serial communications link s=serial('COM1','Baudrate',115200,'Terminator','CR'); fopen(s); %... and open it %Set arm lengths la=4.5; lb=4.3025; %Find arm angles relative to fixed plane [theta_a, theta_b] = inverseKinematics(la, lb, x, y); %Convert to angles to input to servos a=theta_a; b=90-a+theta_b; %Find appropriate pulse widths for each angle %(This function was derived in the servo calibration lab) pw_a=2450-10*a; pw_b=2475-10*b; %Send strings to servos fprintf(s,['#1P',num2str(pw_a),'T200']) fprintf(s,['#2P',num2str(pw_b),'T200'])

ArmDrawLine.m:

function [xi,yi,xf,yf] = ArmDrawLine(xi,yi,xf,yf) %Define the arm la=4.5; lb=4.3025; %Define the line; numPts = 25; %the number of points in the line x2=linspace(xi,xf,numPts); %generate an array of x2 ... y2=linspace(yi,yf,numPts); %... and y2 values to define a line. % loop through all the values of x2 and y2 for i=1:length(x2), %First do inverse kinematics to find angles... [theta_a, theta_b]= InverseKinematics(la, lb, x2(i), y2(i)); %Then do forward kinematics to find arm locations. [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); %Move arm to next point on the line. MoveArm(xb, yb); pause(0.1); %delay 1/10 second end

ArmDrawCircle.m:

function [x0,y0,r] = ArmDrawCircle(x0,y0,r) %Define the arm la=4.5; lb=4.3025; %Define the circle; numPts = 50; %the number of points in the circle phi = linspace(0,2*pi,numPts); %angle goes from 0 to 2*pi. % loop through all the values of phi for i=1:length(phi), x2=x0+r*cos(phi(i)); %x2 and y2 trace out a circle. y2=y0+r*sin(phi(i)); %First do inverse kinematics to find angles... [theta_a, theta_b]= InverseKinematics(la, lb, x2, y2); %Then do forward kinematics to find arm locations. [xa ya xb yb] = forwardKinematics(la, lb, theta_a, theta_b); MoveArm(xb,yb); pause(0.1); %delay 1/10 second end

CwiaSwiaC.m (Circle within a Square within a Circle):

%Draw first circle ArmDrawCircle(0,7,1) %Starting from the end of the circle, draw a tangential square ArmDrawLine(1,7,1,8) ArmDrawLine(1,8,-1,8) ArmDrawLine(-1,8,-1,6) ArmDrawLine(-1,6,1,6) ArmDrawLine(1,6,1,7) %Circumscribe the square ArmDrawCircle(0,7,1.41)