AX12 Firmware

Introduction

Our objective is to have the fastest possible closed loop control between Roboard and the servo motor : receive position – actuate motor

Problem with Robotis standard Dynamixel protocol : too slow

AX12 servo firmware Morpheus

So in way to go around this problem we decided to develop our custom firmware.

The developed firmware was based not just on the direct need of PWM control, but on other needs, like control of the position, the control of the speed, but the other very important feature, the much higher frame rate ability when reading positions from several servos, and sending back commands and data.

To accomplish this speed upgrade, the firmware allows every servo “to know” the previous servo to it after a initialization cycle requested by the Master, on our caser the CM5 or the Roboard.

After this we just need to initiate a cycle of servo chain replies and all servos will send their position back, one after the others.

Features

The new firmware for AX12 servo motor is created with the goal of improvement of the speed and the flux of communication between Servos and Master, but we also pretend to have a different approach of control.

So as main  features we have:

– Static control, control of the goal position  with PID algorithm.

– Dynamic control, control of the speed when dislocating to the goal position also using PID algorithm.

– PWM control, direct control of the PWM that goes to the electric motor.

– Chain reply, reply of all servos positions, in chain, with a single packet request from the master.

– Read from servo,

  • Position
  • Speed
  • temperature
  • ID
  • PID gains for speed and position
  • UART speed
  • Limits

– Write to servo,

  • Position
  • Speed
  • ID
  • PID gains for speed and position
  • UART speed
  • Limits

Protocol

The communication protocol packet has been idealized to allow multi-master communication, and has the following composition in bytes:

[Header] is always 0xAA

[Packet Length] is the Length of the whole packet less the header, the length itself and the CRC, in bytes.

[Destination ID] is the ID of the packet destination

[Origin ID] is the ID of the device who sent the packet

[Command] is the code of query or reply command

[Data] is/are the bytes of data, if any

[CRC] is the CRC of the whole packet less the header and the CRC itself.

The CRC is the sum of every negated bytes (of the whole packet, less the header and itself).

Ex:

Packet   0xAA  0x03  0x01  0x0FE  0x01  0xF9

0xAA is the header

0x03 The Length

0x01 The Destination ID

0xFE Master ID

0x01 PING request

0xF9 Result from  ~(0x03) + ~(0x01) + ~(0xFE) + ~(0x01) = 0xF9

The servo code performs on this first version, reply to just a few commands.

Request and Reply Commands and codes:

PING                     0x01

READ                    0x02

WRITE                  0x03

START                   0x06

CYCLE                   0x07

OK                         0x04

NOK                      0x08

RESET                   0x09

SYNC_WR           0x83

PING:

Ping command has to be sent by regular ID not broadcast, it’s a simple why to check the presence of a device on the network.

A reply to this command will be the PING command itself, or in case of erroneous CRC, a NOK.

Ex:

Master to Servo

Packet   0xAA  0x03  0x01  0x0FE  0x01  0xF9

0xAA is the header

0x03 The Length

0x01 The Destination ID

0xFE Master ID

0x01 PING request

0xF9 Result from  ~(0x03) + ~(0x01) + ~(0xFE) + ~(0x01) = 0xF9

Servo to Master

Packet   0xAA  0x03  0xFE  0x01  0x01  0xF9

0xAA is the header

0x03 The Length

0xFE The Destination ID

0x01 Master ID

0x04 OK reply

0xF6 Result from  ~(0x03) + ~(0x01) + ~(0xFE) + ~(0x04) = 0xF6

READ

Read command has to be sent with regular ID, and allow to read data from the device (both eeprom and ram), given a memory address and a length of bytes to read, never being the sum of the address plus the length of data to read, bigger than the maximum address possible.

A reply to this command will be the data requested, or a NOK in the case of erroneous CRC or in case of the sum of the address plus the length of data to read being bigger than the maximum address possible.

Ex:

Master to Servo

Packet   0xAA  0x03  0x01  0x0FE  0x02 0x0B 0x02 0x

0xAA is the header

0x03 The Length

0x01 The Destination ID

0xFE Master ID

0x01 READ request

0x0B Memory Address to read

0x02 Length of data to read in bytes

0xF9 CRC

Servo to Master

Packet   0xAA  0x03  0xFE  0x01  0x01  0xF9

0xAA is the header

0x03 The Length

0xFE The Destination ID

0x01 Master ID

0xn1 data 1

0xn2  data 1

