All posts by Josh Pieper

Making the reduced weight servo mk2

Earlier I described my design plan for reducing the overall mass of the moteus servo mk2.  Constructing a prototype of this turned out to take many more iterations and time than I had expected!  Along the way I produced and scrapped two front housings, two outer housings and a back housing.

dsc_0095
Soooo much PocketNC time for naught!

I made one complete prototype which only had the weight reduction applied to some of the parts and lacked a back cover and any provision for a wire cover.  It was the one from the moteus controller r4.1 juggling video:

dsc_0098

dsc_0096-1

Because of the multiple tries on the large-for-me front and back housing, I had to make soft-jaws and prepare stock in a more efficient manner.

I also had to get new workholding solutions for the PocketNC in the form of the wcubed vise.

Design updates

Every one of the pieces got reworked in some manner or designed from scratch for the things that did not exist previously.

Front housing: Here I iterated on how much material to remove from the central cavity.  Initially I removed more, but it gave the primary output bearing problems to be loaded intermittently.  Also, I had adhesion problems with the ring gear when too little material was left there.  I settled on a continuous ring for the output bearing and a decent amount of material for the internal gear.

20200107-front-housing-left20200107-front-housing-right

Back housing: I tweaked the back housing mounting points so that the outer housing could be symmetric.  Also, I added a facility for the wire cover to guard the phase wires entering the controller.

20200107-back-housing-left20200107-back-housing-right

Outer housing: The outer housing was largely unchanged from my initial weight reduced design, although I produced one bad one due to a simple mistake locating the mounting hole, and a second because the stud lengths between the front and back were different in an earlier iteration.

20200107-outer-housing

Planet output: The planet output design changed only to add some weight reducing cutouts.  This was the last part for which I was still using mk1 servo spare parts for, so now I actually manufactured a prototype in house.

20200107-planet-output-left20200107-planet-output-right

Planet input: Here there are now weight reducing cutouts, and the mating studs use less material.

20200107-planet-input-left20200107-planet-input-right

Back cover: The back cover design is basically unchanged, I just had to make one for the first time.

20200107-back-cover-left20200107-back-cover-right

Wire cover: The wire cover is a part of the design I had deferred until now.  It bolts to the back housing and shrouds the phase wires.

20200107-wire-cover-right.png20200107-wire-cover-left

Assembly

Here’s some assembly pictures:

dsc_0093
All the machined pieces prior to assembly

 

dsc_0099.jpg
Bearings installed in front housing and planet output
dsc_0101
Planet output and ring gear installed
dsc_0103
Stator installed
dsc_0104
Planets installed and pins in planet input
dsc_0106
Rotor and outer housing
dsc_0112
Back housing, controller, and wire cover
dsc_0113
All put together!

DSC00168

DSC00171

 

C++20 coroutines and moteus_tool

I’ve had a confusing mismash of development tools for the moteus servos for a while now.  My original development tool was in python, which worked just fine.  Coroutines allowed me to express complex asynchronous logic succinctly, the program itself was rather simple, and I could easily integrate it with matplotlib for plotting.  However, when looking to run this on the raspberry pi, I needed a newer python version than came with raspbian, which turned out to be a royal pain to get installed in a repeatable manner.  Thus I rewrote a portion of the moteus_tool in C++ and just used my normal cross-compiling toolchain to generate the binaries.  What I didn’t do was port the calibration logic, as the state machine required with standard boost::asio would have bloated the logic size by 5x, and I didn’t really need to calibrate servos from the raspberry pi ever.

Still, I’ve wanted to consolidate these tools for a while now, and while working towards other telemetry and development tool goals, I decided to make another pass at removing the duplicity.  I figured it was time to try using the new C++20 coroutines to implement the asynchronous logic in C++ and see if I could get rid of the python tool.  Since I’m currently vendoring all the compilers and libraries for the C++ applications, I am already running clang-9.0 with libc++ and boost 1.72 for all the host side tools which theoretically should all support coroutines just fine.

Why coroutines?

To recap, typical callback based boost::asio code looks something like this:

