Steve, The Disembodied Robot Arm

Video Links:

  1. Manual Control
  2. Flailing Around
  3. Group Move
  4. Looking Better
  5. Stripped servo gear
  6. Stacking Batteries
  7. LetsMakeRobots!

 


2008/10/7

 

 

I'd always wanted to play with a robotic arm. I intended to build my own, but as I started looking into the complexity of the mechanisms for the rotating base and the grippers, and comparing the cost of buying the servos and materials myself compared to buying a pre-designed kit like LynxMotion's, I ended up deciding to just buy the Lynx 6 kit. I still feel the cost is higher than it needs to be, but the servos do make up about half of the kit cost, so it doesn't feel quite as excessive. Still, it's certainly not a cheap kit.

But it's oh-so-fun. The arm took about five hours to build, which was more than I expected. I bought the "no electronics" kit, which is about $125 cheaper but doesn't include their SSC-32 servo controller and RIOS Windows software. I didn't want this robot to be tied to a computer -- some of the ideas I have in mind for it would require it to sit and run on a table unattended indefinitely, and I didn't want to dedicate a computer just for that. So I ordered an Arduino and a Pololu Micro Serial Servo Controller instead.

I knew that this solution would require more work on my part, because the Lynx SSC-32 has some pretty advanced servo control features, and the RIOS software handles all the advanced calculations like inverse kinematics and recording motions for playback. I'd have to come up with my own solution from scratch.

At Frits' suggestion, I rigged up six potentiometers to let me easily input values for each of the six joints. Due to my affliction of Can-Never-Leave-Well-Enough-Alone-Itis, I ended up spending two days just on that input mechanism, building a fancy aluminum box and a PCB for it, and fashioning a wire harness complete with detachable connector. Overkill. But it does look kind of nice :)

When I run that function, the Arduino simply reads the six pot values, updates the joint positions to match, and prints the new values to the serial output on the computer. That makes it much easier to find the combination of values that position the arm where I want it. When I'm scripting a motion, I pose the arm with the pots, write down the six values, and add them to the code as a new 'pose' array. Then the code can simply move from one pose to another.

At first, I was using a 4x AA battery pack to provide the 6v for the servos, and the motion was really erratic and weak. It could barely pick anything up, and when one of the servos was straining (like when the gripper was holding onto something), the other servos often didn't move. It sounded like a problem with too little current. I couldn't find official numbers on how much current AA batteries can comfortably put out, but it sounds like it's only around 300ma (2C). I bought a 6v, 2.5A AC adapter at Radio Shack, and that took care of the problem. The motion is now crisp, fast, and powerful.

Coding smooth, reliable motion IS turning out to be a challenge, but I've made faster progress than I expected. At first the arm did tend to jerk around and knock stuff over, as you can see in the second video. The main problem was the fact that I was simply updating new positions for the six servos, and letting them all travel to their respective positions at their own rate. This meant that the arm would end up where you wanted it, but it was hard to predict what path it would take to get there. Also, at 6v with a healthy supply of current, these servos can move pretty fast, so rather than lift those 9v batteries up for my inspection, the arm tended to just fling them across the room. Fun, but needs work.

The feature I really liked about the LynxMotion SSC-32 servo controller is that it supports a mode called "Group Move," where it times each servo's motion so that they all reach the new positions at the same time. The Pololu servo controller I have doesn't support that feature, so I decided to implement that in the Arduino. It worked surprisingly well, and the third video shows a simple test of that feature. The fourth video is the same routine as the second, but using the Group Move feature and using 1 second for each motion. It works much better. This seems like a good start. I'm excited. Think of all the things I can pick up now!

Rather than flood this page with images, you can see photos of the assembly process etc in my photo gallery.

 

 


2008/10/11

 

Disaster! I've broken it. I noticed my Group Move tended to be a tiny bit jerky, which suggested that each iteration of the loop was taking too long. I know that floating point math is MUCH slower than integer math, so I was trying to optimize my Group Move algorithm to use only integers. Unfortunately, I didn't realize that so many of the values I was working with were less than 1.0 -- they got rounded down to 0, which wreaked havoc with the math. When I tested it, the arm flailed around like it was suffering from epilepsy, and it literally broke its wrist :)

