Accessing table values on XL330-M288-T

Issue:

I would like to use the servo in position control mode, but I would like to be able to set the PROFILE_VELOCITY flag to latch the speed of the movement because it’s too fast for my application right now. I wasn’t having any luck with this, and was even having difficulty writing other values in memory, so I finally gave up and had the motor read back every value from the control table it could, and found many default values that didn’t line up with their addresses in the manual. Is there another version or something I should be using?

Eventually I want to set PROFILE_VELOCITY but for now I’d like to be able to set or understand pretty much any value in the table. For example, the “velocity limit” has a default value of 445, and is supposed to appear at address position 44 (emanual/docs/en/dxl/x/xl330-m288.md at master · ROBOTIS-GIT/emanual · GitHub), but in my readback, I see the value 445 at address 17. I feel like I’m doing something very wrong and I haven’t been able to figure it out.

Thank you!

This is the code I just ran

int i = 0;
  do {
    var = dxl.readControlTableItem(i, DXL_ID);
    Serial.print("Read ");
    Serial.print(i);
    Serial.print(" value: ");
    Serial.println(var);delay(20);
    i++;
  } while (i < 256);
  

and this is the output I got up through address 85 - all the rest were zeros

Read 0 value: 1200
Read 1 value: 0
Read 2 value: 52
Read 3 value: 2
Read 4 value: 1
Read 5 value: 4294967295
Read 6 value: 1
Read 7 value: 0
Read 8 value: 0
Read 9 value: 3
Read 10 value: 0
Read 11 value: 0
Read 12 value: 70
Read 13 value: 35
Read 14 value: 70
Read 15 value: 885
Read 16 value: 1750
Read 17 value: 445
Read 18 value: 4095
Read 19 value: 0
Read 20 value: 0
Read 21 value: 0
Read 22 value: 0
Read 23 value: 10
Read 24 value: 0
Read 25 value: 0
Read 26 value: 0
Read 27 value: 0
Read 28 value: 0
Read 29 value: 0
Read 30 value: 2
Read 31 value: 4294967290
Read 32 value: 0
Read 33 value: 53
Read 34 value: 1
Read 35 value: 0
Read 36 value: 0
Read 37 value: 0
Read 38 value: 0
Read 39 value: 0
Read 40 value: 0
Read 41 value: 180
Read 42 value: 1600
Read 43 value: 400
Read 44 value: 0
Read 45 value: 0
Read 46 value: 0
Read 47 value: 0
Read 48 value: 0
Read 49 value: 0
Read 50 value: 0
Read 51 value: 0
Read 52 value: 0
Read 53 value: 0
Read 54 value: 0
Read 55 value: 885
Read 56 value: 0
Read 57 value: 1750
Read 58 value: 510
Read 59 value: 445
Read 60 value: 0
Read 61 value: 0
Read 62 value: 0
Read 63 value: 0
Read 64 value: 0
Read 65 value: 0
Read 66 value: 510
Read 67 value: 0
Read 68 value: 0
Read 69 value: 27
Read 70 value: 0
Read 71 value: 0
Read 72 value: 0
Read 73 value: 0
Read 74 value: 0
Read 75 value: 0
Read 76 value: 0
Read 77 value: 1984
Read 78 value: 0
Read 79 value: 0
Read 80 value: 0
Read 81 value: 0
Read 82 value: 1
Read 83 value: 0
Read 84 value: 510
Read 85 value: 47


DYNAMIXEL Servo:
XL330-M288-T


DYNAMIXEL Controller:
OpenRB-150


Software Interface:
Arduino IDE

In readControlTableItem(i, id), the number i is interpreted as an index of a predefined Control Table item, not a memory address. So using it this way is incorrect.

To read values properly, make sure to use either readControlTableItem(ITEM_NAME, ID) or dxl.read(ID, address, size).

Thanks! that’s absolutely my problem. I just tried to limp it along by counting IDs in the file you sent, but I’d much rather just use names like
var = dxl.readControlTableItem(PROFILE_VELOCITY, DXL_ID);
Unfortunately none of these names are recognized when I try to use them. am I missing an import?

This code is kind of a wreck because I’ve been adding stuff to debug, but you can see at the top I’ve manually tried to define constants for the various IDs. if I don’t do that, I get something like