void DoSomething() {
  boost::asio::async_write(
    *stream_,
    boost::asio::buffer("command to send"),
    std::bind(&Class::DoneWriting, this, pl::_1));
}

void DoneWriting(boost::system::error_code ec) {
  FailIf(ec);
  boost::asio::async_read_until(
    *stream_,
    response_,
    "\n",
    std::bind(&Class::HandleRead, this, pl::_1));
}

void HandleRead(boost::system::error_code ec) {
  FailIf(ec);
  // Do something with the result.
}

This gets even worse if you have embedded control flow.  Typically the best you can do is construct an object to hold the state, and bind it around to keep track of things:

struct Context {
  int iteration_count = 0;
};

void Start() {
  auto ctx = std::make_shared<Context>();
  Write(ctx);
}

void Write(std::shared_ptr<Context> ctx) {
  message_ = fmt::format("{}", ctx->iteration_count);
  boost::asio::async_write(
    *stream_,
    boost::asio::buffer(message_),
    std::bind(&Class::HandleWrite, this, pl::_1, ctx));
}

void HandleWrite(boost::system::error_code ec,
                 std::shared_ptr<Context> ctx) {
  FailIf(ec);
  ctx->iteration_count++;
  if (ctx->iteration_count >= kLoopCount) {
    Done();
  } else {
    Write(ctx);
  }
}

Now, when coroutines are used, you can relinquish control with a simple “co_await”, and all the logic can be written out as if it were purely procedural:

boost::asio::awaitable<void> Start() {
  for (int i = 0; i < kLoopCount; i++) {
    auto message = fmt::format("{}", i);
    co_await boost::asio::async_write(
      *stream_,
      boost::asio::buffer(message),
      boost::asio::use_awaitable);
  }
}

Not only is this significantly shorter, it more directly expresses the intent of the operation, and lifetime of the various values is easier to manage.  No longer do we have to keep around the buffer as an instance variable or a shared ptr to ensure it lives beyond the write operation.  It stays in scope until it is no longer needed like any other automatic variable.

moteus_tool

Switching moteus_tool to coroutines was straightforward, and resulted in a big reduction in the verbosity required.

Moteus controller devkit PCBs in house

Update 2020-01-15: All the development kit slots are full.  Thanks for your interest!

I’ve now received all the supplies I need to make up development kits for the moteus controller and to make a test quadruped!

I’m planning on making a few development kits from this production run so others can experiment with the moteus brushless controllers.  Some people have already expressed interest in getting one — you have hopefully been contacted earlier.  If you are interested in getting an opportunity to buy an early access kit and haven’t heard from me yet, fill out this form!

I expect the development kits to clock in at $199, and include everything you need to power and communicate with the moteus controller, as well as a brushless motor to test with.

dsc_0133
Some fdcanusb boards
dsc_0150
The moteus controller r4.2
DSC00164.JPG
An in-progress moteus development kit
dsc_0149
Lots of moteus controllers!

 

 

Lots of frameless stators and rotors

While gearing up to make some dev-kits followed by a pre-production run of the moteus servo mk2, I recently received a bunch of frameless rotors and stators.

dsc_2225
It’s almost taller than me!
dsc_2228
Some stators
dsc_2230.jpg
A rotor

As with the other custom items, I’ve got some spares of these for sale at shop.mjbots.com if you’re building along with me!

Now it’s time to start building some servos!

 

wcubed vise for Pocket NC

Just because I’m generally looking for workholding solutions for the Pocket NC, I recently picked up a vise designed for it from wcubed.co.

vise.jpg

Unlike the stock vise that comes with the PNC, this has two movable aluminum jaws.  It can probably hold with greater force than the stock vise, since there is a larger contact area, although the screw mechanism doesn’t necessarily apply the force all that uniformly.  Also, since both jaws are movable, you have to take some care to either manually center things, or do some edgefinding, which isn’t terribly easy on a PNC.

What it does allow though, is clamping narrow things.  The stock vise bottoms out at around 0.5″.  This vise can go all the way down to 0.

