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.
http://emanual.robotis.com/docs/en/software/dynamixel/dynamixel_workbench/
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
and
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");
with
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 |
vali18 |
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:
/** EEPROM AREA **/ #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_MARGIN 26 #define AX_CCW_COMPLIANCE_MARGIN 27 #define AX_CW_COMPLIANCE_SLOPE 28 #define AX_CCW_COMPLIANCE_SLOPE 29 #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_PRESENT_TEMPERATURE 43 #define AX_REGISTERED_INSTRUCTION 44 #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
Kurt
![]() |
2018-04-15 02:33:10 |
Kurt |
Hello,
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 Loaddxl_comm_result = packetHandler->read2ByteTxRx(portHandler, DXL_ID, ADDR_PRESENT_LOAD, &dxl_present_load, &dxl_error); if (dxl_comm_result != COMM_SUCCESS) { packetHandler->printTxRxResult(dxl_comm_result);
} else if (dxl_error != 0) { packetHandler->printRxPacketError(dxl_error); } 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 |
Will Son |
Hi,
Thanks a lot for your answers I'll try and let you know how goes!!
![]() |
2018-04-17 00:33:09 |
valentina |