Compilation error: ‘GOAL_POSITION’ was not declared in this scope

Thanks again!

#include <Dynamixel2Arduino.h>

#define DXL_SERIAL Serial1
#define DXL_DIR_PIN 2
Dynamixel2Arduino dxl(DXL_SERIAL, DXL_DIR_PIN);

const uint8_t DXL_ID = 1;
const float DXL_PROTOCOL_VERSION = 2.0;
#define GOAL_POSITION 39
#define PROFILE_VELOCITY 38
#define PROFILE_ACCELERATION 37

void setup() {
  Serial.begin(115200);
  while (!Serial);

  DXL_SERIAL.begin(57600);
  dxl.begin();
  dxl.setPortProtocolVersion(DXL_PROTOCOL_VERSION);

  dxl.torqueOff(DXL_ID);  // Torque must be OFF before mode or profile changes
  
  uint32_t var = dxl.readControlTableItem(PROFILE_VELOCITY, DXL_ID);
  Serial.print("Read PROFILE_VELOCITY: ");
  Serial.println(var);
  
  uint32_t newvel = 100;
  dxl.writeControlTableItem(PROFILE_VELOCITY, DXL_ID, newvel);   // Set high speed

  var = dxl.readControlTableItem(PROFILE_VELOCITY, DXL_ID);
  Serial.print("Read PROFILE_VELOCITY: ");
  Serial.println(var);
  

  //dxl.writeControlTableItem(DRIVE_MODE, DXL_ID, 0x00);          // Velocity-based profile
  dxl.setOperatingMode(DXL_ID, OP_POSITION);                    // Position control mode
  newvel = 10;
  uint32_t newacc = 10;
  dxl.writeControlTableItem(PROFILE_ACCELERATION, DXL_ID, newacc); // Optional, smoother accel
  dxl.writeControlTableItem(PROFILE_VELOCITY, DXL_ID, newvel);   // Set high speed

  uint32_t vel = dxl.readControlTableItem(PROFILE_VELOCITY, DXL_ID);
  Serial.print("Read profile velocity: ");
  Serial.println(vel);

  dxl.torqueOn(DXL_ID);
}

void loop() {
  uint32_t var=5;

  int i = 0;
  // do {
  //   var = dxl.readControlTableItem(i, DXL_ID);
  //   Serial.print("Read ");
  //   Serial.print(i);
  //   Serial.print(" value: ");
  //   Serial.println(var);delay(20);
  //   i++;
  // } while (i < 256);
  
  
  Serial.print("Read GOAL_POSITION: ");
  Serial.println(var);

  dxl.setGoalPosition(DXL_ID, 512);    // Move to 45°
  
  var = dxl.readControlTableItem(GOAL_POSITION, DXL_ID);
  Serial.print("Read GOAL_POSITION: ");
  Serial.println(var);

  delay(2000);
  dxl.setGoalPosition(DXL_ID, 1536);   // Move to 135°

  var = dxl.readControlTableItem(GOAL_POSITION, DXL_ID);
  Serial.print("Read GOAL_POSITION: ");
  Serial.println(var);

  delay(2000);
  //delay(1000000);
}

You don’t need to manually define constants like:

#define GOAL_POSITION 39
#define PROFILE_VELOCITY 38
#define PROFILE_ACCELERATION 37

These are already defined inside the Dynamixel2Arduino library, so you should delete these lines from your code to avoid conflicts and redundancy.

Instead, just add the following line at the top of your code:

using namespace ControlTableItem;

This allows you to use symbolic names like GOAL_POSITION, PROFILE_VELOCITY, and PROFILE_ACCELERATION directly without redefining them. It keeps your code cleaner and safer.


:pushpin: Tip: You can also check the official examples in the Arduino IDE:

File → Examples → Dynamixel2Arduino → basic

For instance, the position_mode or profile_velocity_acceleration examples show exactly how to use these control table items properly using their symbolic names.

These examples are a great reference for setting up and using the library correctly.

Thank you! It’s working! I’d somehow missed that namespace line. I appreciate it

Also a small issue regarding using the OpenRB-150, you do not need to specify the DXL_DIR_PIN.

Just Dynamixel2Arduino dxl(DXL_SERIAL); is needed.