March 27, 2014

What's Happening With the Robot Arm?

Not too much, sadly.  Term started, 2.007 started (introductory post to follow soon), and I've gotten mixed up in other side projects.

I have made a little progress on characterizing the arm's dynamics for feed-forward control as discussed at the end of the last update.  To start out I took some measurements to characterize the friction in the belt reductions.  Somehow in the past month my data from the 72 tooth reduction disappeared, but I still have everything from the 60 tooth one, and I remember they were virtually identical:


The process for calculating the friction was pretty simple.  I ran the motor off a bench supply at a constant current.  I then had the mbed spit back the steady-state angular velocity to my computer over serial.  Since I know the torque constant of my motor, I can convert the current draw read off the bench supply into torque produced by the motor.  Plotting all this data gives me a nice linear curve representing the friction in the belt reduction as a function of angular velocity.

While doing all this testing, all of a sudden the readings from one of my encoders got stuck.  I probed the encoder outputs, and found that one channel was stuck high.  I cracked open the encoder to investigate further, and found this:


Further probing around the inside told me something was wrong with the 339N comparator (the chip on the right).  Fortunately MITERS had some of these same chips floating around.  I cut the leads off the original and soldered a new one in its place:


This seems to have fixed things.  I can't imagine why the chip would have died in the first place though.

In terms of actual mechanical progress, I machined a new linkage to replace the carbon fiber one.  It's basically an aluminum I-beam, with clamping mounts at each end:



I also worked out the inertia terms for the arm.  At the end of the last post I stated that the inertia would change as a function of arm configuration.  Fortunately, this actually isn't really true.  The inertia as seen by the motors is actually independent of the configuration the arm is in.  Let me demonstrate.

First let's look at the inertia as seen by motor 1, which drives the arm's first link.  When that motor (driving link 1) rotates, the following happens:  The link 1 rotates about its pivot (C).  Link 4 rotates about its pivot (D).  Link 2 translates, following the motion of the end of the first link (B).  This is shown by the diagram below:



 So, the inertia seen by motor 1 (ignoring the effects of the belt reduction) it ID + IC + m2*L12.

Now the inertia seen by the second motor, which drives link 3:  Link 3 rotates about its pivot (C).  Link 2 rotates about its pivot (B).  Link 4 translates, following the motion of point (D).


So, the moment of inertia as seen by motor 2 is IC + IB + m4*L32.

The values of the various masses, lengths, and inertias can be determined form my Solidworks models of all the parts.  By assigning appropriate material properties to all the parts, and defining reference coordinate systems at the pivot points, can just click on "mass properties" and read off the values for moment of inertia.

Finally, to figure out the inertia as seen by the motor, I just take the values computed by the two formulas above, and multiply them by the square of the gear ratio between the motor and the links.  So ((18/72)2)2 for the first link and ((18/60)2)2 for the second link.

February 23, 2014

How to Build a Mini Electric Go-Kart in a Day

During the middle of some Friday night MITERSing, Mike, one of this year's crop of MITERS-frosh (also one of the people responsible for the recent revival of LOLriokart), decided to build a tiny electric kart or other small silly vehicle.  That night.  I joined in on the project, and within 10 hours we had a rideable go kart.  

At around 12:00 am Saturday we had a pile of kart-parts.  There's a pair of large scooter wheels, some 1.25" square aluminum tubing, some 1" x 4" rectangular aluminum extrusion, a Kelly KBS24121 controller, an EMP 63-200 motor (essentially identical in construction but a bit smaller than the trike motor), a big Colson Performa wheel, and a very old Brooks saddle.

All the parts were scavenged from around MITERS.  The motor, controller and saddle were mine, one scooter wheel came from an abandoned kick scooter, one came from Jaguar, the Colson came from the carcass of Straight Razer, and all the metal stock was scrap.


For batteries, we finished off a box of A123 18650 cells.  Five of them fit side by side in the inside of the rectangular aluminum extrusion.  We had enough cells for a 6S5P pack, which also happens to be the the most cells that could physically fit in the length of the extrusion.


Unfortunately, the incredibly short timespan over which this was built means my documentation is pretty poor, so there are not many intermediate construction pictures.

The back wheel and motor were both bolted to some U-channel, which was in turn bolted to the rectangular extrusion.  Don't worry, the wingnuts were eventually replaced with locking nuts.


I did most of the machining of the steering assembly.  I made the steering as simple as possible for quick construction, so doesn't have Ackerman steering or anything fancy like that.  The steering is actually completely non-adjustable, since the tie rod is a solid square aluminum bar with holes drilled through it at the pivots.  The steering column is supported by a big chunk of round Delrin which is pressed into the aluminum frame, and the column itself is 1/2" polished steel shaft.  I first tried cutting it with a hacksaw, but after trashing one blade I realized it was hardened, so I milled through it with a little carbide endmill I picked up for a dollar at Swapfest.

