May 4, 2016

More Jumping

Last night I reworked all the communication to happen directly over serial, and hooked the leg up to a more capable power supply.  Performance was greatly improved.  Now the leg can max out the travel of the linear guide it's fixed to:


And the obligatory animated GIF:


That jump was actually still with a current limit set on the power supply.  Turning up the supply to max current, the leg can easily crash into the hard-stop at the top of the linear rail.  It actually managed to move the hard stop by a couple millimeters - I dialed back after that, because if the bearing manages to escape the rail, all the little recirculating balls will fall out.

I almost set it up for wireless control over XBee, but decided to take a nap instead.  Wireless communication with a small LiPo battery fixed to the leg, and no cables dangling off would be beautiful.

April 24, 2016

Jumping Leg

After 2 days of debugging (and only partially fixing) a mysterious SPI communication bug that appeared out of nowhere, here's a jumping leg:





A few things to note:
  - This is with current limited to 40 amps on the motor side.  For more current, I'll need to a smaller phase current shunt.  The current limit definitely gets saturated here.  The boards and motor can't handle that current continuously without real cooling, but seems to handle it just fine in bursts.
 - The linear bench supply powering things got pretty sad here.  You can hear/see it click into constant current mode, which certainly doesn't help jumping performance, and see the voltage spike as the leg lands and motors regen.  Needs more battery.
- This is at 12V, not the maximum 24-ish the controller's can handle.  Also, at peak motor power, the supply sags to ~8V, which may significantly affect jumping performance.

GIF infinite loop mode:


April 22, 2016

I'm Back to Building Robot Arms

Not really, but a sideways leg is basically a SCARA arm, right?

I milled out a simple 4-bar linkage leg.  Leg dimensions were roughly taken from the SMC robot.  It's really fun to prod at with different joint parameters.  Each motor controller takes joint position, stiffness, and damping commands in over SPI:



I threw together some quick Python command line tools for setting the joint parameters in real-time:



Time to strap it to a linear rail and make it jump, then hide away for a couple weeks to write my thesis and finish the other stuff I need to do to graduate.

April 13, 2016

Torque Ripple Characterization and Position/Impedance Control

I promised more science, so here it is.  I took some measurements of my motor's torque ripple  - its variation in torque with rotor position - at different current levels, to see how bad the ripple is, how easy it would be to compensate, and get a sense for how well my motor control is working.

The basic idea for this experiment was apply constant current to the q axis, and measure the torque out of the motor as a function of rotor position by slowly rotating the rotor through a single mechanical rotation.

The setup, from left to right:
Indexing head, a rewound 80-100 motor acting as a shaft, an S. Himmelstein rotary torque transducer, my Multistar Elite motor, and an optical encoder.


At the center of this setup is the the in-progress motor dynamometer I've slowly been working on, which will get documented in its own set of posts later.  The absorber (the 80-100 sized motor) is unused in this setup, and just acting like a shaft between the torque transducer and the indexing head.  The indexing head was used to slowly rotate the rotor.


I made an ER-32 spindle for the torque transducer, for ease of coupling to arbitrary motor shafts.  For these measurements, I used my test-motor setup with optical encoder, because coupling my motor module  pre-gearbox would have been difficult.


Here's the data out of the setup.  Turned out surprisingly well, I think.  Cogging torque shows some ripple at 2x electrical frequency as well as a higher frequency component.  Total cogging amplitude is plus or minus .025 N-m.  Bumping up the Q-amps, overall amplitude of torque ripple doesn't change too much over cogging torque, but becomes noticeably spikier.   I think some cogging torque compensation (which should be easy to implement via a  lookup table) would smooth things out pretty effectively.  But that's an exercise for a later date.  Straight lines in the plots are sections where I'm missing part of a rotation.


For the higher-current tests, I pointed a big fan at my motor and inverter setup.  Thanks to the wonders of modern FETs, the wires going to the motor were the hottest part of the setup at 24 amps, followed by the electrolytic capacitors, then the motor itself.

I wrapped some position and impedance control around my FOC scheme.  For the sake of running robots, high performance position control isn't particularly desireable - instead you often want to control leg stiffness and damping, so the position control is just a PD controller.  The proportional term corresponds to spring-stiffness of the joint, while the derivative corresponds to damping (both ignoring rotor inertia).  Here's what some different levels of springiness and damping look like:


Getting good damping performance is dependent on good velocity measurement, which is not trivial.  The gist of the problem is that differentiating your position signal sucks.  By the time you can filter the differentiated signal enough to have a nice looking velocity, the phase lag caused by the filter ruins your signal.  Fortunately, the MA700 sensor I'm using for position sensing has an encoder output as well as an absolute position output.  I'm able to use the encoder output to my advantage for velocity measurement.  By configuring one timer on the STM32F4 in encoder mode to keep track of encoder count, and then configuring another free-running timer as a slave which resets whenever the count changes, I'm able to automatically capture the time between encoder edges.  This gives a value inversely proportional to the motor speed, which gives good results for velocity measurement when combined with some logic to handle the zero-speed case where the count isn't changing.

