Difference between revisions of "CAN Protocol"
Alexalspach (Talk | contribs) (→Command Identifiers) |
(→Download) |
||
(28 intermediate revisions by 2 users not shown) | |||
Line 7: | Line 7: | ||
===Periodic Communication=== | ===Periodic Communication=== | ||
− | The Allegro Hand control software attempts to communicate with the real or simulated hand at a regular control interval. Every 3 milliseconds the joint torques are calculated and the joint angles are updated. | + | The Allegro Hand control software attempts to communicate with the real or simulated hand at a regular control interval. Every 3 milliseconds, the joint torques are calculated and the joint angles are updated. |
==CAN Frames== | ==CAN Frames== | ||
===Standard CAN Packet=== | ===Standard CAN Packet=== | ||
− | The standard CAN packet used for communication | + | The standard CAN packet used for communication is 14 bytes including 8 bytes of data. |
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
typedef struct{ | typedef struct{ | ||
− | unsigned char STD_EXT; | + | unsigned char STD_EXT; //type of message (Standard or Extended) |
unsigned long msg_id; //message identifier | unsigned long msg_id; //message identifier | ||
unsigned char data_length; // | unsigned char data_length; // | ||
Line 22: | Line 22: | ||
===ID (Message Identifier)=== | ===ID (Message Identifier)=== | ||
− | The 4 byte integer CAN message is split into the command ID (26 bits), destination ID ( | + | The 4 byte integer CAN message identifier (msg_id) is split into the command ID (26 bits), destination ID (3 bits) and source ID (3 bits). |
− | <br> | + | <br> |
− | + | {|style=" border-collapse: separate; border-spacing: 15; border-width: 2px; border-style: solid; border-color: #CCCCCC; padding: 0px; text-align: left; width: 800px" | |
− | {|style=" border-collapse: separate; border-spacing: 15; border-width: 2px; border-style: solid; border-color: #CCCCCC; padding: 0px; text-align: left; width: | + | |
| style="padding: 0px 0px 0px 3px; width: 21.88%; font-size: 80%" | 1 | | style="padding: 0px 0px 0px 3px; width: 21.88%; font-size: 80%" | 1 | ||
| style="width: 21.88%; font-size: 80%" | 8 | | style="width: 21.88%; font-size: 80%" | 8 | ||
Line 49: | Line 48: | ||
| style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Value | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Value | ||
| style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Description | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Description | ||
− | |||
| style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Destination | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Destination | ||
+ | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Source | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_SYSTEM_ON | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_SYSTEM_ON | ||
| style="padding: 2px 5px 2px 5px" | 0x01 | | style="padding: 2px 5px 2px 5px" | 0x01 | ||
| style="padding: 2px 5px 2px 5px" | Start periodic communication | | style="padding: 2px 5px 2px 5px" | Start periodic communication | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_SYSTEM_OFF | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_SYSTEM_OFF | ||
| style="padding: 2px 5px 2px 5px" | 0x02 | | style="padding: 2px 5px 2px 5px" | 0x02 | ||
| style="padding: 2px 5px 2px 5px" | Stop periodic communication | | style="padding: 2px 5px 2px 5px" | Stop periodic communication | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_PERIOD | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_PERIOD | ||
| style="padding: 2px 5px 2px 5px" | 0x03 | | style="padding: 2px 5px 2px 5px" | 0x03 | ||
| style="padding: 2px 5px 2px 5px" | Set communication frequency | | style="padding: 2px 5px 2px 5px" | Set communication frequency | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_MODE_JOINT | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_MODE_JOINT | ||
| style="padding: 2px 5px 2px 5px" | 0x04 | | style="padding: 2px 5px 2px 5px" | 0x04 | ||
| style="padding: 2px 5px 2px 5px" | Command Transmission Mode | | style="padding: 2px 5px 2px 5px" | Command Transmission Mode | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_MODE_TASK | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_MODE_TASK | ||
| style="padding: 2px 5px 2px 5px" | 0x05 | | style="padding: 2px 5px 2px 5px" | 0x05 | ||
| style="padding: 2px 5px 2px 5px" | Command Transmission Mode | | style="padding: 2px 5px 2px 5px" | Command Transmission Mode | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_1 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_1 | ||
| style="padding: 2px 5px 2px 5px" | 0x06 | | style="padding: 2px 5px 2px 5px" | 0x06 | ||
| style="padding: 2px 5px 2px 5px" | Index finger (1) torque command | | style="padding: 2px 5px 2px 5px" | Index finger (1) torque command | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_2 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_2 | ||
| style="padding: 2px 5px 2px 5px" | 0x07 | | style="padding: 2px 5px 2px 5px" | 0x07 | ||
− | | style="padding: 2px 5px 2px 5px" | Middle finger (2) | + | | style="padding: 2px 5px 2px 5px" | Middle finger (2) torque command |
− | + | ||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_3 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_3 | ||
| style="padding: 2px 5px 2px 5px" | 0x08 | | style="padding: 2px 5px 2px 5px" | 0x08 | ||
| style="padding: 2px 5px 2px 5px" | Pinky finger (3) torque command | | style="padding: 2px 5px 2px 5px" | Pinky finger (3) torque command | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_4 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_TORQUE_4 | ||
| style="padding: 2px 5px 2px 5px" | 0x09 | | style="padding: 2px 5px 2px 5px" | 0x09 | ||
| style="padding: 2px 5px 2px 5px" | Thumb torque command | | style="padding: 2px 5px 2px 5px" | Thumb torque command | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_1 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_1 | ||
| style="padding: 2px 5px 2px 5px" | 0x0a | | style="padding: 2px 5px 2px 5px" | 0x0a | ||
| style="padding: 2px 5px 2px 5px" | (unused) | | style="padding: 2px 5px 2px 5px" | (unused) | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_2 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_2 | ||
| style="padding: 2px 5px 2px 5px" | 0x0b | | style="padding: 2px 5px 2px 5px" | 0x0b | ||
| style="padding: 2px 5px 2px 5px" | (unused) | | style="padding: 2px 5px 2px 5px" | (unused) | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_3 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_3 | ||
| style="padding: 2px 5px 2px 5px" | 0x0c | | style="padding: 2px 5px 2px 5px" | 0x0c | ||
| style="padding: 2px 5px 2px 5px" | (unused) | | style="padding: 2px 5px 2px 5px" | (unused) | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_4 | | style="padding: 2px 5px 2px 5px" | ID_CMD_SET_POSITION_4 | ||
| style="padding: 2px 5px 2px 5px" | 0x0d | | style="padding: 2px 5px 2px 5px" | 0x0d | ||
| style="padding: 2px 5px 2px 5px" | (unused) | | style="padding: 2px 5px 2px 5px" | (unused) | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_QUERY_STATE_DATA | | style="padding: 2px 5px 2px 5px" | ID_CMD_QUERY_STATE_DATA | ||
| style="padding: 2px 5px 2px 5px" | 0x0e | | style="padding: 2px 5px 2px 5px" | 0x0e | ||
| style="padding: 2px 5px 2px 5px" | Request joint state | | style="padding: 2px 5px 2px 5px" | Request joint state | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_COMMON | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
|- | |- | ||
| style="padding: 2px 5px 2px 5px" | ID_CMD_QUERY_STATE_DATA | | style="padding: 2px 5px 2px 5px" | ID_CMD_QUERY_STATE_DATA | ||
| style="padding: 2px 5px 2px 5px" | 0x0e | | style="padding: 2px 5px 2px 5px" | 0x0e | ||
| style="padding: 2px 5px 2px 5px" | Joint state response | | style="padding: 2px 5px 2px 5px" | Joint state response | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_SUB_01<br>ID_DEVICE_SUB_02<br>ID_DEVICE_SUB_03<br>ID_DEVICE_SUB_04 | ||
|- | |- | ||
| style="padding: 5px 5px 2px 5px" | ID_CMD_QUERY_CONTROL_DATA | | style="padding: 5px 5px 2px 5px" | ID_CMD_QUERY_CONTROL_DATA | ||
| style="padding: 2px 5px 2px 5px" | 0x0f | | style="padding: 2px 5px 2px 5px" | 0x0f | ||
| style="padding: 2px 5px 2px 5px" | Joint state response | | style="padding: 2px 5px 2px 5px" | Joint state response | ||
− | |||
| style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
+ | | style="padding: 2px 5px 5px 5px" | ID_DEVICE_SUB_01<br>ID_DEVICE_SUB_02<br>ID_DEVICE_SUB_03<br>ID_DEVICE_SUB_04 | ||
|- | |- | ||
|} | |} | ||
Line 153: | Line 152: | ||
====Source and Destination Identifiers==== | ====Source and Destination Identifiers==== | ||
− | + | {|style=" border-collapse: separate; border-spacing: 15; border-width: 2px; border-style: solid; border-color: #CCCCCC; padding: 0px; text-align: left; width: 520px" | |
− | + | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Variable Name | |
− | < | + | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Value |
+ | | style="padding: 3px 5px 2px 5px; background: #F0F0F0" | Description | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_COMMON | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x01 | ||
+ | | style="padding: 2px 5px 2px 5px" | Allegro Hand | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_MAIN | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x02 | ||
+ | | style="padding: 2px 5px 2px 5px" | Control PC | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_SUB_01 | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x03 | ||
+ | | style="padding: 2px 5px 2px 5px" | Index Finger | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_SUB_02 | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x04 | ||
+ | | style="padding: 2px 5px 2px 5px" | Middle Finger | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_SUB_03 | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x05 | ||
+ | | style="padding: 2px 5px 2px 5px" | Little Finger | ||
+ | |- | ||
+ | | style="padding: 2px 5px 2px 5px" | ID_DEVICE_SUB_04 | ||
+ | | style="padding: 2px 5px 2px 5px" | 0x06 | ||
+ | | style="padding: 2px 5px 2px 5px" | Thumb | ||
+ | |- | ||
+ | |} | ||
+ | <br> | ||
==Case-study: Softing CAN== | ==Case-study: Softing CAN== | ||
Line 227: | Line 254: | ||
===Transmitting Control Torques=== | ===Transmitting Control Torques=== | ||
Control inputs for the four joints in each finger should be packed in a single CAN frame. The sample code below demontrates how to encode four PWM inputs into an 8 byte data buffer and how to set the CAN frame ID properly. | Control inputs for the four joints in each finger should be packed in a single CAN frame. The sample code below demontrates how to encode four PWM inputs into an 8 byte data buffer and how to set the CAN frame ID properly. | ||
+ | |||
+ | '''''Note:''' PWM = Desired_Torque (N-m) * '''800.0'''.<br>800.0 is an empirical constant that will convert torque to PWM.''<br> | ||
+ | As seen below, ''torque2pwm = 800.0'' | ||
+ | |||
+ | |||
+ | '''''Note:''' The joint index order used in the following code is for '''Allegro Hand versions 2.0 and up'''. For Allegro hand 1.0 or earlier, see the code snippet after this one.'' | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
Line 239: | Line 272: | ||
}; | }; | ||
+ | // This joint index order is used Allegro Hand versions 2.0 and up. | ||
+ | if (findex >= 0 && findex < 4) | ||
+ | { | ||
+ | data[0] = (unsigned char)( (pwm[3] >> 8) & 0x00ff); | ||
+ | data[1] = (unsigned char)(pwm[3] & 0x00ff); | ||
+ | |||
+ | data[2] = (unsigned char)( (pwm[2] >> 8) & 0x00ff); | ||
+ | data[3] = (unsigned char)(pwm[2] & 0x00ff); | ||
+ | |||
+ | data[4] = (unsigned char)( (pwm[1] >> 8) & 0x00ff); | ||
+ | data[5] = (unsigned char)(pwm[1] & 0x00ff); | ||
+ | |||
+ | data[6] = (unsigned char)( (pwm[0] >> 8) & 0x00ff); | ||
+ | data[7] = (unsigned char)(pwm[0] & 0x00ff); | ||
+ | |||
+ | Txid = ((unsigned long)(ID_CMD_SET_TORQUE_1 + findex)<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); | ||
+ | canWrite(hCAN, Txid, data, 8, STD); | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | |||
+ | '''''Note:''' The joint index order used in the following code is for '''Allegro Hand versions 1.0 and down'''. For Allegro hand 2.0 or later, see the code snippet before this one.'' | ||
+ | |||
+ | <syntaxhighlight lang="cpp"> | ||
+ | // This joint index order is used Allegro Hand versions 1.0 and down. | ||
if (findex >= 0 && findex < 4) | if (findex >= 0 && findex < 4) | ||
{ | { | ||
Line 258: | Line 318: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | |||
===Receiving Joint Angles=== | ===Receiving Joint Angles=== | ||
Each finger consists of four joints. The joint angles for those four joints can be received via one CAN packet. The sample code below demonstrates the method for decoding the data buffer and reading the joint angles. | Each finger consists of four joints. The joint angles for those four joints can be received via one CAN packet. The sample code below demonstrates the method for decoding the data buffer and reading the joint angles. | ||
Line 332: | Line 394: | ||
==Download== | ==Download== | ||
− | [ | + | [http://wiki.wonikrobotics.com/AllegroHandWiki/images/8/83/AllegroHandCanProtocol.pdf Allegro Hand CAN Protocol (English)] ----------- This page.<br> |
− | [ | + | [http://wiki.wonikrobotics.com/AllegroHandWiki/images/a/a2/AllegroHandCanProtocol_KR.pdf Allegro Hand CAN Protocol (Korean)]<br> |
Latest revision as of 14:21, 18 May 2016
Contents |
[edit] CAN Communication
[edit] Baud-Rate
The CAN communication baud-rate is 1Mbps.
[edit] Non-Periodic Communication
Messages can be sent to initialize or stop CAN communication.
[edit] Periodic Communication
The Allegro Hand control software attempts to communicate with the real or simulated hand at a regular control interval. Every 3 milliseconds, the joint torques are calculated and the joint angles are updated.
[edit] CAN Frames
[edit] Standard CAN Packet
The standard CAN packet used for communication is 14 bytes including 8 bytes of data.
typedef struct{ unsigned char STD_EXT; //type of message (Standard or Extended) unsigned long msg_id; //message identifier unsigned char data_length; // char data[8]; // data array } can_msg;
[edit] ID (Message Identifier)
The 4 byte integer CAN message identifier (msg_id) is split into the command ID (26 bits), destination ID (3 bits) and source ID (3 bits).
1 | 8 | 16 | 24 | 26 | 27 | 29 | 30 | 32 |
Command ID | Dest. ID | Source ID |
[edit] Command Identifiers
Variable Name | Value | Description | Destination | Source |
ID_CMD_SET_SYSTEM_ON | 0x01 | Start periodic communication | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_SYSTEM_OFF | 0x02 | Stop periodic communication | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_PERIOD | 0x03 | Set communication frequency | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_MODE_JOINT | 0x04 | Command Transmission Mode | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_MODE_TASK | 0x05 | Command Transmission Mode | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_TORQUE_1 | 0x06 | Index finger (1) torque command | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_TORQUE_2 | 0x07 | Middle finger (2) torque command | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_TORQUE_3 | 0x08 | Pinky finger (3) torque command | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_TORQUE_4 | 0x09 | Thumb torque command | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_POSITION_1 | 0x0a | (unused) | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_POSITION_2 | 0x0b | (unused) | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_POSITION_3 | 0x0c | (unused) | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_SET_POSITION_4 | 0x0d | (unused) | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_QUERY_STATE_DATA | 0x0e | Request joint state | ID_COMMON | ID_DEVICE_MAIN |
ID_CMD_QUERY_STATE_DATA | 0x0e | Joint state response | ID_DEVICE_MAIN | ID_DEVICE_SUB_01 ID_DEVICE_SUB_02 ID_DEVICE_SUB_03 ID_DEVICE_SUB_04 |
ID_CMD_QUERY_CONTROL_DATA | 0x0f | Joint state response | ID_DEVICE_MAIN | ID_DEVICE_SUB_01 ID_DEVICE_SUB_02 ID_DEVICE_SUB_03 ID_DEVICE_SUB_04 |
[edit] Source and Destination Identifiers
Variable Name | Value | Description |
ID_COMMON | 0x01 | Allegro Hand |
ID_DEVICE_MAIN | 0x02 | Control PC |
ID_DEVICE_SUB_01 | 0x03 | Index Finger |
ID_DEVICE_SUB_02 | 0x04 | Middle Finger |
ID_DEVICE_SUB_03 | 0x05 | Little Finger |
ID_DEVICE_SUB_04 | 0x06 | Thumb |
[edit] Case-study: Softing CAN
In this chapter, sample code demonstrating the implementation of the CAN communication interface is provide. This is the foundation for Softing PCI CAN.
[edit] Opening the CAN Communication Channel
char ch_name[256]; sprintf_s(ch_name, 256, "CAN-ACx-PCI_%d", ch); INIL2_initialize_channel(&hCAN[ch-1], ch_name); L2CONFIG L2Config; L2Config.fBaudrate = 1000.0; L2Config.bEnableAck = 0; L2Config.bEnableErrorframe = 0; L2Config.s32AccCodeStd = 0; L2Config.s32AccMaskStd = 0; L2Config.s32AccCodeXtd = 0; L2Config.s32AccMaskXtd = 0; L2Config.s32OutputCtrl = GET_FROM_SCIM; L2Config.s32Prescaler = 1; L2Config.s32Sam = 0; L2Config.s32Sjw = 1; L2Config.s32Tseg1 = 4; L2Config.s32Tseg2 = 3; L2Config.hEvent = (void*)-1; CANL2_initialize_fifo_mode(hCAN[ch-1], &L2Config);
[edit] CAN Initialization
long Txid; unsigned char data[8]; Txid = ((unsigned long)ID_CMD_SET_PERIOD<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); data[0] = (unsigned char)period_msec; canWrite(hCAN, Txid, data, 1, STD); Sleep(10); Txid = ((unsigned long)ID_CMD_SET_MODE_TASK<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN, Txid, data, 0, STD); Sleep(10); Txid = ((unsigned long)ID_CMD_QUERY_STATE_DATA<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN, Txid, data, 0, STD);
[edit] Starting Periodic CAN Communication
When you start periodic CAN communication, joint angles are automatically updated according to the torque control input.
long Txid; unsigned char data[8]; Txid = ((unsigned long)ID_CMD_QUERY_STATE_DATA<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN[ch-1], Txid, data, 0, STD); Sleep(10); Txid = ((unsigned long)ID_CMD_SET_SYSTEM_ON<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN[ch-1], Txid, data, 0, STD);
[edit] Stopping Periodic CAN Communication
long Txid; unsigned char data[8]; Txid = ((unsigned long)ID_CMD_SET_SYSTEM_OFF<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN[ch-1], Txid, data, 0, STD);
[edit] Transmitting Control Torques
Control inputs for the four joints in each finger should be packed in a single CAN frame. The sample code below demontrates how to encode four PWM inputs into an 8 byte data buffer and how to set the CAN frame ID properly.
Note: PWM = Desired_Torque (N-m) * 800.0.
800.0 is an empirical constant that will convert torque to PWM.
As seen below, torque2pwm = 800.0
Note: The joint index order used in the following code is for Allegro Hand versions 2.0 and up. For Allegro hand 1.0 or earlier, see the code snippet after this one.
long Txid; unsigned char data[8]; float torque2pwm = 800.0f short pwm[4] = { 0.1*torque2pwm, 0.1*torque2pwm, 0.1*torque2pwm, 0.1*torque2pwm }; // This joint index order is used Allegro Hand versions 2.0 and up. if (findex >= 0 && findex < 4) { data[0] = (unsigned char)( (pwm[3] >> 8) & 0x00ff); data[1] = (unsigned char)(pwm[3] & 0x00ff); data[2] = (unsigned char)( (pwm[2] >> 8) & 0x00ff); data[3] = (unsigned char)(pwm[2] & 0x00ff); data[4] = (unsigned char)( (pwm[1] >> 8) & 0x00ff); data[5] = (unsigned char)(pwm[1] & 0x00ff); data[6] = (unsigned char)( (pwm[0] >> 8) & 0x00ff); data[7] = (unsigned char)(pwm[0] & 0x00ff); Txid = ((unsigned long)(ID_CMD_SET_TORQUE_1 + findex)<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN, Txid, data, 8, STD); }
Note: The joint index order used in the following code is for Allegro Hand versions 1.0 and down. For Allegro hand 2.0 or later, see the code snippet before this one.
// This joint index order is used Allegro Hand versions 1.0 and down. if (findex >= 0 && findex < 4) { data[0] = (unsigned char)( (pwm[0] >> 8) & 0x00ff); data[1] = (unsigned char)(pwm[0] & 0x00ff); data[2] = (unsigned char)( (pwm[1] >> 8) & 0x00ff); data[3] = (unsigned char)(pwm[1] & 0x00ff); data[4] = (unsigned char)( (pwm[2] >> 8) & 0x00ff); data[5] = (unsigned char)(pwm[2] & 0x00ff); data[6] = (unsigned char)( (pwm[3] >> 8) & 0x00ff); data[7] = (unsigned char)(pwm[3] & 0x00ff); Txid = ((unsigned long)(ID_CMD_SET_TORQUE_1 + findex)<<6) | ((unsigned long)ID_COMMON <<3) | ((unsigned long)ID_DEVICE_MAIN); canWrite(hCAN, Txid, data, 8, STD); }
[edit] Receiving Joint Angles
Each finger consists of four joints. The joint angles for those four joints can be received via one CAN packet. The sample code below demonstrates the method for decoding the data buffer and reading the joint angles.
The sample code assumes that when fingers are in their zero positions, the joint angles from the can packet are 32768. In practice, users should perform experiments and introduce offsets to obtain the zero position.
char cmd; char src; char des; int len; unsigned char data[8]; int ret; can_msg msg; PARAM_STRUCT param; ret = CANL2_read_ac(hCAN, ¶m); switch (ret) { case CANL2_RA_DATAFRAME: msg.msg_id = param.Ident; msg.STD_EXT = STD; msg.data_length = param.DataLength; msg.data[0] = param.RCV_data[0]; msg.data[1] = param.RCV_data[1]; msg.data[2] = param.RCV_data[2]; msg.data[3] = param.RCV_data[3]; msg.data[4] = param.RCV_data[4]; msg.data[5] = param.RCV_data[5]; msg.data[6] = param.RCV_data[6]; msg.data[7] = param.RCV_data[7]; break; } cmd = (char)( (msg.msg_id >> 6) & 0x1f ); des = (char)( (msg.msg_id >> 3) & 0x07 ); src = (char)( msg.msg_id & 0x07 ); len = (int)( msg.data_length ); for(int nd=0; nd<len; nd++) data[nd] = msg.data[nd]; switch (cmd) { case ID_CMD_QUERY_CONTROL_DATA: { if (id_src >= ID_DEVICE_SUB_01 && id_src <= ID_DEVICE_SUB_04) { int temp_pos[4]; // raw angle data float ang[4]; // degree float q[4]; // radian temp_pos[0] = (int)(data[0] | (data[1] << 8)); temp_pos[1] = (int)(data[2] | (data[3] << 8)); temp_pos[2] = (int)(data[4] | (data[5] << 8)); temp_pos[3] = (int)(data[6] | (data[7] << 8)); ang[0] = ((float)(temp_pos[0]-32768)*(333.3f/65536.0f))*(1); ang[1] = ((float)(temp_pos[1]-32768)*(333.3f/65536.0f))*(1); ang[2] = ((float)(temp_pos[2]-32768)*(333.3f/65536.0f))*(1); ang[3] = ((float)(temp_pos[3]-32768)*(333.3f/65536.0f))*(1); q[0] = (3.141592f/180.0f) * ang[0]; q[1] = (3.141592f/180.0f) * ang[1]; q[2] = (3.141592f/180.0f) * ang[2]; q[3] = (3.141592f/180.0f) * ang[3]; } } }
[edit] Download
Allegro Hand CAN Protocol (English) ----------- This page.
Allegro Hand CAN Protocol (Korean)
Whos here now: Members 0 Guests 0 Bots & Crawlers 1 |