To test the handling, we pushed it around with some clamps attached as temporary handlebars:


The steering knuckles were machined from some 1" square aluminum.  At one end, they have a 1/2" hole through them, through which pass the bolts the wheels pivot around.  A little thrust bearing is sandwiched between the knuckle and it's supporting plate.  These bearings were found in a drawer of random bearings, and were labeled "Precision components, handle with care!".  So much for that...


For a seat, we used an old Brooks saddle.  It was clamped to a segment of 3" square tubing, which was fastened to the frame through the same holes as the motor and wheel bracket.  


Mike quickly threw together an electronics system with some parts from his electric longboard, so we could ride it.  These were a Hobbyking 120A car controller, a 4S hardcase LiPo (same as the ones in my scooter), and a really sketchy RC car remote with a broken trigger:  All duct taped to the frame.  As of around 9 am on Saturday morning, the kart looked like this:


We searched long and hard for something silly to use as a steering wheel, but eventually just bolted on a length of 80-20 extrusion, as a nod to all the 80-20 go karts out there.


At this point, the kart was driveable:



The electrical system was far from ideal, so it was replaced Saturday night and Sunday morning.  I worked on assembling the new battery pack, while Mike got the Kelly controller ready and set up one of Charles's hall sensor boards.

I started off by gluing together sets of 5 cells in parallel.  These were soldered together with a strip of copper braid across each end.


These six modules were then connected in series with more braid.


Balance connectors, power leads, and insulation and padding at the terminals was added.  The big red power lead shown was actually replaced with some insulated copper braid, because the round wire took up just barely too much space for the pack to fit into the aluminum tube.


Here is the battery pack next to the frame.  More insulation was added before sliding it down the tube.  Actually shoving the battery in was a hair-raising procedure.  To install the battery, I had to lightly lubricate the outside of the pack's insulation to prevent it from getting stuck part way down.  On the first attempt, the little bulge where I spliced together balance wires got caught on the inside edge of a bolt hole, which removed a tiny speck of insulation from the balance lead of the second to last cell.  There were a couple little sparks, and the frame was floating at 17V relative to the negative end of the battery.  We disassembled the front end of the kart, and pushed the battery back out a few inches.  The trouble spot was reinsulated, and then protected from any sharp edges with some thin plastic sheeting.


Once the kart was reassembled, we rigged up the Kelly and began playing with hall sensors and motor phases to get the motor commutating properly.  First time around two of the hall sensors we used turned out to be dead, so I had to replace them.  After that, everything worked great, and it only took a few minutes to get the motor spinning the right direction.  Adjusting the sensor timing took a bit longer, since I had to extend the slots in the sensor board to get it positioned at the optimal spot.


The final kart:  I haven't weighed it, but it probably tips the scales at 20-25 pounds.  Top speed is only 15 mph, so it will be a good indoor and demo vehicle.




Now it's time to recover a weekend's worth of sleep.

February 8, 2014

Robot Arm, Now With The Drawing Ability Of A 5-Year-Old

Last update I was bad at serial and the robot arm almost exploded itself.  I quickly made my serial communication less stupid, and added some features like a checksum, which stopped the robot from behaving so spastically.  However, no matter what I did I was unable to get smooth motion while streaming serial commands.  The robot would follow the path smoothly for a few seconds at a time, but would be interrupted by jerky motions I could not diagnose.  One strategy for fixing this might be buffering the serial commands rather than executing them as they arrive.  For now though, my Python script simply generates a text file with all the commands, rather than streaming them over serial.  I can then copy the text file to the mbed for it to execute.  While more time consuming to change paths, this method has been much more (read: completely) reliable.

So here's the robot drawing some things:

Fast squares:



Writing "MITERS":



Here are some mediocre squares.  I've gotten it to draw better ones (without weird corners) since this since, but it's actually roughly the size it's supposed to be:


This is what happens when I try to draw 10 cm squares at a few Hz..... the "circles" were also drawn at the same frequency.  There are a couple reasons why it looks to terrible.  First the robot was shaking the table it was on.  Second, the paper was held below the pen by my hands.  These two problems were responsible for probably at least 2/3 of the waviness.  The remainder was caused (I think) by flexing in the linkage between the second link of the arm and its motor.  It might not be reasonable to expect the arm to be able to draw three perfect squares per second, but I can definitely get them a lot better than this.


Here's what the "MITERS" text looks like.  Once again, I was just holding the paper below the arm with my hands.


I've started simplifying my method of path generation.  Right now, I feed my python script some setpoints.  It interpolates between these points at whatever step size I choose, converts these X-Y positions to arm joint angles through the robot's inverse kinematics function, and then turns those angles into encoder counts which are loaded onto the robot.  Eventually I want to write a G-code interpreter to make path generation easy.

