Humanoid Notes
CM-2 Plus
- In Linux, needed a udev rule to allow permissions to read/write the USB Serial port:
- /etc/udev/rules.d/10-ftdi.rules:
- MODE="0777"
- 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"
- ser.setTimeout(.1)
- ser.write("t\r")
- ser.read(10000)
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
where:
- 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
Us it:
>>> write(0xff, 0xff, 0x01, 0x02, 0x00, 0xfc)
The returned Status Packet is as the following
Status Packet : 0XFF 0XFF 0X01 0X02 0X00 0XFC
where:
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