Tutorial: Controlling AX-12 Servos

  1. lnxfergy's Avatar
    lnxfergy lnxfergy is offline Mech Warfare Organizer Alumni
    How To, DIY

    Controlling AX-12 Servos

    Controlling AX-12 Servos
    AX-12 Dynamixel servos, as found in the bioloid kit, are extremely useful and powerful servos. They sport a digital controller, serial bus, overload and overheat shutdown, and a great torque-to-cost ration. This tutorial will explain the basics of AX-12 servos, and show you how to control an AX-12 servo, using either your PC, or an Arduino.

    AX-12 Basics
    Controlling the AX-12 servos is a snap. They use a serial bus and a very simple packet structure:

    1. Each packet begins with 2 start bytes, both of which will be value 255 (or 0xff for those who prefer hexadecimal)
    2. The next byte is the ID of the servo that you want to control. The servos included in the comprehensive kit are numbered 1-18. An ID of 254 is a broadcast, all servos will take the command -- be very careful with this, it's easy to mess stuff up.
    3. The next byte is the length of the packet
    4. The next byte is the instruction to carry out. Instructions include: Ping, Read, Write, and SyncWrite. For now, we'll only worry about Write.
    5. We then send any parameters.
    6. The last byte is a checksum. The checksum is a quick way to make sure the packet didn't get messed up in transit. We compute the checksum by adding up the ID, length, instruction, and all parameters, which I'll call SUM, then: checksum = 255 - (sum%256), so that we have an 8-bit number. If you send the wrong checksum, the servo won't do anything with the data recieved.

    An AX-12 will typically return a status packet after you send a command, the packet structure is also very simple, it has the same start bytes, checksum, ID, and length. The instruction is replaced by the error level, and the parameters returned depend on the actual instruction sent.

    We mentioned that the instructions we can carry out are mainly limited to Read/Write, so what are we reading and writing? The AX-12 uses a memory-mapped or register-based interface. Memory addresses (register addresses) correspond to particular parameters of operation. For instance, register #3 is the ID of the servo, if we write to this, the servo ID changes. The registers most of interest will be:

    • #3 = ID. Servos in the comprehensive kit are already set to ID 1-18, if you buy a single servo though, the default ID of the new AX-12 is 1. Each servo on the bus needs it's own ID.
    • #4 = Baud Rate. The default value is 1, which sets the baud rate to 1Mbps. Another common value you might use is 16, which gives us good old 115.2kbps.
    • #30 & 31 = Goal position. This is the point we want the servo to go to, because the value is between 0 and 1023, we need 2 registers to hold our 10-bit value. Register 30 is the low byte, and register 31 is the high byte. Thus, 0 = 0x000, 512 = 0x200, 1023 = 0x3ff. For a value of 1023, register 30=0xff, register 31=0x03.
    • #43 = Temperature. We can read back the current temperature of the servo, this is important because heat kills motors and electronics.

    All of these registers are described in detail in the AX-12 data sheet/manual.

    Python-Powered PC Control

    Since AX-12 servos use a serial bus, we can easily control them using our PC. Parts we will need:

    • A USBDynamixel and a SMPS2Dynamixel, this lets you easily control and power your servos. I am using an older HUV board which does nearly the same job as these two parts combined, but is no longer available.
    • At least 1 AX-12 servo.
    • Python 2.5, available for most any operating system, and it's free.
    • We also need pySerial, which allows the python language to communicate with a serial port.
    • If using Windows, you'll also need the Python for Windows extension, known as PyWin32.
    • If using Ubuntu, you can install all of the above with: sudo apt-get install python python-serial

    After installing the above software, we can begin controllng our servos. Once we have plugged our servo into our computer, we can control it. Python has a command line ability, so we can do this all at the command line at first, or save it into a file and run it:

    import serial                     # we need to import the pySerial stuff to use
    # important AX-12 constants
    AX_READ_DATA = 4
    s = serial.Serial()               # create a serial port object
    s.baudrate = 1000000              # baud rate, in bits/second
    s.port = "/dev/ttyUSB0"           # this is whatever port your are using
    # set register values
    def setReg(ID,reg,values):
        length = 3 + len(values)
        checksum = 255-((index+length+AX_WRITE_DATA+reg+sum(values))%256)          
        for val in values:
    def getReg(index, regstart, rlength):
        checksum = 255 - ((6 + index + regstart + rlength)%256)
        vals = list()
        s.read()   # 0xff
        s.read()   # 0xff
        s.read()   # ID
        length = ord(s.read()) - 1
        s.read()   # toss error    
        while length > 0:
            length = length - 1
        if rlength == 1:
            return vals[0]
        return vals
    setReg(1,30,((512%256),(512>>8)))  # this will move servo 1 to centered position (512)
    print getReg(1,43,1)               # get the temperature

    ** NOTE: I've left the following as historical reference, documentation on the library is now part of the ArbotiX project and can be found at http://arbotix.googlecode.com **

    Arduino Control

    The Arduino has a single serial port, which is somewhat problematic. We can send data out to the servos, but then we lose our serial port. Typically we need that to at least send debugging info back to our computer. For that reason, we will use the more powerful Sanguino/ArbotiX. This can be programmed in the Arduino environment, but is a larger chip with 2 serial ports.

    The Arduino presents slightly more of a challenge. The AX-12 servo has 3 lines on the bus: Power, Ground, and Signal. How does it use only one signal? Only one device on the bus can talk at a time. This is known as half-duplex serial. This poses a challenge on our AVR, since the hardware serial UART has separate lines for the RX and TX. We have two possible solutions:

    • Add additional circuitry to convert full duplex to half duplex, or
    • Tie the RX and TX lines together, and be safe about our code. This is the route I will take.We need to be sure that any time we are receiving, we turn off our TX channel.

    We also have some issues because of the high speed of the bus. A 1Mbps data rate allows only 16 instructions between bytes. This is not much of problem for sending data, but on receive, we have to be very fast or we will lose bytes of the return packet. The default serial read functions for the Arduino/Sanguino/ArbotiX are not fast enough to handle 1Mbps, so we will have to replace them with our own. (For those who want to know what the heck is going on under the hood: the circular buffer is the part that slows down the read functions, we'll speed ours up by removing the circular buffer -- to do this, we have to make our buffer larger than any packet returned, and reset the index of the buffer at the end of each read.)

    I've wrapped quite a bit of code into a bioloid library for the ArbotiX. To use it, we need to do some setup:

    1. Install the Arduino environment. Under windows, just install the Arduino package, which includes the compiler and downloader programs (you may also need to install Java if you do not already have it). Under Ubuntu, you have to install the AVR parts seperately, you'll also need to install Java: sudo apt-get install gcc-avr avr-libc avrdude sun-java6-jre.
    2. Install the Sanguino extensions, be sure to follow all instructions.
    3. Install the bioloid library: this entails replacing several parts of the sanguino code, since we need to turn off the default Serial1 behavior and replace it with our own code.

    Wiring up is quite easy: connect the TX1 and RX1 pins to the AX-12 serial line. Make sure the Sanguino and the AX-12 have a shared ground. Apply 7-10V to your AX-12 servos. The bioloid library allows you to control individual servos, but also does some interesting things with Poses and SyncWrite. The pose engine is still under development, I'll come back to discuss that later when it's more complete. To write to a servo:

    // include the library itself
    #include <ax12.h>
    #include <BioloidController.h>
    // now, create a connection called "bioloid" -- you should always call it bioloid
    //  so that our macros work. Our baud rate is 1Mbps = 1000000
    BioloidController bioloid = BioloidController(1000000);
    void setup(){
        // this is a simple macro to move servo ID #1 to the center position (512)
    void loop(){
        // nothing to do here...

    You can download a ZIP file of the latest revision of my bioloid library off my SVN server. (9-28-10: now part of ArbotiX project, see http://arbotix.googlecode.com)

Replies to Tutorial: Controlling AX-12 Servos
  1. kas Guest

    Thumbs up Re: Controlling AX-12 Servos

    Hi Inxfergy,

    Thanks for this very interesting tutorial
    The bioloid library is a dead link; please update the link, or let me have your library code by mail

    Greetings from Grenoble, France

  2. Re: Controlling AX-12 Servos

    I've removed the bioloid library from my SVN repository, it's now hosted on google code under the arbotiX project:



  3. nehuma Guest

    Re: Controlling AX-12 Servos

    hello mate.
    I bought 3 servos Dynamixel and 1 arduino duemilanove , I'd like to know if you can help me to control the servos whit the arduino, and how can I do it, I have no idea how to start it

  4. nehuma Guest

    Re: Controlling AX-12 Servos

    hello again where can I download
    #include <ax12.h>
    #include <BioloidController.h>

    I think I'll need it if I want to programming with Arduino

  5. Join Date
    Sep 2009
    Madison, WI

    Re: Controlling AX-12 Servos

    Hi nehuma

    All files (software and libraries, including the ax12.h and BioloidController.h that you seek) can be downloaded from http://code.google.com/p/arbotix/ under Featured downloads on the right of the page. Everything is contained within the arbotix zip file.

    A majority of the documentation you need is hosted here too within the Wiki (just click the Wiki tab link or use this: http://code.google.com/p/arbotix/wiki/home?tm=6), including initial setup/configuration instructions to get you started. This also contains instructions and a link for installing the Arduino IDE, which you'll need to do. Hope this helps!


  6. nehuma Guest

    Re: Controlling AX-12 Servos

    thanks stephen,
    I have another question. my arduino is arduino mega it has 4 serial ports, , Can I programming in arduino's language if I use Arbotix libraries? is the same structure?

    I'll do what you said before, I have to put rx and tx in the same line


  7. nehuma Guest

    Re: Controlling AX-12 Servos

    I did what you said with the libraries and put the example code but still does not work .I have to do anything else?

  8. Re: Controlling AX-12 Servos

    Quote Originally Posted by nehuma
    I did what you said with the libraries and put the example code but still does not work .I have to do anything else?
    The ArbotiX libraries use RX/TX1, they require a modified core for a faster serial read function (the default Arduino serial ISR handlers are too slow for 1Mbps). You'll have to modify the mega core to use the library.

    NOTE TO ALL: *PLEASE* post questions to the forum, as I don't get any notice about posts here in the tutorial section -- leading to very long delays in response.


  9. Re: Controlling AX-12 Servos

    I have modified and expanded lnxfergy's original code to run on a Raspberry Pi. It presents a wrapper for communicating with an AX12 servo that can be imported into a script. The module also provides a few rudimentary functions from a command line such as creating and playing poses. The module assumes that the AX12 servo(s) are connected through a buffer such as a 74HC125. The direction is controlled by a GPIO pin. We might could eliminate this by closing the serial port, tristating the pin, and then reopening the port. It doesn't seem to be worth the work involved though.

    Here is the library:

    "If A is a success in life, then A equals x plus y plus z. Work is x; y is play; and z is keeping your mouth shut."

    Don't be a HelpVampire

Closed Tutorial