On to some hardware.  I made a quick pen holder out of a botched elbow joint I machined a while ago:


I also made a quick demo-frame out of 80-20 for Techfair.


Action shot:


I am working on replacing the carbon fiber linkage assembly with something that can't twist where it connects to the pins at the pulley and arm:


Back to some robot control stuff.  In the above videos, you may notice the tones the robot generates while moving.  This tone corresponds to the frequency at which I have the robot arm read points.  Right now, the arm only has position control, so when it gets a new goal point, it attempts to travel to and stop on that point as fast as possible.  So my servos are kind of trying to be stepper motors.  To smooth out motion, I plan on implementing some velocity control on top of the position control.

At the high level, velocity control is pretty simple to explain.  When reading through the list of points to move to, the robot will look ahead a step.  By looking at the position change required between the current step and the next step, it can figure out how fast it needs to be moving when it arrives at its current step.  For example, if one of the motors has a current goal position of 100 (arbitrary units), a next goal position of 101, and the time between steps is one second, when the motor reaches position 100 it should be moving at a speed of around 1 per second.  If the current goal is 100, and the next goal is also 100, the motor should be completely stopped when it reaches position 100.  The actual velocity control will be done by a PI velocity loop running within the position control loop.

So that sounds great, but it makes a big assumption:  that you actually have a good idea how fast your motors are moving.  For my position control loop, I determine the motor velocity for the D term of the PID loop by taking the difference between consecutive position readings.  The issue with this is that encoders are digital.  When you try to sample the velocity really fast by subtracting position readings over very short time intervals, you lose resolution in your velocity measurement.  So this method is no good for running a very fast velocity control loop.  Also, I have been feeding my robot new points faster than I am able to sample for velocity, meaning that a velocity loop would be too slow to do anything.

Skimming through a bunch of papers on servo control loops, I found that my problem was not at all unique to my system.  Turns out the solution is to estimate the velocity at a high rate, and then update your estimate at a lower rate with encoder feedback.  Estimating the motor velocity will work pretty similarly to my python script to simulate the arm back at the beginning of this project.  A guess at the change in velocity over a cycle will be made by calculating the predicted acceleration of the arm given the arm's inertia, the motor's torque-speed curve, the previous command to the motors, and the loop time.  As actual measurements from the encoders are collected, the estimated velocity will be updated.  This will involve figuring out more precise values for inertia and frictional torque in the system than I've used before.  Also, the inertia of the arm's first link will be some function of the angle of the second link, which will make things a little trickier.

So there's a lot more work to be done.  At some point I need to add a third axis too....

January 28, 2014

A Tale of Two Robot Arms

The robot arm is now moving.  I started out by writing simple PID position controllers, and then making the motors do some fast back-and-forths.  Nothing is at all tuned right now, and I imagine my whole control loop will get fancier as I take 2.004 next term and learn how to actually do controls.

The basic control structure of the robot arm is this:  At the highest level, my computer runs some python code.  This code takes XY-space commands and does the inverse kinematics for the robot arm to convert XY to two joint angles, and then sends the joint angles over serial (using pySerial) to one of two mbed microcontrollers.  The mbed keeps one command to itself, and sends the other along to a second mbed over SPI.  Each mbed reads the encoder signals from the motors and uses that plus the commanded positions from my computer to do a PID control loop for each motor.  Finally, the mbed's send PWM and direction signals to a pair of Pololu motor drivers, which actually drive the motors.

For the sake of the robot arm and anything in its plane of motion, early testing was done without the arm attached.  Here's the linkage drive doing a 10 Hz shake:



And the arm's first link moving:



Once I got the core of my python code mostly working, I could send position commands from my computer:



Or so I thought.  Here, the arm was supposed to do a 1 Hz, 10 mm amplitude Y axis sine wave.  And it did, for a bit:


Somehow the arm managed to not crash into its physical limits, so nothing was damaged.  As far as I can tell, the problem was with my serial communication.  I added identification commands to the beginning and end of each block joint angles as a safety feature, so now the robot just stops when the commands go wrong, rather than freaking out as above.  Also, I'm now testing with the motor power supply at 5V rather than 20+, so the max speed and torque are much, much less dangerous.  After incident this I added an emergency stop button.


Which leads perfectly into the story of robot arm number 2.  The e-stop button and panel above came from the silicon wafer handling enclosure for a Stäubli RX60 robot arm.  A while ago MIT professor Seth Teller contacted MITERS looking for a home for this robot.  It turns out the robot arm was not just a robot arm.  It was actually a 100 lbs arm with a 200 lbs controller inside a 2,800 lbs box.  A very, very fancy box for inspecting silicon wafers.

