RE: AX-12A, Dynamixel Protocol_1, and U2D2

Hello,

I am using the described items in the heading. I am receiving some errors and odd behavior from my servos that is most likely my fault.

[TxRxResult] Incorrect status packet!
[ID:001] GoalPos:180  PresPos:000
[TxRxResult] Incorrect status packet!
[ID:001] GoalPos:180  PresPos:000
[TxRxResult] Incorrect status packet!
[ID:001] GoalPos:180  PresPos:000
[TxRxResult] Incorrect status packet!
[ID:001] GoalPos:180  PresPos:000
[TxRxResult] Incorrect status packet!
[ID:001] GoalPos:180  PresPos:000
[ID:001] GoalPos:180  PresPos:179

My Goal Position and Present Position print many times while the servos do nothing. I am using the read_write.py and sync_write.py files in the python/examples/ dir.

Anyway, my source so far has just been me adding in the required data into the listed fields for testing.

For example, this is sync_write.py:

from dynamixel_sdk import *                    # Uses Dynamixel SDK library

# Control table address
ADDR_MX_TORQUE_ENABLE      = 24              
ADDR_MX_GOAL_POSITION      = 30
ADDR_MX_PRESENT_POSITION   = 36

# Data Byte Length
LEN_MX_GOAL_POSITION       = 4
LEN_MX_PRESENT_POSITION    = 4

# Protocol version
PROTOCOL_VERSION            = 1.0           

# Default setting
DXL1_ID                     = 1           
DXL2_ID                     = 2             
BAUDRATE                    = 57600       
DEVICENAME                  = '/dev/ttyUSB0'   

TORQUE_ENABLE               = 1            
TORQUE_DISABLE              = 0              
DXL_MINIMUM_POSITION_VALUE  = 0         
DXL_MAXIMUM_POSITION_VALUE  = 90           
DXL_MOVING_STATUS_THRESHOLD = 20         

index = 0
dxl_goal_position = [DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_POSITION_VALUE]

and so on…

So, my question basically is, “How can I use the lib. w/out printing the Present and Goal Position so many times?”

The time it takes to run through the source for the print statements is longer than the actual time for the maneuvers from the Servos, i.e. AX-12As.

Seth

P.S. This may seem funny b/c of it just being print statements but they are heavily repetitive and taking a lot of processing time, right? Anyway, any ideas would be nice.

Hello,

Here is the source. As you can tell, I know very little about the SDK, i.e. still. I am trying to learn more about it as time persists.

def Packs():
    for i in range (0, 259, 2):
        i = int(input("Please type a number from 1 to 360: "))
        TORQUE_ENABLE  = 1
        sleep(5)
        TORQUE_DISABLE = 0
        sleep(5)
        print ("Your number, sir: ", i)
        fort = dxl_goal_position
        if fort == input and i >= 0:
            TORQUE_ENABLE  = 1
            sleep(5)
            TORQUE_DISABLE = 0
            sleep(5)
        else:
            pass
    print ("Hello!")

Packs()

As you can tell, I need some help along until I can figure out things. Please do not laugh!

Seth

P.S. I did not use one of the functions in the protocol1_packet_handler.py file. Is there a list of functions one should use for specific uses? Sorry for all the fixes…

In case of AX series, position related data is 2 byte field, so I’m assuming that the incorrect length might have caused the issue.

Here’s the modified & tested read_write.py example code from DYNAMIXEL SDK.
Please note that I used a factory default AX which comes with 1Mbps baudrate by default.

# read_write.py example
import os

if os.name == 'nt':
    import msvcrt
    def getch():
        return msvcrt.getch().decode()
else:
    import sys, tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    def getch():
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

from dynamixel_sdk import *                    # Uses Dynamixel SDK library

# Control table address
ADDR_MX_TORQUE_ENABLE      = 24               # Control table address is different in Dynamixel model
ADDR_MX_GOAL_POSITION      = 30
ADDR_MX_PRESENT_POSITION   = 36

# Protocol version
PROTOCOL_VERSION            = 1.0               # See which protocol version is used in the Dynamixel