That came in handy with some recent moteus servo parts that I wanted to do a “5-axis” style toolpath from 3/8″ thick bar stock.

dsc_0045
Is it really that tall?

The vise provided plenty of clamping power to hold and machine at the tip of this awkwardly long bar.  This cut does chatter like crazy, but that’s about what you would expect.

 

Preparing stock on a CNC Bridgeport

As mentioned previously, I made up some soft jaws to hold 4in round stock in a 6″ vise.  My goal was to prepare stock for workholding on the Pocket NC v2-50 to machine prototypes of the front and back housing for the reduced weight moteus servo mk2.

Now, I’ve used those soft jaws to trim down both pieces of stock to the correct length, bore a center hole, and in the case of the front housing, remove a bunch of additional material in a more expeditious manner.  There’s not much more to it than that, so here’s the video:

First soft-jaws for CNC machining

While working to build the reduced weight moteus servo mk2, I got tired of hand machining the first operation on a manual mill and lathe for the front and back housings.  It was necessary, primarily to enable workholding on the PocketNC v2-50, but also because it allowed me to remove much of the excess material more quickly than could be done on the PNC.  So, I got trained up on the AA CNC Bridgeport and went to town.

The manual work I did on the mill used V blocks to hold the round stock, but for this I wanted something that was more repeatable and would offer more gripping power.  Thus I decided to try my hand at soft jaws for the first time.  I got some blanks from MonsterJaws which would fit the vise there and got started.

For the CAD/CAM, I grabbed a random 6″ Kurt vise model from the interwebs and stuck my part in it.  Then I added the vise blanks and used a “combine” operation to subtract out the stock from the blanks.

20200105-stock-in-vise.png

Then, when doing the CAM, I just ran a 3d adaptive followed by a finishing contour pass:

20200105-soft-jaw-cam

When I ran the actual toolpath, I messed up and had the spindle running about 1/3 of the speed I wanted, which made for some nice chomping noises, but it did cut.

dsc_2242
Blanks ready to cut
dsc_2245
Stock mounted!

Endurance testing moteus controller r4.1

Before ordering a bigger batch of the new moteus r4.1 controller, I wanted some assurance that it would be able to run for an extended periods of time under representative loads while not breaking or having thermal issues.

dsc_2095
r4.1 mounted up

When I did this for the r3.1 controller, I had 2 motor joints and a planar leg built and did a jumping endurance test.  I could have done that now, but building up a leg fixture was more work than I wanted to mess with at the moment, so I went with a simpler approach:

dsc_2074
Getting ready…

I joined two of my fun past-times, robots and juggling!  I printed up an arm with a pocket, stuck a 1lb (450g) juggling ball in it, and set the thing throwing.  Mind you, this is probably one of the worst juggling robots in existence, I only built it to stress test the motor controller.  I’ve had it throwing the ball now for several hours at 4Nm without dropping, here’s a video of some of the testing.

 

 

 

My first non-Fusion generated g-code

While working to build a weight reduced moteus servo mk2, I reworked my outer housing CAM to do all the machining on the Pocket NC v2-50.  For this part I didn’t necessarily need any challenging workholding and since I could get the stock in tube form, there wasn’t an inordinate amount of material to remove either.

The one challenge is that when mounted in the Sherline Chuck, the mill can’t actually reach all the way to the edge of the part without hitting the X travel limit (which is why most of the other 100mm diameter parts I do are fixtured slightly off-center).  In this case I tackled the problem in two iterations.

Iteration 1

For the first iteration, I just used an adaptive clear from 8 different directions to get most of the material out of the way, then used a multi-axis “flow” to finish the outer diameter causing the B axis to rotate while the end-mill remained roughly in place.  Then a subsequent pass came in from the top to clean up all the stuff that was left behind.

20191216-outer_housing_3_plus_1.png
Coming at the problem from all sides
20191216-outer_housing_od_finish
A “flow” toolpath to do the outside