I have a wrapper function for moving servos which makes sure that I don't send them to a position they can't reach, but in order to speed up the Group Move, I was bypassing that function and just sending direct positions to the servos. Apparently the wrist rotate servo was asked to do some unholy motion that it didn't like and it stripped half the teeth off of one of its gears (see video).

HiTec makes a metal gear upgrade pack for this servo, an HS-85BB, but my local hobby shop didn't have it and I was impatient, so I just bought the metal-geared equivalent, HS-85MG, and replaced the servo. Eventually I'll order a gear pack to repair this servo and have it available for a future project.

I had already been considering upgrading the gripper servo, an HS-81, to metal gears, because that was where I really noticed a weakness. Whenever I tried to pick something up, if I applied too much pressure, the gears would slip and it'd make a gross grinding sound. The hobby shop did have a metal gear set for that servo, so I bought that as well and upgraded it.

The difference is definitely noticeable. Now I can squeeze as hard as I want, and the gears don't grind. In fact, the limitation now is that when the gripper servo is straining, it apparently consumes enough current to cause voltage fluctuations or something, and the gripper occasionally twitches if I squeeze too hard. So I still have to be aware of how much pressure it's applying, but if I apply too much pressure all that happens is that whatever I'm carrying gets dropped, which is better than breaking gears.

I've also been doing more reading on kinematics, both forward and reverse. I implemented forward kinematics (calculating the X/Y/Z position of the gripper based on the angles of each of the joints), and it works great -- I can place the arm in any position, and it outputs the coordinates in inches. I've tested by measuring the actual position, and it's quite accurate.

I tried coding up inverse kinematics too (determining the joint angles you need in order to put the gripper in a certain position), and just like I'd read, it seems to be too heavy to be done on a microcontroller. I got something that sort of worked, but it took several minutes to move the arm to a point just a few inches away. I'm going to keep experimenting with it, but I've pretty much accepted that eventually I'll have to hook this up to a little Linux machine or something. I imagine eventually I'll mount it on a mobile robot so it can drive around and do interesting things, and I figure that robot will be controlled by some sort of onboard nano-ITX computer or something.

 


 

2008/12/2

As I mentioned earlier, I've come to terms with the limitations of trying to control an arm with a limited processor like a microcontroller, so I'm not going to put more effort into simple scripting. I'll set the arm aside until I can afford to buy a cheap laptop and webcam to set up the arm with vision processing etc. I think that will make for much more interesting programming possibilities. I'd also like to make it mobile, so that it can interact with more than just the little part of the world that's within its reach.

But in the meantime, I put together one last fun little video, which you can see above.

Flail around and knock over stuff

  • Actuators / output devices: 4x HS-475HB, 1x HS-422, 1x HS-82MG, 1x HS-85MG
  • Control method: Homebuilt wired remote control (6 pots)
  • CPU: Arduino diecimila
  • Power source: 6v 2.5A AC Adapter for servos, USB power for Arduino
  • Target environment: Tabletop

This is a companion discussion topic for the original entry at https://community.robotshop.com/robots/show/steve-the-disembodied-robot-arm

Looks fun

Looks fun :wink: How much can it lift?

PS the sound is messed up on the 3. and 4. video

bravo!
keep 'm dancing!

How exciting!! :DPlease

How exciting!! :smiley:

Please throw a lamp on before you film next time :wink:

Veery nice work on the "controller"! :slight_smile:

That "group mode" sounds fun to make - actually you should be able to re-use some of the thinkings that you used on your YDM-clone. I would really love to code such a feature myself; You could even add sort of "pre-destinations" on some of the servos. That way all arm could go from one position to another… and in that flow, one or two of the servos would have "drive by-destinations", so that it would move from A to C position… but"the elbow" would lift over something, if you follow… :slight_smile:

You write "RIOS software handles all the advanced calculations like inverse kinematics and recording motions for playback"…?? Recording motions? Which sensors?

Looking forward to see what you teach it :slight_smile:

It can lift more than I

