Difference between revisions of "Humanoid Notes"

From IPRE Wiki
Jump to: navigation, search
(CM-2 Plus)
Line 11: Line 11:
 
# send it a "t" and return and newline to put into "toss mode"
 
# send it a "t" and return and newline to put into "toss mode"
 
## ser.setTimeout(.1)
 
## ser.setTimeout(.1)
## ser.write("t\r\n")
+
## ser.write("t\r")
 
## ser.read(10000)
 
## ser.read(10000)
  
 
Now you are ready to send it byte commands.
 
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
  
 
== Links ==
 
== Links ==

Revision as of 02:28, 2 July 2010

CM-2 Plus

  1. In Linux, needed a udev rule to allow permissions to read/write the USB Serial port:
    1. /etc/udev/rules.d/10-ftdi.rules:
    2. MODE="0777"
  2. Put the CM-2+ in Manager Mode (1st blinking light)
  3. Open the serial port at 57600 baud
    1. import serial
    2. ser = serial.Serial("/dev/ttyUSB0", 57600)
  4. The CM-2+ will use its own UART to talk to the Dynamixel Bus at a Baud rate of 1000000
  5. send it a "t" and return and newline to put into "toss mode"
    1. ser.setTimeout(.1)
    2. ser.write("t\r")
    3. 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:

  1. 0xFF 0xFF begins each packet
  2. 0x01 is ID
  3. 0x02 is the LENGTH of what comes next
  4. 0x01 is the INSTRUCTION code
  5. 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

Links