BeagleBone Dynamixel AX12 Interface – Part 2.5

More progress on my Dynamixel to BeagleBone interface experimentation…

I now have enough of the the Dynamixel communication protocol working to both read and write to any address in the servos control table.

This video demonstrates reading the present position from on servo and updating the goal position of a second servo. The video also features a great new USB Logic 16 from saleae I have recently purchased.

Below please find the python code used in the video. It is by no means final or finished. It was just a quick mock-up to test the hardware. It is however a good starting point or reference for others who want to experiment with the same setup.

import serial
import time

UART2_PORT = "/dev/ttyO2"
UART2_BAUD = 115200
UART2_TX = "spi0_d0"
UART2_RX = "spi0_sclk"
UART2_TXMUX = 1
UART2_RXMUX = 33

UART2_TXIO = 117
UART2_RXIO = 49

AX_ID = 2
AX_LENGTH = 3
AX_INSTRUCTION = 4
AX_PARAMETER = 5
AX_WRITE = 3
AX_READ = 2

open("/sys/class/gpio/unexport", "w").write("%d" % UART2_TXIO)
open("/sys/class/gpio/export", "w").write("%d" % UART2_TXIO)
open("/sys/class/gpio/gpio" + str(UART2_TXIO) + "/direction", "w").write("out")

open("/sys/class/gpio/unexport", "w").write("%d" % UART2_RXIO)
open("/sys/class/gpio/export", "w").write("%d" % UART2_RXIO)
open("/sys/class/gpio/gpio" + str(UART2_RXIO) + "/direction", "w").write("out")

open("/sys/kernel/debug/omap_mux/" + UART2_TX, "wb").write("%x" % UART2_TXMUX)
open("/sys/kernel/debug/omap_mux/" + UART2_RX, "wb").write("%x" % UART2_RXMUX)
ax = serial.Serial(UART2_PORT, UART2_BAUD)

def checksum(packet):
        check = 0
        for i in range(AX_ID, (packet[AX_LENGTH] + 3)):
                check += packet[i]
        return 255 - (check % 256)

def settx():
    open("/sys/class/gpio/gpio" + str(UART2_TXIO) + "/value", "w").write("%d" % 1)
        open("/sys/class/gpio/gpio" + str(UART2_RXIO) + "/value", "w").write("%d" % 0)

def setrx():
    open("/sys/class/gpio/gpio" + str(UART2_TXIO) + "/value", "w").write("%d" % 0)
        open("/sys/class/gpio/gpio" + str(UART2_RXIO) + "/value", "w").write("%d" % 1)

def txrx(txp, rxp):
        txlength = txp[AX_LENGTH] + 4
        rxlength = 0

        txp[0] = 0xff
        txp[1] = 0xff
        txp[txlength - 1] = checksum(txp)

        settx()
        for i in range(txlength): ax.write(chr(txp[i]))
        setrx()

        if txp[AX_INSTRUCTION] != 254:
                if txp[AX_INSTRUCTION] == AX_READ: rxlength = txp[AX_PARAMETER + 1] + 6
                else: rxlength = 6

                time.sleep(.02)
                for x in range(ax.inWaiting()): rxp[x] = ord(ax.read())
                for x in range(txlength + 1): rxp.pop(0)

                if rxp[0] != 255 and rxp[1] != 255: return -2
                if rxp[rxlength - 1] != checksum(rxp): return -3

                return 1

        return 1

def readbyte(id, address):
        txpacket = [0]*8
        rxpacket = [0]*30

        txpacket[AX_ID] = id
        txpacket[AX_LENGTH] = 4
        txpacket[AX_INSTRUCTION] = AX_READ
        txpacket[AX_PARAMETER] = address
        txpacket[AX_PARAMETER + 1] = 1

        result = txrx(txpacket, rxpacket)
        value = rxpacket[AX_PARAMETER]
        return result, value

def readword(id, address):
        txpacket = [0]*8
        rxpacket = [0]*30

        txpacket[AX_ID] = id
        txpacket[AX_LENGTH] = 4
        txpacket[AX_INSTRUCTION] = AX_READ
        txpacket[AX_PARAMETER] = address
        txpacket[AX_PARAMETER + 1] = 2

        result = txrx(txpacket, rxpacket)
        value = ((rxpacket[AX_PARAMETER + 1] << 8) + rxpacket[AX_PARAMETER])
        return result, value

def writebyte(id, address, value):
        txpacket = [0]*8
        rxpacket = [0]*30

        txpacket[AX_ID] = id
        txpacket[AX_LENGTH] = 4
        txpacket[AX_INSTRUCTION] = AX_WRITE
        txpacket[AX_PARAMETER] = address
        txpacket[AX_PARAMETER + 1] = value

        return txrx(txpacket, rxpacket)

def writeword(id, address, value):
        txpacket = [0]*9
        rxpacket = [0]*30

        txpacket[AX_ID] = id
        txpacket[AX_LENGTH] = 5
        txpacket[AX_INSTRUCTION] = AX_WRITE
        txpacket[AX_PARAMETER] = address
        txpacket[AX_PARAMETER + 1] = value & 0xff
        txpacket[AX_PARAMETER + 2] = (value & 0xff00) >> 8

        return txrx(txpacket, rxpacket)

value = 0
writebyte(0x01, 0x18, 0)

while 1:
        result, value = readword(0x01, 36)
        if result == 1:
                #print value
                writeword(0x02, 30, value)
                #time.sleep(.1)

open("/sys/class/gpio/unexport", "w").write("%d" % UART2_TXIO)
open("/sys/class/gpio/unexport", "w").write("%d" % UART2_RXIO)

2 comments on “BeagleBone Dynamixel AX12 Interface – Part 2.5

  1. Craig sharpe on said:

    This is very ironic, I too have a beaglebone, dynamixal AX-12 servos and a saleae (8 channel) logic analyser!

    Would be interested to know what parts your using here and a preview of the code

    :-)

  2. Craig sharpe on said:

    Just realised I can scroll the code snippet..

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>