With dumb differentiation (at my encoder resolution and sample rate), here's what a velocity output would look like.  Most of the time velocity is zero (because encoder position doesn't change during one sample period), and for samples where the value has changed, the velocity is 1 encoder line width divided by the sample period.  You can try to filter this signal, but the results are not at all satisfactory.



With the encoder period measuring scheme, here's what velocity estimate looks like, both using the raw period value and with some simple 1st order extrapolation to estimate between edges.  Much better.


It's a simple concept, but took about 4 days of staring at the STM32F4 reference and ST forum to figure out how to get this implemented natively.  And now that I have this code, I can stick it on my closed-loop subwoofer for improved performance there.

Next step is to build up another motor module, and cram two of these into a 2 degree of freedom leg.  And go copy and paste my blog into a latex document write my thesis, which is due in three weeks....

April 5, 2016

Motor Module

Another fairly unsubstantial post (as far as technical details are concerned), but pretty pictures.  I promise there'll be more science in the future.

Here's a motor + gearbox + position sensor + controller module assembled:



Cute feature:  The FETs on the bottom of the board heatsink to the flat spot on the gearbox.


At the other end is a small diametrically magnetized cylindrical magnet, glued to the rotor, and MA700 chip sensing magnet orientation.




Here's it spinning with the gearbox open.  Nice sound of dry-running spur gears:



March 22, 2016

New Boards!

I finally put the finishing touches on the 2nd revision of motor control boards, and sent them out to get made.  Here's the layout I sent to 3pcb:


I waited a couple days after receiving the boards for the new MITERS rework station to show up.  It has a heater below the board that preheats everything, and a hot air gun on an arm.  Assembly, especially of the TSOP-package parts, was far more pleasant than first time around and turned out way better:



Here's the first one assembled:


There are supposed to be little 1mm pitch JST connectors on the bottom for programming, sensors, and communication, but my cables haven't showed up yet.  So for now I'm just programming through soldered in wires.


Controller next to a motor.  I strongly considered making the controller the same footprint as the motor, so it could be directly bolted on the back of the motor, but ended up not.  Maybe I'll do that for version 3.


Next to the Nucleo and shield it replaces.



I haven't actually driven a motor with it yet (waiting for JST cables to show up), but I've programmed it and confirms it PWM's, bridge doesn't shoot through, etc, so things are looking hopeful.

February 28, 2016

Planetary Gearboxes

I made a little single-stage 6:1 planetary gearbox for one of the motors. 


Cross section, so you can see the bearing arrangement.  For compactness and maximum bearing spacing, the planet carrier is supported on either side by bearings, rather than cantilevered as they usually are.


Parting a bunch of 20 tooth planets off some gear rod stock.


To reduce backlash and make everything generally smoother, the planets have ball bearings pressed into them.  The inner race of the bearings are pressed onto the planet carrier.  Usually the planets ride on pins with bushings, which will contribute to backlash and friction in the gearbox:.


To machine the planet carrier and housing, I had to calibrate the MITERS CNC mill, which hadn't been fully calibrated after its LinuxCNC upgrade.  The ballscrew pitch (which we previously didn't know) was figured out by drilling and reaming a set of holes, pressing in dowel pins, and measuring the spacing between the pins.  The number of encoder ticks (thus revolutions of the motor) and this distance were used to calculate the pitch, which we then rounded to the closest reasonable number (the measurement was off by ~.04%).  With the pitch correct, I then calibrated the backlash in the X/Y axes.  Final result machining a 20mm circle was dead on in one axis, and + 9 microns in the other axis.  Not too bad.



1/2 a planet carrier:


Front half of the housing:


Back half of the housing.  The ring gear was machined from a chunk of BaneBots P80 ring gear.  You can make ~8 of these from a $23 section BaneBots ring gear, while a comparable gear from SD-PSI costs ~$50.


Pinon shrink-fit onto the motor shaft:


Output half of the planet carrier installed:



And...I forgot to take a picture of it fully assembled.  Oh well.  This is a test gearbox, so I probably won't end up using it in a leg, but we'll see.  KHK Gears also sampled me some ring gears, planets and pinions to build up a pair of gearboxes.  I'll probably end up using those for a actual leg, because they're finer pitch (.5 Mod) and I expect them to be a bit smoother, since 1: I didn't have to part them off larger stock, and 2: they're make by the same manufacturer and designed to used in planetary gear sets.

Also, here's a sneak-peak at version 2 of the motor control board.  All-in-one this time, not a Nucleo-stack.  I still need to finalize position sensor before I finish routing in connectors, but it's really close to being ready to send out.  Total size is 35x52mm.