0xnn data n

0xzz CRC

WRITE

Write command can be sent either by regular ID or broadcast, and allow to write data to the device (both eeprom and ram), given a memory address and a length of bytes to write, never being the sum of the address plus the length of data to read, bigger than the maximum address possible.

A reply to this command will an OK, or a NOK in the case of erroneous CRC or in case of the sum of the address plus the length of data to read being bigger than the maximum address possible or even if any parameter to be written is out of the correspondent  limits.

NOTE:

The reply from the SERVO will already be done with the new settings.

Master to Servo

Packet   0xAA  0x03  0x01  0x0FE  0x02 0x0B 0x02 0x

0xAA is the header

0x03 The Length

0x01 The Destination ID

0xFE Master ID

0x01 WRITE request

0x0B Memory Address to start writing

0xn1 data 1

0xn2 data 2

0xnn data n

0xzz CRC

Servo to Master

Packet   0xAA  0x03  0xFE  0x01  0x01  0xF9

0xAA is the header

0x03 The Length

0xFE The Destination ID

0x01 Master ID

0x04 OK reply

Or

0x08 NOK reply If any of the values is located out of the memory range

0xF6 CRC

START

Start command has to be sent by broadcast, and is used to init the bus, once after this every servo will send a PING to the START requester, with a delay proportional to the ID, allowing like this to the MASTER build a table of existing devices, and to each SERVO their turn on the bus.

A reply to this command will be a PING from each connected SERVO within the ID correspondent delay.

Master to Servo

Packet   0xAA  0x03  0x01  0x0FE  0x01  0xF9

0xAA is the header

0x03 The Length

0x01 The Destination ID

0xFE Master ID

0x01 START request

0xF9

Servo1 to Master

Packet   0xAA  0x03  0xFE  0x01  0x01  0xF9

0xAA is the header

0x03 The Length

0xFE The Destination ID

0x01 Master ID

0x04 PING reply

0xF6

Servo 2 to Master

Packet   0xAA  0x03  0xFE  0x02  0x01  0xF8

Servo N to Master

Packet   0xAA  0x03  0xFE  0x0N  0x01  0xnn

NOTE:  All servos will reply separated by the maximum of 1ms each, at 1MBaud

CYCLE

Cycle command has to be sent by broadcast, and will only be successful if the START command has been done at least once.

This command will start the cycle of replies from the SERVOs to the MASTER, one after the other by the order set on the START.

A reply to this command will be the Position of each servo, if successfully accomplished.

OK

Ok the command is the reply from the servo when a successful WRITE command is received and executed.

NOK

The NOK command is a reply from the SERVO when a bad CRC append, or a command is unsuccessful, due to erroneous data or out of bounds parameters.

SYNC_WRITE

The syncronous write has to be sent by broadcast and allow to send data to several servos  using one single packet to do it, SINCE the ADRESS and the LENGTH of data to be written to each servo is the SAME to all of them.

The packet composition is like following,

[Header]  [Packet Length]  [Destination ID][Origin ID][Command] […D A T A …] [CRC]

[…D A T A …]   consists in

[Address][length]   [ID1][Data1 1]…[Data1 N]  . . .  [ID N][DataN 1]…[DataN N]

Where

[Address] is the address of the memory where to start writing the data to the servo;

[length] is the length in bytes to be written to each servo starting in the given address;

And each group of [ID][…Data…] is for each servo, where

[ID] the ID of the servo to which the array of data with the length [length], corresponds;

[…Data…] Array of bytes to be written to the servo.

RESET

The reset command can be sent either by regular ID or broadcast, and can be used to reset ALL the EEPROM data to the default values, including ID and BAUDRATE.

EEPROM Default values

MY ID                                   0x01

CTL UP LIMIT                     0x02

CTL LW LIMIT                    0x02

KPp                                       0x1E

KIp                                        0x05

KDp                                       0x01

KPv                                       0x1E

KIv                                         0x05

KDv                                       0x01

UART BAUD                       0x10(a speed of 115200 baudrate)

Predefined values and respective ranges:

Memory organization

The memory organization implemented is continuous between eeprom and ram as shown below, allowing this to read or write eeprom, ram or both with a single request command.

MY ID

This memory address contain the IDentification of the servomotor on the bus, used for example to identify the origin of it own messages to the bus or to calculate the delay on startup.

