Motors generate different motions with same data

Hello, I have been using xm430-w350 motors and I really enjoy using them!

I’d like to ask one question regarding dynamixel SDK.

So to actuate the motors in python, I have been using the following scripts:
def set_command_position(id_position_list):

if connected:
    ADDR_PRO_GOAL_POSITION = 116  # Control table address
    LEN_PRO_GOAL_POSITION = 4  # Data Byte Length: Note the unit is byte = 8 bits = 2 bits HEX

    # Wait until the USB port is released  =========================================================================
    ttyUSB_data = glob.read_one_data(glob.mem_ttyUSB_data, 'portOccupied')
    while ttyUSB_data[0]:
        ttyUSB_data = glob.read_one_data(glob.mem_ttyUSB_data, 'portOccupied')

    # Occupy the USB port  =========================================================================================
    data_usb_occupied = {}
    data_usb_occupied['portOccupied'] = np.array([1.0])

    #print("Lock acquired for send command ----------------------------------------------")
    # compose sync_write package
    groupSyncWrite = GroupSyncWrite(portHandler, packetHandler,
                                    ADDR_PRO_GOAL_POSITION, LEN_PRO_GOAL_POSITION)

    num_of_motors = len(id_position_list)

    for iter in range(num_of_motors):
        DXL_ID = id_position_list[iter][0]
        dxl_goal_position = rad2tick(id_position_list[iter][1])

        # Allocate goal position value into byte array

        # A word = 4 digits HEX number = 16 bits binary number = 0 - 65535, thus 65536 has loword=0 and hiword=1
        # LOBYTE and HIBYTE separates low 4 digit HEX into 2 low + 2 high digits and express in DEX
        # e.g. 2047 has LOBYTE=255 and HIBYTE=7, since 15 + 15*16 = 255, 255 + 7*16^2 = 2047
        param_goal_position = [DXL_LOBYTE(DXL_LOWORD(dxl_goal_position)),

        # Add Dynamixel goal position values to the Syncwrite parameter storage
        dxl_addparam_result = groupSyncWrite.addParam(DXL_ID, param_goal_position)
        if not dxl_addparam_result:
            print("[ID:%03d] groupSyncWrite addparam failed" % DXL_ID)
            return False

    # Syncwrite goal position
    dxl_comm_result = groupSyncWrite.txPacket()
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
        return False

    # Clear syncwrite parameter storage

    # Release the USB port =========================================================================================
    data_usb_occupied = {}
    data_usb_occupied['portOccupied'] = np.array([0.0])

    #print("Lock released for send command ----------------------------------------------")
    return True
    return False

The problem I face so far is that the motors generate different angles although “param_goal_position” in the above code is identical between two different motions.

One thing I noticed was that the issue does not exist anymore if I set the range of the joint angles from 0 to 4096. It seems that when we command the joint angle which is outside the feasible range, sometimes I get the totally random motion even with the same “param_goal_position”.

  • This is what we use as settings in R+ manager:

  • We use 14.1 V as an input voltage to the OpenCM 485 Expansion board.

  • We use Python 3.

I look forward to hearing from you!
Best regards,

1 Like

That is weird.

Sync Write is just instruction where you are packing the data for TX. The following is briefly explaining how the sync instruction packs the data.

The key point in the image, the instruction is just do what you command.
But it seems that you code is well packing the goal position data when I briefly analyzed. So what I doubt, please check that Min / Max Position for your all DYNAMIXEL (ID 1 to 10 maybe?) and see if there is anything missing the value that should be set.