This worked, but had a couple of problems.  First, it was slow.  A full cycle time was something like 10 hours, largely because all the adaptive clears spent a lot of time not removing much material and rapiding around.  Second, it left a non-ideal surface finish on the outer diameter.  The “flow” toolpath for some reason seemed to jiggle the mill around in X and Y for no great reason, and occasionally sped the B axis up by like 3 times the normal rate for a quarter revolution for no apparent reason.

Iteration 2

I figured this would be a lot easier if I could just have more control over the mill while spinning the B axis.  I could take all the extra material off the top using the side of the cutter, and produce a nicer surface finish on the outside.  Since that wasn’t possible within Fusion 360, I figured this wouldn’t be a terrible time to try doing some “manual” g-code for the first time.  The “manual” is in quotes only because I ended up writing a python script to do the actual generation.

To begin with, I started with the g-code from a Fusion 360 generated toolpath so that I could get the tool setup, probing and such configured in a way that I knew the Pocket NC would accept.  Then my python script had two options, the first generated the g-code to turn down all the material on the top of the stock to the final length.  It moved the mill into position, spun the B axis by 340 degrees, then gradually moved down a Y step while moving 20 degrees, then spun another 340 again until reaching the end.  This worked out just great, used much more of the cutting length of my Datron 4mm mill, and got done in something like 20 minutes.

The second option in the script was for turning down the OD to the final size.  This used the same basic approach, but instead of setting the Z past the inside of the tube, set it to exactly the OD.  The the Y stepped down in the same manner as before, just over a different range (the top of the finished part to slightly past the bottom).

This got me to where I could start on the internal features in only about 40 minutes of Pocket NC v2-50 time, which is a big improvement over a trip to Artisan’s Asylum and an hour on the lathe in order to get it set up, turning the part, and then cleaning up.

 

Bringing up the fdcanusb

I introduced the fdcanusb previously, now I’ll describe some of the process and challenges in getting it to work.

Hardware

My initial challenges were around the PCB design and manufacturing.  To begin with, my very first revision was sent out for manufacturing with the same incorrect pinout as the moteus controller r4.0 and thus was only really usable as a paperweight.  Second, the supply of STM32G474 chips seems to be spotty now, so for r2 I had to scavenge chips from the boards that had broken pinouts.

The r2 boards did have a DB9 pinout that was not industry standard, this time due to Eagle’s DB9 footprint being broken, but that will be easy enough to fix in r2.1.

Software

The software had three things that needed to work, FDCAN, USB, and the finally all the glue logic.  Getting FDCAN to work was remarkably easy:  I just used the STM HAL APIs and was basically done.

USB was harder.  The last time I made a virtual serial port for the STM32, the mjmech gimbal board, I used the STM provided CDC libraries.  However, those are released only under a rather restrictive license, confusingly named the “Ultimate Liberty Software License Agreement”.  Despite the claims in the title, you actually have very little liberty, in that the software can only be used on STM controllers and has notice provisions as well.  As with the rest of the moteus universe, I wanted to be able to release this firmware under a permissive license so needed to look elsewhere.

Github and google found a number of candidates, and the one that I ended up starting from was dmitrystu/libusb_stm32.  It was already licensed under the Apache 2.0, and supported controllers which looked like they would be very similar to the STM32G4.  Sure enough, the STM32L433 has an identical USB peripheral and was already supported.

I ended up forking that repository into the fdcanusb one and modifying it slightly to be usable with C++ and mbed.  Also, interestingly, the CDC demo used the same endpoint for RX and TX, which the linux drivers didn’t seem to like so I just gave them separate endpoints like I’ve done before.  I then implemented a wrapper for the CDC class which presents the same asynchronous serial interface as everything else in mjbots/mjlib and was set to go.

The final piece of the software was all the glue and application logic.  I just used PersistentConfig and CommandManager from mjlib, which gave a human readable ASCII interface out of the box.  Then I wrote up the application logic in CanManager, which didn’t have to do much at this point.

Next steps

In its current state, the fdcanusb firmware is capable of communicating with the moteus r4.X series controllers just fine.  Next I’ll get a few more made to distribute with moteus development kits and see if there is any more demand for them.