# Default setting
DXL_ID                      = 1                 # Dynamixel ID : 1
BAUDRATE                    = 1000000             # Dynamixel default baudrate : 57600
DEVICENAME                  = '/dev/ttyUSB0'    # Check which port is being used on your controller
                                                # ex) Windows: "COM1"   Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"

TORQUE_ENABLE               = 1                 # Value for enabling the torque
TORQUE_DISABLE              = 0                 # Value for disabling the torque
DXL_MINIMUM_POSITION_VALUE  = 0           # Dynamixel will rotate between this value
DXL_MAXIMUM_POSITION_VALUE  = 1023            # and this value (note that the Dynamixel would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.)
DXL_MOVING_STATUS_THRESHOLD = 20                # Dynamixel moving status threshold

index = 0
dxl_goal_position = [DXL_MINIMUM_POSITION_VALUE, DXL_MAXIMUM_POSITION_VALUE]         # Goal position


# Initialize PortHandler instance
# Set the port path
# Get methods and members of PortHandlerLinux or PortHandlerWindows
portHandler = PortHandler(DEVICENAME)

# Initialize PacketHandler instance
# Set the protocol version
# Get methods and members of Protocol1PacketHandler or Protocol2PacketHandler
packetHandler = PacketHandler(PROTOCOL_VERSION)

# Open port
if portHandler.openPort():
    print("Succeeded to open the port")
else:
    print("Failed to open the port")
    print("Press any key to terminate...")
    getch()
    quit()


# Set port baudrate
if portHandler.setBaudRate(BAUDRATE):
    print("Succeeded to change the baudrate")
else:
    print("Failed to change the baudrate")
    print("Press any key to terminate...")
    getch()
    quit()

# Enable Dynamixel Torque
dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, ADDR_MX_TORQUE_ENABLE, TORQUE_ENABLE)
if dxl_comm_result != COMM_SUCCESS:
    print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
elif dxl_error != 0:
    print("%s" % packetHandler.getRxPacketError(dxl_error))
else:
    print("Dynamixel has been successfully connected")

while 1:
    print("Press any key to continue! (or press ESC to quit!)")
    if getch() == chr(0x1b):
        break

    # Write goal position
    dxl_comm_result, dxl_error = packetHandler.write2ByteTxRx(portHandler, DXL_ID, ADDR_MX_GOAL_POSITION, dxl_goal_position[index])
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
    elif dxl_error != 0:
        print("%s" % packetHandler.getRxPacketError(dxl_error))

    while 1:
        # Read present position
        dxl_present_position, dxl_comm_result, dxl_error = packetHandler.read2ByteTxRx(portHandler, DXL_ID, ADDR_MX_PRESENT_POSITION)
        if dxl_comm_result != COMM_SUCCESS:
            print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
        elif dxl_error != 0:
            print("%s" % packetHandler.getRxPacketError(dxl_error))

        print("[ID:%03d] GoalPos:%03d  PresPos:%03d" % (DXL_ID, dxl_goal_position[index], dxl_present_position))

        if not abs(dxl_goal_position[index] - dxl_present_position) > DXL_MOVING_STATUS_THRESHOLD:
            break

    # Change goal position
    if index == 0:
        index = 1
    else:
        index = 0


# Disable Dynamixel Torque
dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL_ID, ADDR_MX_TORQUE_ENABLE, TORQUE_DISABLE)
if dxl_comm_result != COMM_SUCCESS:
    print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
elif dxl_error != 0:
    print("%s" % packetHandler.getRxPacketError(dxl_error))

# Close port
portHandler.closePort()

Hello @ROBOTIS-Will ,

I will attempt your setup source soon. Thank you for taking time out and replying.

I will review it and check it w/ the source I have currently. I think I am way off base here. So, studying the SDK will be next.

Seth

Hello,

Sorry it has taken me so long to reply. I kept the info. on this page up in the chance I could get things working in the manner I choose. I have been away or aloof from source lately. Anyway, thank you for this article and for still promoting a neat way to handle Servo Motors like the AX-12A.

Seth

Hi @silver2row

No worries at all. Glad to see you again!
You may also want to check out a new ROBOTIS community below.