Tag Archives: fdcan

CAN prefixes for moteus

The moteus controller, communicates exclusively over CAN-FD for command, telemetry, and diagnostics. It will accept either standard or extended frames, and until now, the ID format in terms of bits looked like the following:

33333222222221111111100000000
43210765432107654321076543210
XXXXXXXXXXXXXQSSSSSSSDDDDDDDD

Where:

  • X: Don’t care
  • Q: 1 for query, 0 for no query
  • S: source ID
  • D: destination ID

If the lower 8 bits matched the configured ID, all the X bits would be completely ignored and moteus would accept the CAN message as if it were destined for itself. This may not be super desirable, as it consumes nearly all of the available CAN-FD addressing space.

Starting with firmware version 2021-08-20, moteus now uses the following ID format:

33333222222221111111100000000
43210765432107654321076543210
PPPPPPPPPPPPPQSSSSSSSDDDDDDDD

Where P is a 13 bit “CAN prefix” that can be configured and defaults to 0. moteus will only accept CAN frames where this prefix matches the configured value*, and all frames it sends will have the prefix set as configured. This allows you to reclaim large sections of the CAN ID space for other devices in the event that moteus controllers share a bus.

[*] Footnote: The bootloader will require that the CAN prefix be set correctly, but WILL NOT set the prefix on the messages it sends. The existing moteus client side tools will function, but other devices on the bus may be confused.

Unsuccessful CAN-FD communication between CANBed-FD and moteus

On the mjbots discord, people are often looking for the cheapest possible way to command and monitor a moteus controller. One possible solution that comes up over and over again is the CANBed-FD board, as sold by Seeed Studio (and others). I decided to get one of these in house to see if I could make it work:

The first thing I figured out was that the DB-9 connector used a non-standard pinout for CAN_L and CAN_H. I just switched to the terminal block connections instead of the DB-9 to get around that. For the software, I decided to use the acan2517FD Arduino library, as it was quite a bit more robust and featureful than the one provided by Longan Labs.

With this in hand, I was able to get the Arduino to send properly formatted CAN-FD frames that moteus would receive. However, as it often does, the problem came when receiving. This Longan Labs board uses a 20MHz clock for the MCP2518FD onboard, which means that it is only *just* able to do the 5MHz CAN-FD clock rate that moteus requires, and there is no margin for actually being able to synchronize to a slightly skewed bitrate using the sync jump width. Because of this, I was not able to get the device to receive data from a moteus controller except by nudging the bitrate of the moteus controller around by fractional percents manually, and then it only worked for a short time before temperature, or humidity, or whatever, drifteed it out of range.

If someone finds an Arduino board that uses a MCP2518FD with a 40MHz clock (or a 4MHz clock that uses the built in PLL), let me know, as I expect that should be able to work fine. That is the configuration used by the Seeed Raspberry Pi CAN-FD adapter, which has 2 MCP2518FDs with a 40MHz clock and it has been demonstrated to work with bit timings listed in the moteus reference documentation.

pi3hat configurable CAN

To date, the pi3hat CAN channels only supported CAN properties suitable for use with moteus controllers. Given that’s what most people are using them for, that’s fine. However, there was no real constraint behind that, just laziness.

Thus, I’ve released new firmware for the pi3hat that supports configuring the bitrate, FD-ness, and other properties of all 5 CAN channels.

Currently only the C++ library exposes the configuration functionality, but it will be easy enough to add to python when someone needs it.

pi3hat r4.4

It seems like all the posts I’m writing these days are for new products! Here’s the pi3hat r4.4:

There are two changes from the previous r4.2. First, it now supports voltage inputs up to 44V. Second, in support of future upgrades, the 5th CAN-FD port has been upgraded to support 8Mbps, but downgraded to no longer have a wide common mode voltage range.

THUS, IT IS NOT SAFE TO CONNECT THE CAN-FD PORT ON THE pi3hat r4.4 TO A power_dist r3.X BOARD.

Also, it is in stock at mjbots.com!

That said, the worldwide electronic supply chain is still in shambles. That combined with the Chinese New Year means that stock may be intermittent, and slight alternate versions to adjust to different parts may be forthcoming.

New cross-platform moteus tools!

After receiving many requests via youtube, discord, and email, I’ve finally gone ahead, bitten the bullet, and updated all of the moteus tools to be pure python and work in a cross platform manner. Now, the only thing you need to do to install pre-compiled versions of tview and moteus tool on most* platforms is:

pip3 install moteus_gui
python3 -m moteus_gui.tview    # (or maybe just tview)
python3 -m moteus.moteus_tool  # (or maybe just moteus_tool)

I’ve personally tested these on Linux, Windows, and Raspberry Pi, and others have at least verified basic operation on Macs. Python 3.7 or greater is required.

….

But wait, there’s more!

Now, both moteus_tool, tview, and the python bindings more generally can use python-can as a transport. That means tview can now be used with socketcan, pcan, and a bunch of other options. To one up that, most users won’t have to even specify any command line options, as tview and moteus tool will automatically select a fdcanusb or python-can depending upon what is available.

I’ll be updating the devkit introduction video soon, although the commands in there will largely continue working for the time being.

Errata

  • Neither pypi or piwheels has pyside2 for the Raspberry Pi, but it is packaged in Raspberry Pi OS. You can follow the instructions in git to find a recipe that works.
  • To use the pi3hat, you need to also do pip3 install moteus_pi3hat

moteus and socketcan

