Go Down

Topic: Robotic Arm (Read 6232 times) previous topic - next topic


Feb 19, 2009, 06:53 pm Last Edit: Feb 19, 2009, 06:55 pm by electrocrook Reason: 1
I've begun making a robotic arm - in fact, the building was quite easy as I decided in the end to use off the shelf parts for it so that I could retask them when I've finished playing with my arm.


The arm doesn't work yet, it still needs wiring up along it's length and to the arduino. In fact, I'm not sure the servos will carry the weight of the arm itself, but this is an initial effort so I'm anticipating one step forward for 5 steps back :)

I have a small bit of code (just to test out my gripper servo really)

Code: [Select]
/ Test servo sketch by Andy Crook Feb 2009
// simply cycle a servo gripper open and closed. The values are not 180 and 0 because
// my gripper opens at 30 and closes fully at 170.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

void setup()
 myservo.attach(9);  // attaches the servo on pin 9 to the servo object

void loop()
   myservo.write(170);              // tell servo to close to setting 170          
   myservo.write(30);              // tell servo to open to setting 30


Hi Andy, looks like a good start. I think you may be correct about needing beefier servos further down the arm ( are those HS322 HD?)

Looking forward to seeing more  ;)

Have fun!  


Yeah 322s with carbonite gearing. I have 3 422's to swap around with as well, one in the base and two in the gripper at present but I think I may shorten the end of the arm, and put in the 422's at the base angle and first joint where the weight of the arm would produce most problems. I can also simply remove the tubes to shorten the arms drastically if needed, probably on the second tube. Have to play with it all and see I guess.


Feb 19, 2009, 10:46 pm Last Edit: Feb 19, 2009, 10:48 pm by zitron Reason: 1
Real industrial articulated robots use a counter weight or spring on the arm axis to balance the weigh of the arm and end effector, this reduces the load on the motor. Maybe you can try something like that?



That's a possibility if it comes down to it. I don't want to have to buy very expensive servos for it certainly.


Apr 14, 2009, 10:49 pm Last Edit: Apr 14, 2009, 10:56 pm by electrocrook Reason: 1
Well, after a long time (and a birthday) I've got some more powerful servos for my arm, and it's pretty much done apart from some wiring. I've left this till last so I could focus on the software.

So lastly I need to wire up all the servos, and beautify the wiring so that the arm is free to move. I also need to bolt the base down as the arm is quite heavy now and tips over.

I've got the arduino sketch taking command over serial, then setting the appropriate servo, and a more complex VB app which will send servo positions to the arduino. In the end, I'm going to be able to record sets of servo positions so I can calibrate the arm for positions in front of it, and switch between them.

Here is the current GUI for the VB app. Simple at the moment but it's just for moving the servos. It's a real pleasure to move a slider in a VB app and see the arm move in the real world :)

Here's the sketch on the Arduino as it currently stands. It has been a trial to get VB to output the right kind of serial bytes to the arduino - i thought it would be simpler, but I got it sorted in the end. This code may change a bit still, but most of the coding will be done via VB now.

Code: [Select]
// This Arduino sketch controls 6 servos on a robotic arm by receiving commands over a serial COM port
// by Andy Crook 2009
// www.c-digital-art.co.uk

#include <ServoTimer2.h>  // the servo library

// define the pins for the servos
#define basePin 2
#define shoulderPin 3
#define elbowPin   4
#define wristPin 5
#define wristrotatePin 6
#define gripPin   7

#define MIN_PULSE  540 // pulse in microseconds for servo's
#define MAX_PULSE  2200

ServoTimer2 servoBase;    // declare variables for the 6 servos
ServoTimer2 servoShoulder;
ServoTimer2 servoElbow;    
ServoTimer2 servoWrist;
ServoTimer2 servoWristrotate;
ServoTimer2 servoGrip;  