It can lift more than I expected – I was able to lift a 6-cell nimh battery pack from an R/C car. The main weakness seems to be the gripper servo – if I squeeze too hard on the object, the servo gears slip and it makes a gross grinding sound, but of course if I don’t grip hard enough, the object slips out of the gripper. It can apparently grip reasonably hard before the gears slip, but without some sort of force sensor, I don’t have a good way to tell how hard it’s gripping until I try to lift the object and see if it falls :slight_smile:

I don’t know what happened with the sound on the last two videos, my camera apparently broke after the first two, because now every video I record with it has static for sound. Weird. Well, I replaced the sound on the last two videos with music to make it less annoying.

Dan

Hehe yeah, I noticed it’s

Hehe yeah, I noticed it’s dark and hard to see what’s going on. These were sort of like ‘snapshots’, just to capture the robot’s progress :slight_smile: I’ll definitely make sure I have better lighting and camera angles etc once I’ve got something more interesting to show.

That’s a good idea about ‘pre-destinations’ for some servos. What I’ve been doing so far for that kind of thing is just using two separate ‘poses’. For example, when I want to pick up a battery, I first move into a pose where the arm is above the battery, and then a short 250ms transition to a second pose where the arm moves down so the fingers are around the battery but still open, then another 250ms transition where the grippers close, then from there I can move to the next pose (like holding the battery up in the air). To release the battery, I do those three poses backwards.

At first I was forgetting to do the last pose when releasing, so I’d place the battery down, open the grips, and then move to the next pose (above the second battery), but of course since I forgot to first move into the “above the battery” pose, the arm knocked the battery out of place when it moved sideways to the next pose :slight_smile:

But when I use the right set of poses, it seems to work quite well. So if I need to get the elbow over something, I could simply make an intermediate pose where the elbow is where I want it, and run through the two poses in series. It’s basically the way a lot of computer animation is done – define the ‘keyframes’, where you position all the objects in the scene at certain key points, and then you let the software move the objects from one keyframe to the other.

I’ll have to see if that solution works well enough once I start doing more advanced motions though. Next up: stacking :slight_smile:

When I said ‘recording motions’, I meant basically what I’m doing in code – scripting a series of arm motions that it can then play back. With RIOS, apparently you can position the arm using your keyboard and mouse on the computer, and save that motion in the software, and then the software can re-play the arm motions you stored. Personally, using keyboard and mouse sounds more awkward than having six nice hardware dials to play with :slight_smile:

The inverse kinematics sounds nice though. It would let me avoid manually dialing in each joint position each time – with inverse kinematics I could just specify where I wanted the gripper to end up in the x/y/z space, and it could figure out the joint positions. I think that would pretty much be necessary if I wanted to do anything other than pre-scripted motions. And apparently inverse kinematics is too heavy of a calculation for microcontrollers to do, so maybe eventually I’ll have to connect this to a computer anyway.

Dan

Arms are really cool

Glad you are having fun with this, I’d like to try one sometime!

Here’s some Forth code for the same Lynx arm, not sure if it is helpful or not :

http://www.newmicros.com/isopod/appnotes/RCRelMove.txt

Not inverse kinematics, but think there are some IK examples for a hexapod robot.

Good bot

It’s a nice bot.

Question: Are there two motors working in parallel to lift the arm at the base?

Can you get it to write “LMR”? (Heh heh heh. THAT should keep you busy for a couple of weeks.)

PS - there’s someone strangling your cat in the background of the first two videos.

How do you move servos with a pot?

awesome!

So how do you manually control a servo with a pot?

Very nice!!!I have to work

Very nice!!!

I have to work with an Mitsubishi RV-1A robot arm in my company and I like to work with it.

The RV-1A is able to be operated in X,Y,Z-Mode. I’d like to know if this is also possible with your controller.

So you can use you Pots to move the “Hand” along a virtual X, Y or Z-Axis. I think, if you are able to do that, you can do anything with that arm :slight_smile:

Measure and reproduce
I’d say the pots are hooked to an ADC on the microcontroller. Their position would be noted periodically and a representative servo output generated from a digital port.

BoA is just about right. I’m

