Talking to Dynamixel servos from a NVIDIA Jetson (or other host computer)

jwatte's picture

It's pretty common, among people who want to talk to Dynamixel servos like the MX-28 or MX-64 or AX-12, to try to use a built-in UART on whatever computer they're using. Raspberry Pi, Odroid, NVIDIA Jetson are just a few common choices. The first thing an engineer will wonder is: "will I break something if I just tie TX and RX together on my UART?"

Actually, tying TX and RX will work fine, as long as you know to receive and discard the bytes you are sending yourself. There are two other problems, though:

FIRST PROBLEM

What's not going to work is the TX pin not being able to turn off the idle-high, which means that the response from the servos will fight the driver of the serial port. This may kill the serial driver or the servos if they are poorly implemented. (The Dynamixels are reasonably robust using a common buffer driver chip; I don't know about the level translator chip on the Jetson motherboard.)

There are two ways of solving this first problem:

1) The $0.02 way, is to tie the TX of the Jetson to the bus through a 4k7 resistor. This will pull the bus up softer than a full logic-high, which will possibly be enough to let the servos pull the bus low when they respond. The weaker pull-up will limit the speed you can run the bus at, though; you may not be able to stay robust at typical DXL speeds of 1-4 megabit. Try 115 kbps.

2) The proper way is to use a send/receive buffer chip, like a 74HCT125, and drive the direction pin with a GPIO output from the Jetson. Beacuse you need to switch the direction soon after the final stop bits of the Jetson transmit, timing may be hard to get right. The Dynamixel servos allow you to configure a response delay that you can turn up to get more margin in the timing. Of course, this will reduce the speed of the overall communications on the bus. Note that the "T" in the model number is important; I'll get to that below.

SECOND PROBLEM

This is another way that you may damage your system, or see problems in communications.

The Dynamixel bus is specified as 5V single-ended UART. This means that transmitting nodes on the bus will drive it all the way up to 5V. It also means that something that can only drive at 3.3V (like the Jetson UART otuput) may not properly register as a "1" when the level is high.
The 5V voltage may damage the driver chip on the Jetson carrier board.

There is only really one way to solve this problem, and that's to introduce some kind of buffer chip that can properly level translate. The 74HCT125 is a reasonable choice (see above.) The "T" is important, because it means it accepts "TTL" levels for high and low. The non-T version requires 0.7 times VCC to robustly recognize a high, and 5.0V (your VCC for DXL bus) times 0.7 is 3.5V, which the Jetson cannot provide. "TTL" has much lower level requirements.

SOLVING BOTH PROBLEMS

The 74HCT125, or a similar buffer/driver chip, will solve these problems, but require careful timing on your end to flip the direction bit right after sending data, so you can receive the response data.

A better option is to use something that is designed to do this for you. There are three options that are fairly plug-and-play:

1) The USB2Dynamixel from Robotis is designed to do this. However, it is bulky, and somewhat expensive. Also, it is a big clump that you plug straight into a USB port, all but guaranteeing that the port will be mechanically busted, so you'll also want a small pigtail USB extension cable to actually use it. I have one in my toolbox, because it's what Robotis requires when doing diagnostics and firmware recovery.

2) The USB2AX adapter, which is a much smaller, much lighter, slightly cheaper version of USB2Dynamixel, developed by "Xevel." (Nice guy; built an awesome Tachikoma robot replica a few years back.) This doesn't do the RS-422 four-pin protocol that some Dynamixels use, but that's OK for you as you're using the three-pin version. I have one, and sometimes use it, mostly from a Raspberry Pi.

3) A microcontroller of some sort. You write whatever protocol you want between your full CPU and the microcontroller, and the microcontroller in turn talks to the servo bus. With a 5V microcontroller that can turn off the TX pin while keeping the RX receiving, you don't even need a buffer chip. I've done this with Arduinos of various kinds (the ones based on the AVR328p -- the ARM ones are 3.3V and more fragile.)

Robotis also has a microcontroller board called the OpenCM 9.04, which is great, because it comes with the necessary buffer chips, and some libraries to talk to Dynamixel servos. You then talk to this board using either USB (which is how it's programmed,) or using a separate serial port (the board has three, one of which is used for the Dynamixel.) The board is 3.3V, but it contains the buffer chip for going to 5V and doing direction control. The OpenCM 9.04 A model comes without pins soldered, so you can get the appropriate Molex SPOX connectors for the DXL bus, and solder them in yourself. The C model only comes with a smaller JST connector which they use for their toy line (XL-320 servos and such.) You could use an adapter cable, though, as it's electrically the same. You'd then write some firmware that receives from one UART, and sends on the DXL bus, and vice versa. I have used this board, it works fine, but the old Arduino IDE and the firmware libraries that come with it are somewhat unfinished to my taste.

Finally, the Teensy 3.2 microcontroller is the best thing since sliced bread. It has very, very, robust firmware libraries. It can compile from an Arduino IDE, or from the command line. It has good support on the PJRC forums. And all of its three UARTs have the ability to drive a pin for direction automatically, so hooking up a buffer chip for the 5V half duplex translation is easy (assuming you are OK designing as simple board to mount the chip.) This is my go-to solution out of personal preference.

RECOMMENDATION

If you want a "it just works" solution, go with the USB2AX and eat the USB port.
If you can't possibly stand the loss of a USB port, then go with the OpenCM 9.04 talking to the Jetson over UART; this is the simplest to get working with very minimal soldering.

Finally, there's a lot of discussion about Dynamixel servos at the Trossen Robotics forums. (Xevel sometimes hangs out there, too.) If you still have questions, you will find some very smart people there, answering questions and getting nerdy about robotics.