The ID can be changed by a broadcast, which we have to have in attention that all the servos on the bus will get the same ID, or can be changed by a packet addressed to the current ID with the new ID, to which the servo will reply with the new ID already. The Values to the ID must be within 1 and 253.

CTL UP/LW LIMIT

The Control upper limit is the margin in steps, the distance from the edge to consider as limit avoiding with this entering on the dead zone of the servo encoder.

KPp, KIp and KDp

Constants to control the PID for the static positioning control loop.

KPv, KIv and KDv

Constants to control the PID for the dynamic positioning control loop.

UART BAUD

Baudrate to control the UART to the bus, once again not that after modifying the uart baudrate the reply to the command will be done with the new baudrate.

 

POSITION

The position when reading returns the actual position of the servo, when writing sets the new Goal Position. The position must have values within

(0+CTL LW LIMIT) and (1023 – CTL UP LIMIT).

SPEED

The speed when reading returns the actual speed of the servo when moving toward the goal position, when writing, sets the speed with which the servo will follow to the goal position.  This speed is given in steps by 10ms, and we have 10 different speeds.

The values must be within 0 and 10


Devices IDs

The devices IDs have to be assigned with values within 1 and 254. Normally 254 is the value assigned to be the MASTER, but with this new protocol and packets composition, any ID can be MASTER, allowing also the support a Multi MASTER system on the BUS.

The address 255 is the common address of broadcasting.

TYPICAL DATA FLUX

*    This can be the PC, Roboard, CM5, or more than one of them at the same time.

**  These are the Servomotors

Speed tests

A test to a 10 servos in serie, and combining a control by PWM with an access to the servos positions using chain reply, we can reach the 600 frames per second.

Bugs and improvements

–          A chain break was our first big problem, so we created a maximum period of time to get the previous servo reply, that in the end of it, the servo would send it own reply avoiding this way breaking the chain.

–          Another problem was the overflow of the PIDs Integral component, jumping from the maximum positive to the maximum negative of the Signed Int variable that was keeping the value, which was solved with simple limits implementation.

–          A timeout to receive frames was also implemented after we got very big delays on the re-synchronization of the servos after an erroneous frame.

Source, hex, method of flashing

To Flash the servos with the custom firmware we need a Dynamixel2USB, a SMPS2Dynamixel or equivalent and the servo you want to flash. After installing the robotis software and tools, open the Robotis Terminal on the serial comm of the Dynamixel2USB. Keep the power off on the servo and with the terminal opened, press ‘#’ key continuosly and power the servo. By this way you enter in the servo boot menu.

Press ‘enter’ to clear the excess of ‘##’ and then enter ‘l’.

The servo will now wait for the firmware. Click ‘files’ and then ‘Transmit files’, search and select the ‘AX12.BIN’ file from the morpheus firmware folder.

After the successful download , clear the servo rom by inserting ‘c’. Wait until it finish and then enter ‘r’ to reset it.

Now the servo is ready. To reflash with original firmware from robotis or any other issue, more details can be found in the main blog page.

Custom Morpheus Firmware

Morpheus Firmware V1.2.rar

Custom Morpheus Firmware Datasheet

MORPHEUS Servo.pdf

Windows control GUI example

ServoGUI_Interface 1.1.zip

Control GUI example datasheet

MORPHEUS Servo Control GUI.pdf