int incomingByte = 0;  // for incoming data
int servovalue = 0; // for servo value
int pos = 0;
long val0 = 0;

int base = 0;
int shoulder = 0;
int elbow = 0;
int wrist = 0;
int wristrotate = 0;
int grip = 0;

void setup() {
 servoBase.attach(basePin);           // attach all pins to the servos

 servoBase.write(1000);               // set initial values for all servos
 servoShoulder.write(1000);           // will calibrate these once arm is built
 servoElbow.write(1000);              // for a good 'initial setting'

 Serial.begin(9600);   // opens serial port and sets data rate to 9600 bps


void loop()

 if (Serial.available() > 1) {      // if there are more than 1 bytes of data in the buffer read them in 2 byte chunks
   // this will cycle round every 2 bytes. As long as you send 2 bytes at a time to the buffer
   // they should all set fine. If one byte is sent it will wait for the next one but
   // if no appropriate header byte is found, it will do nothing but clear the buffer
   // the servovalue byte must be from 0 - 180 for the map function to work right
   // example setting for all 6 servos:
   // As a byte sequence this is: 200 65 201 66 202 67 203 68 204 69 205 70

   // read incoming byte
   incomingByte = Serial.read();
   servovalue = Serial.read();
   Serial.print("Servo Command: ");
   Serial.print(incomingByte, DEC);
   //incomingByte = (incomingByte, DEC);
   if (incomingByte == 200){
      Serial.print(" - BASE ");
   if (incomingByte == 201){
      Serial.print(" - SHOULDER ");
   if (incomingByte == 202){
      Serial.print(" - ELBOW ");
   if (incomingByte == 203){
      Serial.print(" - WRIST ");
   if (incomingByte == 204){
      Serial.print(" - WRIST ROTATE ");
   if (incomingByte == 205){
      Serial.print(" - GRIP ");
   if (incomingByte > 199 && incomingByte < 206) // if command is valid, state servo setting
   Serial.print(" - VALUE: ");
   Serial.print(servovalue, DEC);
   Serial.println(" Degrees");
  // Serial.println(" ");
     Serial.println(" Command not recognised "); // if command header byte is not 200-205, signal error
   if (incomingByte == 200) // sets base to value following 200
     pos = servovalue;
     base = pos;  // keep value of base set for future use (not implemented yet)
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoBase.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180

 if (incomingByte == 201) // sets shoulder to value following 201
     pos = servovalue;
     shoulder = pos;
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoShoulder.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180

 if (incomingByte == 202) // sets elbow to value following 202
     pos = servovalue;
     elbow = pos;
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoElbow.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180

 if (incomingByte == 203) // sets wrist to value following 203
     pos = servovalue;
     wrist = pos;
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoWrist.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180
 if (incomingByte == 204) // sets wristrotate to value following 204
     pos = servovalue;
     wristrotate = pos;
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoWristrotate.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180

 if (incomingByte == 205) // sets grip to value following 205
     pos = servovalue;
     grip = pos;
     val0 = map(pos, 0, 180, MIN_PULSE , MAX_PULSE );
     servoGrip.write(val0);              // tell servo to go to position in variable 'pos' from 0 to 180

 if (Serial.available() == 1) // if there is only one byte left after read, then read it to discard it
   Serial.println("Serial Buffer ERROR: One byte left -> Discarded");




Keep up the good work. I hope to start a project like this in the future.


Looks like you've got the forward kinematics taken care of.  Your links do appear rather long, it looks like its asking a lot out of the bottom servo.  Note the short links on your computer screen in DSCF1314rs.JPG.  I would put a beefier servo for that placement.  

Post more of your VB development, I am interested in that.  Good job!


Once  I get around to the final wiring and the like, I'll get to adding to and tidying up the code, then post some source but it's nothing special, just simple serial commands to the arduino which sets the servo angle. I may try to code an IK solver for the XYZ space the arm can reach, which I imagine would be quite a challenge :)

Go Up