- In Linux, needed a udev rule to allow permissions to read/write the USB Serial port:
- Put the CM-2+ in Manager Mode (1st blinking light)
- Open the serial port at 57600 baud
- import serial
- ser = serial.Serial("/dev/ttyUSB0", 57600)
- The CM-2+ will use its own UART to talk to the Dynamixel Bus at a Baud rate of 1000000
- send it a "t" and return and newline to put into "toss mode"
Now you are ready to send it byte commands.
Example: Ping Instruction
First, let's write a little Python function that will construct a string from a series of bytes:
def write(*s): ser.write("".join(map(chr, s)))
This assumes that there is a serial port called "ser" already opened and ready to use. The *s allows any number of arguments, which will be put into the list named "s". The "".join() joins the list together with nothing between them; the map(chr, s) will turn each number into a character.
Now, let's open a serial port, and use the write function to send a command. Looking up an example, we see that "0xff 0xff 0x01 0x02 0x00 0xfc" will query Dynamixel 1. From the manual:
Obtaining the status packet of the Dynamixel actuator with an ID of 1
Send Instruction Packet : 0XFF 0XFF 0X01 0X02 0X01 0XFB
- 0xFF 0xFF begins each packet
- 0x01 is ID
- 0x02 is the LENGTH of what comes next
- 0x01 is the INSTRUCTION code
- 0xFB is the CHECKSUM
>>> write(0xff, 0xff, 0x01, 0x02, 0x00, 0xfc)
The returned Status Packet is as the following
Status Packet : 0XFF 0XFF 0X01 0X02 0X00 0XFC
0x01 is the ID 0x02 is the LENGTH of what comes next 0x00 is the ERROR code 0xFC is the CHECKSUM
Let's try it. We read the data:
>>> ser.read(6) '\xff\xff\x01\x02@\xbc'
Regardless of whether the Broadcasting ID is used (0xFE) or the Status Return Level (Address 16) is 0, a Status Packet is always returned by the PING instruction.
We should probably read byte by byte:
>>> write(0xff, 0xff, 0x01, 0x02, 0x00, 0xfc) >>> b1 = ser.read(1) >>> b1 == 0xff >>> b2 = ser.read(1) >>> b2 == 0xff
Ok so far.
>>> id = ser.read(1) >>> id == 0x01
And then let's get the data:
>>> data_len = ser.read(1) >>> data_len == 2 >>> error = ser.read(1) >>> checksum = ser.read(1)
Shouldn't be anything else to read:
>>> leftover = ser.read(1) >>> len(leftover) == 0