Tag Archives: servos

servo arm now drawing things with inverse kinematics

you can see some of the error modes i was encountering in the ^ shaped “straight line” where theta1 was clipping out because I was feeding it negative values based on my inverse kinematics calculated angles

i blame servo jitter for how shaky the lines are πŸ™‚

this took forever and a heaping bowlful of confusion to get to where i am. actually i’m still confused. but basically i spent all day sunday working on this, emailed out to MITERS, and finally a hallmate, pranjal, helped me out (https://github.com/pranjalv123/servoarm) today and fixed where I was stuck at in an hour or two.

essentially he rewrote the code in python (I was actually starting to do this) to graph and understand what was going on. For instance, the bottom-most image is the working envelope of the robot arm;

Isn’t that fascinating? It’s like a  yin yang. If you play around with the servo arm this sort of working envelope makes sense.

So turns out my code was decently fine, the negative values just meant I was giving it bad inputs that it physically couldn’t reach given the arm link lengths I’d given it.

We initially tried to wrap the negative values around by doing mod180 ‘ing it,
 theta1 = ((int)theta1+180)%180
but this gives the sort of trajectory shown in the upper image
(I think… it may also be that elbowup needs to be false to generate that sort of trajectory)

setting elbowup to be true fixed a lot of issues to (which makes sense physically as more x,y coordinates can be reached if the elbow is up rather than down, it’s  easy to see if you play around with it … see the inverse kinematics chapter on http://www.eng.utah.edu/~cs5310/chapters.html if this elbowup/down stuff is coming out of nowhere — basically there are two combinations of theta 1 and theta 2 that will work for any given x,y coordinate and you just pick whether you want the elbow up or down solution)

and finally the working enveloped helped me pick correct x,y values to feed it. Initially I was just basing my x,y values off of the instructables www.instructables.com/id/Robotic-Arm-with-Servo-Motors/?ALLSTEPS but scaled down 1/3, which was just a guess of mine based on my servo joint limitations versus her motor joint limitations

it is also surprisingly close to the dimensions in mm I give it, eg.


double highY = 80; // line drawing targets in mm


double lowY = 20;


double staticX = 20;

will give me a line about 60 mm long (I put the link lengths in as mm), which is exciting.

I’m still not sure what’s going on with why the straight line up and down is at a 45degree angle, but that’s probably a constant offset problem. Fixable either in code or if I set the initial conditions on the angle the links are mounted on the servos better.

Next: faces?

Servo repair with 4-40 tap, no thanks to silly proprietary servo hardware

Hexapod now has 18 working servos again! yay.

Servo Failure modes
I didn’t strip the gears* on one of my servos from applying to much load to it (the way I expected my servo to fail), but rather stripped the threads on the servo to servo horn coupler.

*see http://techtv.mit.edu/videos/10523-what-is-design-an-example for a good video of designing a robot, having the gears strip, and solving that problem with rubber “shock absorbers.” This video is shown near the very beginning of 2.007 Design and Manufacturing I, a sophomore build-robots mechanical engineering class.
@28:30 you see a good picture of stripped servos gears, where the missing teeth means that the servo can’t turn correctly:


Anyway, I had some issues because I thought maybe I was using the wrong size screw. The servo horns and screws and splines are all some dumb not inter-compatible between manufacturers proprietary design.

So I ordered some replacement servos off of ebay.
“Vigor VS-2 standard analog Servo VS 2 vs2”
$9.98 for 2, or $4.99 each.
Probably I paid way too much but whatever. At the time I thought $5 was really cheap for a servo (now I think $3 is more reasonable price for this servo). Bought 2/9 and delivered 2/19, not bad.

At first I thought I got ripped off and the servos were stripped, but then I looked more closely and realize that there are no threads cut into the servos:

So you can use the proprietary self-tapping screws, but I realized you can just tap them with regular ol’ 4-40 threads and use normal 4-40 screws instead of, if you ever lose the pack of proprietary servo stuff, hunting around for ages looking for an appropriate size screw.
left: 4-40 screw mates fine with servo horn. top: a 4-40 tap. right: A proprietary screw with mysterious thread count and pitch next to a nylon 4-40 screw.
Works well!


2dof minimalistic servo arm, now with mapped values + code

values actually mapped correctly = some semblance of control. mapping painstakingly / experimentally determined
the setup

actually very difficult to write words even with the arm controller (versus twiddling some potentiometers to control the arm), because the potentiometer to servo mapping isn’t precise and there’s a lot of slop (e.g. look at the dead space around the screwdriver)

time elapsed: probably 1 hr including trying to figure out how to draw things and documenting ^^ (~40 minutes to code this and map the values)

/**
 * @file: RC control of servo
 *
 * @description
 * theta1 = bottom joint pot value, theta2 = top joint pot value
 * these were experimentally determined,
 * I had one leg of pot connected to sig5v, the other to a voltage
 * divider setup with a 1kohm=R2 and being read to A0 or A1 respectively
 */

#include <Servo.h>
Servo servo1;
Servo servo2;

int theta1;
int theta2;

int map1;
int map2;

void setup()
{
//    pinMode(1, INPUT);
//    pinMode(2, INPUT);
    Serial.begin(9600);
    servo1.attach(2,500,2400);
    servo2.attach(3,500,2400);
}

void loop()
{
  theta1 = analogRead(A1);
  theta2 = analogRead(A0);
//  map1 = map(theta1, 163,380, 0,130);
  map1 = map(theta1, 163,360, 0,130);
//  map2 = map(theta2, 1017,275, 0,160);
  map2 = map(theta2, 1017,264, 3,150);
  servo1.write(map1);
 
  servo2.write(map2);
  Serial.print(“theta1 “); Serial.print(theta1);
  Serial.print(” map1 “); Serial.print(map1 );
  Serial.print(” theta2 “); Serial.print(theta2);
  Serial.print(” map2 “); Serial.print(map2);
  Serial.println();
 
  delay(20);
 
}