Nancy, Peter and I went to retrieve the arm from its box, which was all stored at a storage warehouse just down the street.


And inside the box:


So shiny....  Everything was paneled in brushed stainless steel.  The e-stop panel I used can be seen in the middle left.


And the exciting part.  6 axes of robot-arm goodness:


Most of the important bits were Mikuvanned back to MITERS.  The robot was screwed to a table for temporary testing.


I pulled a couple of the panels off to see what sort of magic was on the inside:


Those are some fancy servos.  The two largest joints are driven by 200 V, 1 kW(!) servos.  That much power in an arm is kind of terrifying.  I couldn't tell what type of gear system was used, but but excepting the rotation at the writs, the joints do not appear to be backdriveable.

January 24, 2014

Fun With Encoders

Time to play with some microcontrollers!

For now I'm starting out using the mbed platform.  Think Arduino but faster and fancier.  I spent a lot of time using these in the lab over the summer, so that's what I'm using to get things up and running.  Eventually, I'd like to switch over to a BeagleBone Black, but there's a fairly large learning curve there that I'm not going to jump into just yet.

To sample the encoders, I first used the convenient QEI library.  Testing with this quickly showed me that one of the stock encoders was borked.  Upon opening it up, I could see a chip out of the encoder's glass optical disc.  Disassembling it revealed even more sadness on the surface of the disc.


Fortunately, I had a pile of fancy encoders scavenged from a lab cleanout over the summer, so I grabbed one of those.  The stock case and connector were extremely bulky, so I 3D-printed a new shell.

Stock:


Modified:


The new encoder is coupled to the motor by a timing belt from the motor's back shaft, and is held in place by some pieces of laser cut Delrin.


Adding this new encoder made another problem apparent.  The new encoder has 2,500 lines per revolution, over the stock encoder's 500, giving a resolution of 10,000 steps per revolution in quadrature mode.  The QEI software library just couldn't handle the pulse rate.  I could manually wave the robot arm around and get the microcontroller to lose track of the encoder's location

Fortunately, it turns out that the processor on the mbed has a built in hardware quadrature encoder interface.  However, on the mbed the pins corresponding to the interface are used up by indicator LEDs.  Some clever guy figured out how to use them anyway, by soldering wires to tiny pads on the bottom of the PCB, and wrote a driver as well.  Each board only has one such interface, so I'll need to use two of them to drive the motors.  To sync everything, they will eventually communicate with each other over SPI.    The hardware QEI seems to have solved the speed problem.  I can wave the arm around as fast as I want manually without it skipping a step.

I also assembled some boards to interface all the electronic components together.  From top left, clockwise are terminals for power supply and motors, a pair of motor drivers with added heatsinks, two mbeds, and two encoder breakouts.


Up next:  writing some kind of control loop so the robot can actually do things.

January 18, 2014

Now It Looks Like A Robot Arm

In the last month I've more or less finished the hardware side of the robot arm.  For the two fast axes, at least.  I'll deal with the z axis later.

Finishing the arm required a few big machining operations, especially for the elbow joint.  Naturally, I made these parts from big bricks of aluminum billet.  Elbow Part One started out as some 2" square billet, which I faced to size manually on the CNC mill, since the MITERS Bridgeport was temporarily out of commission.  On my first attempt at making this part, I discovered that when plunging into a pocket with a large endmill, the CNC mill's spindle stalls really easily.  Even with .5 mm plunges this occurred.  To resolve this, I manually drilled big pilot holes for the circular contours.  After the first CNC job, the part looked like this:


And after two more CNC jobs and one manual one, it was almost done.  It's a little sad that when you machine something this way 90% of the metal goes into waste chips.  But not nearly sad enough that I won't do it anyway.


I manually added the slot and tapped holes for a clamping mechanism.


When I ordered the pulleys for the belt reductions, I had a different design in mind for the plastic reduction than I ended up using.  In the final assembly, the output plastic pulley was torqued by the linkage it drove, causing it to deflect significantly.  To get a bit more precision, I got a nice aluminum pulley to replace it.  I drilled some big holes in it for moment of inertia reduction, and CNC milled plates for the linkage to attach to.



The second part of the elbow joint was machined manually out of some 2" round stock.


The driving link was made from some unidirectional carbon fiber tube I found lying around MITERS.  It is clamped at each end by a piece of aluminum that passes through the pairs of bearings on the pulley and elbow.  While turning the aluminum clamps, I found that the MITERS lathe turns a pretty significant taper.  To get a tight fit in both the bearings, I had to remove the taper by taking extra small passes off towards the chuck.



Hey, it looks like a robot arm now!  




For the time being I am going to ignore the z axis, and work on assembling the electronics and programming the thing, so that I can have something interesting and moving to display at TechFair.