Various users have been trying to use lower-cost Raspberry Pi CAN-FD adapters for the moteus controller for some time (like this one from Seeed), but have had problems getting communication to work. I buckled down and went to debug the problem, discovering that the root of the issue was that the linux kernel socketcan subsystem calculates very sub-optimal CAN timings for the 5Mbps bitrate that moteus uses. This results in the adapters being unable to receive frames sent at the actual 5Mbps rate, but instead only slightly slower.

The solution is to manually specify the bus timings when configuring the socketcan link. This makes the MCP2518FD boards work, and also PEAK-CAN-FD USB adapters (and probably every other socketcan CAN-FD adapter) work as well. You can find the timings linked in the moteus reference documentation: https://github.com/mjbots/moteus/blob/main/docs/reference.md#bit-timings

General socketcan improvements

As a result of all this debugging, I made some general improvements to socketcan support in all the client side moteus tools.

  1. There is now a documented commandline for invoking moteus_tool from socketcan: https://github.com/mjbots/moteus/blob/main/docs/reference.md#moteus_tool-configuration
  2. I released moteus and moteus_pi3hat 0.2.0 to pypi. These provide socketcan interfaces for python, transparently using them if no fdcanusb or pi3hat peripherals are found.

Thanks for everyone on discord’s patience as we worked through these compatibility issues!

Measuring the pi3hat r4.2 performance

Last time I covered the new software library that I wrote to help use all the features of the pi3hat, in an efficient manner. This time, I’ll cover how I measured the performance of the result, and talk about how it can be integrated into a robotic control system.

pi3hat r4.2 available at mjbots.com

Test Setup

To check out the timing, I wired up a pi3hat into the quad A1 and used the oscilloscope to probe one of the SPI clocks and CAN bus 1 and 3.

Then, I could use pi3hat_tool incantations to experiment with different bus utilization strategies and get to one with the best performance. The sequence that I settled on was:

  1. Write all outgoing CAN messages, using a round-robin strategy between CAN buses. The SPI bus rate of 10Mhz is faster than the 5Mbps maximum CAN-FD rate, so this gets each bus transmitting its first packet as soon as possible, then queues up the remainder.
  2. Read the IMU. During this phase, any replies over CAN are being enqueued on the individual STM32 processors.
  3. Optionally read CAN replies. If any outgoing packets were marked as expecting a reply, that bus is expected to receive the appropriate number of responses. Additionally, a bus can be requested to “get anything in the queue”.

With this approach, a full command and query of the comprehensive state of 12 qdd100 servos, and reading the IMU takes around 740us. If you perform that on one thread while performing robot control on others, it allows you to achieve a 1kHz update rate.

CAN1 SPI clock on bottom, CAN1 and CAN3 bus on top

These results were with the Raspberry Pi 3b+. On a Raspberry Pi 4, they seem to be about 5% better, mostly because the Pi 4’s faster CPU is able to execute the register twiddling a little faster, which reduces dead time on the SPI bus.

Bringing up the pi3hat r4.2

The pi3hat r4.2, now in the mjbots store, has only minor hardware changes from the r4 and r4.1 versions. What has changed in a bigger way is the firmware, and the software that is available to interface with it. The interface software for the previous versions was tightly coupled to the quad A1s overall codebase, that made it basically impossible to use with without significant rework. So, that rework is what I’ve done with the new libpi3hat library:

It consists of a single C++11 header and source file with no dependencies aside from the standard C++ library and bcm_host.h from the Raspberry Pi firmware. You can build it using the bazel build files, or just copy the source file into your own project and build with whatever system you are using.

Performance

Using all of the pi3hat’s features in a runtime performant way can be challenging, but libpi3hat makes it not so bad by providing an omnibus call which sequences accesses to all the CAN buses and peripherals in a way that maximizes pipelining and overlap between the different operations, while simultaneously maximizing the usage of the SPI bus. The downside is that it does not use the linux kernel drivers for SPI and thus requires root access to run. For most robotic applications, that isn’t a problem, as the controlling computer is doing nothing but control anyways.

This design makes it feasible to operate at least 12 servos and read the IMU at rates over 1kHz on a Raspberry Pi.

pi3hat_tool

There is a command line tool, pi3hat_tool which provides a demonstration of how to use all the features of the library, as well as being a useful diagnostic tool on its own. For instance, it can be used to read the IMU state:

# ./pi3hat_tool --read-att
ATT w=0.999 x=0.013 y=-0.006 z=-0.029  dps=(  0.1, -0.1, -0.1) a=( 0.0, 0.0, 0.0)

And it can be used to write and read from the various CAN buses.

# ./pi3hat_tool --write-can 1,8001,1300,r \
                --write-can 2,8004,1300,r \
                --write-can 3,8007,1300,r
CAN 1,100,2300000400
CAN 2,400,2300000400
CAN 3,700,230000fc00

You can also do those at the same time in a single bus cycle:

# ./pi3hat_tool --read-att --write-can 1,8001,1300,r
CAN 1,100,2300000400
ATT w=0.183 x=0.692 y=0.181 z=-0.674  dps=(  0.1, -0.0,  0.1) a=(-0.0, 0.0,-0.0)

Next steps

Next up I’ll demonstrate my performance testing setup, and what kind of performance you can expect in a typical system.

New product Monday: pi3hat

I’ve now got the last custom board from the quad A1 up in the mjbots store for sale, the mjbots pi3 hat for $129.

This board breaks out 4x 5Mbps CAN-FD ports, 1 low speed CAN port, a 1kHz IMU and a port for a nrf24l01. Despite its name, it works just fine with the Rasbperry Pi 4 in addition to the 3b+ I have tested with mostly to date. I also have a new user-space library for interfacing with it that I will document in some upcoming posts. That library makes it pretty easy to use in a variety of applications.

Finally, as is customary with these boards, I made a video “getting started” guide: