POST No. 2406764
OpenCM9.04 Write_Read
2018-04-14 03:12:00 vali18

Hello everyone,

I am using OpenCM9.04 and AX-12A dynamixel motors. 

I am quite a begineer and I have few questions. 

I am working on a project and don't have too much time, so I'm generally looking for the simplest way to control and get values from the motors. 

I am working in the ArduinoIDE and I have been trying to use both the dynamixel_workbench and SDK library. 

I looked at all the documentation and at the examples on Arduino. 


So far I have managed successfully to write and read Position, based on the examples, and I am now trying to get Load values. 

Generally I would like to understand how to use the write and read functions such as: 

itemWrite(uint8_t id, const char* item_name, int32_t value) - Write data in address 


itemRead(uint8_t id, const char* item_name) - Read data in address 

How can I replace the const char* item_name with other variables or adresses? 

Such as present load? 

I see that in the code-examples are used inbuilt variable such as "Goal_Position" or "Present_Position" , where can i find a full list of variables(name, type and addreess)?

So far I intuitively replaced the 

dxl_wb.itemRead(DXL_ID, "Present_Position"); 


dxl_wb.itemRead(DXL_ID, "Present_Load"); 

and got some semi-working values, but I would like to understand better how to use it. 

At this stage in the serial monitor i'm getting double values,6464 instead of 64 for example. So I need to clean the code a bit.

Any help would be much appreciated!!

thank you!!

2018-04-14 03:12:00
2018-04-15 02:33:10 Kurt

Hopefully others like @Will Son will give you a more complete answer and suggestions. 

My Understanding is the Workbench is sort of setup mainly to do ROS...  If you go with the link you showed, and run their GUI stuff, it should show you a list of the valid strings in the list of properties.

I personally have not used it and instead use either my own library or the Dynamixel SDK: http://support.robotis.com/en/software/dynamixelsdk.htm

There are a few reasons for this.   The  methods you down like dxl_wb.itemRead(DXL_ID, "Present_Position");

Assuming this is correct it will figure out the type of servo that DXL_ID is, then it will do a series of String compares until it finds the correct one, it then converts that string ID into the actual Servo Register number and reads the value from the servo... I prefer to simply use the SDK and pass in the Servo ID and Register #, since in my setups I know the types of servos I am working with.

You can get the set of register IDS from the AX-12 documentation: http://support.robotis.com/en/product/actuator/dynamixel/ax_series/dxl_ax_actuator.htm

I typically have a header file setup some place with standard #defines for the different register ids...   For example from one of my programs:

#define AX_MODEL_NUMBER_L           0
#define AX_MODEL_NUMBER_H           1
#define AX_VERSION                  2
#define AX_ID                       3
#define AX_BAUD_RATE                4
#define AX_RETURN_DELAY_TIME        5
#define AX_CW_ANGLE_LIMIT_L         6
#define AX_CW_ANGLE_LIMIT_H         7
#define AX_CCW_ANGLE_LIMIT_L        8
#define AX_CCW_ANGLE_LIMIT_H        9
#define AX_SYSTEM_DATA2             10
#define AX_LIMIT_TEMPERATURE        11
#define AX_DOWN_LIMIT_VOLTAGE       12
#define AX_UP_LIMIT_VOLTAGE         13
#define AX_MAX_TORQUE_L             14
#define AX_MAX_TORQUE_H             15
#define AX_RETURN_LEVEL             16
#define AX_ALARM_LED                17
#define AX_ALARM_SHUTDOWN           18
#define AX_OPERATING_MODE           19
#define AX_DOWN_CALIBRATION_L       20
#define AX_DOWN_CALIBRATION_H       21
#define AX_UP_CALIBRATION_L         22
#define AX_UP_CALIBRATION_H         23
/** RAM AREA **/
#define AX_TORQUE_ENABLE            24
#define AX_LED                      25
#define AX_CW_COMPLIANCE_SLOPE      28
#define AX_GOAL_POSITION_L          30
#define AX_GOAL_POSITION_H          31
#define AX_GOAL_SPEED_L             32
#define AX_GOAL_SPEED_H             33
#define AX_TORQUE_LIMIT_L           34
#define AX_TORQUE_LIMIT_H           35
#define AX_PRESENT_POSITION_L       36
#define AX_PRESENT_POSITION_H       37
#define AX_PRESENT_SPEED_L          38
#define AX_PRESENT_SPEED_H          39
#define AX_PRESENT_LOAD_L           40
#define AX_PRESENT_LOAD_H           41
#define AX_PRESENT_VOLTAGE          42
#define AX_PAUSE_TIME               45
#define AX_MOVING                   46
#define AX_LOCK                     47
#define AX_PUNCH_L                  48
#define AX_PUNCH_H                  49

 From that test program, for example I have a simple function to hopefully set all of the servos to their center position:

void AllServosCenter(void) {
  bool any_errors = false;
  uint8_t error;
  int retval;
  // First make sure all of the motors are turned on. 
  for (int i = 0; i < NUM_SERVOS; i++) {
    retval = packetHandler->write1ByteTxRx(portHandler, pgm_axdIDs[i], AX_TORQUE_ENABLE, 0x1, &error);
    any_errors |= ReportAnyErrors("TQ ON", pgm_axdIDs[i], retval, error);
  delay(2); // give servo some time to handle torque on...
  for (int i = 0; i < NUM_SERVOS; i++) {
    retval = packetHandler->write2ByteTxRx(portHandler, pgm_axdIDs[i], AX_GOAL_POSITION_L, 0x1ff, &error);
    any_errors |= ReportAnyErrors("Goal", pgm_axdIDs[i], retval, error);
  if (any_errors) Serial.println();

 The above code is from my AX test program as I was converting it from running using my own library (BioloidSerial) to the DynamixelSDK as part of the stuff I was doing to convert the Trossen Robotics PhantomX Hexapod from using their ArbotixM board to an OpenCM board... The stuff is up in: https://github.com/KurtE/Open_CM904

Hope the helps


2018-04-15 02:33:10
2018-04-16 09:56:38 Will Son


DynamixelWorkbench can be considered as Linux version of R+ Manager which lacks several features because Linux users didn't have much options to perform a simple test with Dynamixel.

For this reason DynamixelSDK is recommended when developing a software.

There is a various language samples and explanations of the source of in the eManual.

For example, reading and writing position example in C can be found here (C++ can be found here) and please note that AX series only support Protocol 1.0(Control table 1.0, Control table of AX-12A).

Also don't forget to change the below definition based on the actual port assigned from your PC.

#define DEVICENAME                      "/dev/ttyUSB0"      // Check which port is being used on your controller
                                                            // ex) Windows: "COM1"   Linux: "/dev/ttyUSB0"

If you want to read Present Load, you can add in the definition and read the address as below.

// Control table address
#define ADDR_MX_TORQUE_ENABLE           24                  // Control table address is different in Dynamixel model
#define ADDR_MX_GOAL_POSITION           30
#define ADDR_MX_PRESENT_POSITION        36
#define ADDR_PRESENT_LOAD               40

...(code omitted)

uint16_t dxl_present_load = 0; // Present Load

...(code omitted)

//Read Present Load
dxl_comm_result = packetHandler->read2ByteTxRx(portHandler, DXL_ID, ADDR_PRESENT_LOAD, &dxl_present_load, &dxl_error);
if (dxl_comm_result != COMM_SUCCESS)
else if (dxl_error != 0)
printf("[ID:%03d] Present Load:%03dn", DXL_ID, dxl_present_load);

If you want to keep using DynamixelWorkbench, please see this code from line #34 for available options.

Thank you.

2018-04-16 09:56:38
2018-04-17 00:33:09 valentina


Thanks a lot for your answers I'll try and let you know how goes!!

2018-04-17 00:33:09
웹에디터 시작 웹 에디터 끝