24 Responses to “AX12 Firmware”

  1. Mohit Says:

    Can i use AX12.bin on a new atmega 8a chip ? I want to make my own servo from dc motor and control like ax12 with cm510.

    • actuatedcharacter Says:

      should be ok if it is the same chip
      The bootloader of ax12 is also opensource if I recall. Son standard atmega8 compatible bootloader

      • Adrien G. Says:

        I had to change my burnt atmega on a AX-12. Do you think I can find a bootloader to put inside the atmega (with my usbasp) , and then try to recover the original firmware thanks to “dynamixel wizard” ?

      • actuatedcharacter Says:

        Any bootloader will do but it wont work with the wizard as that expects certain serial commands to be responsive within few milliseconds from a reset. If u don’t find the ax12 bootloader then use another and then use whatever tool is associated with that bootloader. For example old arduino versions were compatible with atmega8

  2. Mohit Says:

    same chip means a new Atmega 8A chip ?

  3. Mohit Says:

    Hi,
    Can you give me the .c file of the firmware ?

  4. Mohit Says:

    I read the motor.c file. There is no programming line for murata potentiometer. Why ?

  5. robomarinheiro Says:

    Hi there!

    No you didn’t, once the potentiometer is read through a ADC peripheral.

    If you go on Control.c you will have 2 functions for this.
    void GetPosition(void) – this function triggers the ADC sampling
    void ISR_AD (void) – This function is an Interrupt Service Routine, called by the Interrupt set after the ADC finishes the sampling.

    We trigger and wait until its ready! 🙂

    I must admit, i was a “young junior” coder when i did this code, compared to what i do now. But if you need any further help let me know.

    ATMega8 is the same as ATMEga8A, this is the new version that came to replace the old, same specs except its more efficient in terms of comsumption and have some bugs sorted out.
    If you want, take a look on this 🙂

    Click to access avr523.pdf

    All the software that you can find done by us is free to use and to modify! And its all available here, just digg around and you’ll find it, if not just leave a comment asking about it.

    Hope it helps!

    • Mohit Says:

      ok thanks. Where is the new code ? Are you planning to write code for Mx28 ? You can take help from Darwin op software on springnote website.

  6. MOHIT Says:

    Hi;Its me again.The circuit schematic of AX12+ shows the Direction is controlled from pin 13 and 14 of Atmega 8A.I want to control the Direction from only one pin. Please tell me the way. what changes I have to make in the motor.c ?

    • robomarinheiro Says:

      Hi,
      Controlling the direction and speed, everything with a single pin its possible but i’m not seeing an easy way to do this.
      Considering that this is just some ideas:
      1) You can use a serial motor controller, probably the easiest way, I2C and there you go, single pin work.
      2) Using voltage comparator for Vmax/2 that control Voltage to Freq H Bridge and a PWM output with an RC filter to linearize the output.
      This will be a mess…
      3) use another processor with I2C serial control input that will comply with the main processor requests, and control the motor it self.
      4) Just keep the 2 controller pins directly connected controlling the DC motor HBridge, and use a I2C IO multiplexer connected to other pins to expand the IOs that you need for other stuff.

      Honestly, i think this processor is really used till the limit to keep up with the servo needs. 🙂

      Sorry for not helping much but there is not much more you can do with this board.

  7. Luu Says:

    hi,Ricardo Marinheiro!
    how many servo your project can control?
    thanks about great project

    • robomarinheiro Says:

      Hi,

      The test we have done on the Lab, was controlling 10 servos from the PC at 200 frames/s.
      The software on the CM5 could control more and a few previous tests for “the fun” that i’ve done my self could for more of them.
      There is a direct relation on the servos used and the time that the whole daisy chain takes to finish a single cycle.
      With one or 2 servos we could reach almost 700 Frames a sec, with 20 we were around 100 150.
      It must be taken in consideration that there are servos errors and comm errors and interference from the servos, DC/DCs AC/DCs H bridges GSM everything that uses power peaks of high current just dumps A LOT of noise on the communications.
      Also, i would say that at full work, 90% of the processor time is for uart work, so…
      Everything counts for the performance:)
      Small tip, on every servo power input, put a capacitor like 100uF or so, could help, just an idea.

  8. eagle Says:

    Will this firmware work with AX-18 servos also?

    • robomarinheiro Says:

      Hi,
      To be honest, i would not risk to burn 80£ servos just for the try.
      I’ve never tried to use this FW on AX18. IF,( a big IF once i’m not sure, i can’t find any schematics), the AX 18 internal board is identical to the AX 12 just changing the H bridge capacity and a few external passives i imagine, it should work, but i would NOT risk it.
      Sorry.
      If i find something, i’ll leave a note.

  9. Mohit Says:

    Hi;
    I want to shutdown the Overload trigger of Ax12+. I am ready to burn 1 or 2 Ax12+. Please tell me how to disable the Overload detection.

  10. Luther Palmer Says:

    I’m trying to build custom firmware for the MX-28T and MX-64T. Any tips on how to get started? How did you learn which ports were connected to what? Probing?

  11. Shreeyak Says:

    Hey, i’m going through your firmware, love your work and a big thank you for it. I have some questions on it, could you kindly answer a few questions i have about the code? could we communicate via email?

  12. agerken Says:

    Hi, i’m interested in your firmware! It is only usable for the AX-12 right? Can I control the servos with the Dynamixel-SDK afterwards?

  13. agerken Says:

    Hi, sorry to ask again,
    do you have any higher level code for the communication with the servo and your protocol? Thanks!

Leave a reply to Luther Palmer Cancel reply