BoA is just about right. I’m not driving the servos directly with the pots, only using them as an input method. The Arduino reads the values of the six pots on its six analogue inputs, scales those 0-1023 numbers to the 500-5500 range used by the servo controller, and then sends the values to the servo controller, which then starts sending the new pulses.

Actually, I lied. Using the pots, I determined the range of values that each servo can move to without bumping into another arm segment or maxing out its travel, and so the microcontroller keeps track of each joint’s range of valid values, and it scales the 0-1023 value from the pot to the actual range of values that joint can travel to, like 931 - 3788, or something like that. That way I can still use the full range and resolution of each pot.

Dan

Nice, that sounds fun.

Nice, that sounds fun. Lately I’ve really been wanting to play with bigger, more complex and powerful robots. I’m jealous :slight_smile:

No, with the software I’ve written so far for the Arduino, I can’t control the arm using X/Y/Z coordinates. To do that, I’d need to be able to calculate inverse kinematics. Regular kinematics is calculating, based on the angle of each joint (i.e. the position of each servo), where the gripper will end up. That’s easy, just basic trigonometry and geometry. Inverse kinematics, on the other hand, starts with the position of the gripper, and calculates the joint angles you need in order to put the gripper there. That’s a lot harder :slight_smile: As far as I know, that can’t be done on a microcontroller (or at least not a relatively low-end one like the Arduino). It’d be nice though :slight_smile:

Dan

Yup, there’s two relatively

Yup, there’s two relatively high-torque servos (HiTec HS-475HB) at the ‘shoulder’. There’s also a spring connected between the base and the ‘elbow’ to help lift bigger loads.

As for handwriting, it’s already on my todo list. Frits says I’ll never manage it :slight_smile:

BullyBot! Leave Fluffy alone!

Dan

powerless math

About those pesky integers. Did you ever consider something I would call “doubling the word length”? I mean: to use variables internally (during the magic calculations part) that are twice as long (20 rather than 10 bits, or 32 rather than 16). Rework them to required length before output. Remember, in binary, multiplying by 2 is the same as one bitshift leftwards. Multiplying by 256 would shift eight positions. And vice versa.

Armchair disclaimer: Never done it myself. I always just multiplied by 1000 when I needed some 1/1000th precision in a fraction that was really an integer.

8ik

Hey, Dan… Now if you where

Hey, Dan… Now if you where recording some "key frames", and let your SW produce the steps in between, when ever shifting from one key fram to another… then you could;

Have up to 1024 keyframes "stored in each potmeter", and then when turning the pot, you could make it mooooovvvveee aannd liftveryfst :smiley:

This is how I do it

Any time I want to multiply two 8-bit integers, I put the result in a 16-bit integer. What can be very convenient is that the end result isn’t always very important, rather, the ratio (I suppose you could call it a “scaled” result) so where the numbers are predicted as being “sufficiently large”, you can simply discard the least significant byte of the result in order to obtain a 8-bit number.

sounds like my plan

That sounds a lot like what I had in mind.

How about divisions? How does your uC respond to an operation like 1/3 (both 8bit bytes)? Would that be an instant attempt at floating point math, or would it just result in an integer 0 (in an 8bit byte)?

8ik

Ahh, that’s right, I had

Ahh, that’s right, I had forgotten about that handy trick. I gave up on my attempt to replace my floating point calculations with integers, because often the values (such as ‘number of servo pulse increments per ms’) were less than 1. I thought of just multiplying the values, but then I’d have to divide them back down in the loop before sending the new value for each servo, and I thought that’d be no better. But you’re right, with integers they can be divided cheaply and easily as long as it’s by a power of 2. That might work after all, thanks. But first I’ve gotta fix the servo gear I broke when my function tried to divide by zero :slight_smile:

Dan

Hey, that’s actually a

Hey, that’s actually a really good idea too. I was thinking the pots wouldn’t be useful after I had found the positions I wanted for each keyframe, but you’re right, I could use them to move the robot back and forth through a scripted motion too. I don’t think I’d try to cram 1024 of them in there :slight_smile: But 5 or 6 could be really useful. Thanks :slight_smile:

Dan