OHand 通信协议 V3.0
1. 通信协议概要
用户主控单元通过发送命令数据实现对灵巧手的状态获取和控制。 上位系统向 ROH 灵巧手发送读指令,ROH 灵巧手收到指令数据并校验成功后,将相应的结果返回给上位系统。
注: CAN协议和串口协议指令格式相同,CAN协议使用CAN报文的形式,一帧8个字节,CAN ID和灵巧手ID保持一致
2. 通讯参数
RS232、RS485 通讯参数都是 115200bps、8 数据位、1 停止位、无奇偶校验。
CAN 通讯参数是 1000000bps。
3. 灵巧手串口指令帧格式
操作 ROH 灵巧手的指令帧格式如下:
| 字节 | 数值 | 说明 |
|---|---|---|
| byte[0] | 0x55 | 包头 |
| byte[1] | 0xAA | 包头 |
| byte[2] | HandID | ROH 灵巧手 ID 号 |
| byte[3] | MasterID | 主机 ID 号 |
| byte[4] | Command | 操作命令 |
| byte[5] | DataLen | 该帧数据部分长度,即 byte[6]..byte[6 + DataLen - 1] |
| byte[6]..byte[6 + DataLen - 1] | Data[0]..Data[DataLen-1] | 命令数据 |
| byte[6 + DataLen] | Checksum | 校验码(参见 4. LRC 校验码计算方式) |
ROH 灵巧手对指令的回复帧如下:
| 字节 | 数值 | 说明 |
|---|---|---|
| byte[0] | 0x55 | 包头 |
| byte[1] | 0xAA | 包头 |
| byte[2] | MasterID | 主机 ID 号 |
| byte[3] | HandID | ROH 灵巧手 ID 号 |
| byte[4] | Command | 操作命令,如果指令执行错误,那么最高位为 1,低七位为操作命令,Data[0]为错误代码(参见 6. 灵巧手错误代码) |
| byte[5] | DataLen | 该帧数据部分长度,即 byte[6]..byte[6 + DataLen - 1] |
| byte[6]..byte[6 + DataLen - 1] | Data[0]..Data[DataLen - 1] | 返回数据 |
| byte[6 + DataLen] | Checksum | 校验码(参见 4. LRC 校验码计算方式) |
示例:
指令帧(HEX):
| 包头 | 灵巧手 ID | 主机 ID | 操作命令 | 数据长度 | 数据 | 校验码 |
|---|---|---|---|---|---|---|
| 55 AA | 02 | 01 | 50 | 12 | 10 27 FF 10 27 FF 10 27 FF 10 27 FF 10 27 FF 10 27 FF | 66 |
正确回复帧(HEX):
| 包头 | 主机 ID | 灵巧手 ID | 操作命令 | 数据长度 | 数据 | 校验码 |
|---|---|---|---|---|---|---|
| 55 AA | 01 | 02 | 50 | 00 | NULL | 53 |
错误回复帧(HEX):
| 包头 | 主机 ID | 灵巧手 ID | 操作命令 | 数据长度 | 数据 | 校验码 |
|---|---|---|---|---|---|---|
| 55 AA | 01 | 02 | D0 | 01 | 01 | D3 |
注: 操作命令为指令帧的操作码与0x80或后的值,数据位为错误代码
4. LRC 校验码计算方式
灵巧手串口指令帧中 byte[2]..byte[6 + DataLen - 1]的各字节异或值:
uint8_t buf[...];
uint8_t lrc = 0;
uint8_t cmd_data_len = 4/* sizeof(MasterID) + sizeof(HandID) + sizeof(Command) + sizeof(DataLen) */ + DataLen;
/* Fill buf */
buf[0] = 0x55;
buf[1] = 0xAA;
...
for (int i=0; i<cmd_data_len; i++)
lrc ^= buf[2 + i];
buf[2 + cmd_data_len] = lrc;
5. 灵巧手指令
| 指令名称 | 值 | 说明 | 数据字节 | 回复数据 |
|---|---|---|---|---|
| HAND_CMD_GET_PROTOCOL_VERSION | 0x00 | 获取协议版本 | [PROTOCOL_MINOR_VERSION, PROTOCOL_MAJOR_VERSION] | |
| HAND_CMD_GET_FW_VERSION | 0x01 | 获取固件版本 | [FW_REVISION_L, FW_REVISION_H, FW_MINOR_VERSION, FW_MAJOR_VERSION] | |
| HAND_CMD_GET_HW_VERSION | 0x02 | 获取硬件版本 | [HW_TYPE, HW_VER, BOOT_VER_MAJOR, BOOT_VER_MINOR] | |
| HAND_CMD_GET_CALI_DATA | 0x03 | 获取校正数据 | [F0_RANGE_END_L, F0_RANGE_END_H, ..., Fn_RANGE_END_L, Fn_RANGE_END_H, F0_RANGE_START_L, F0_RANGE_START_H, ..., Fn_RANGE_START_L, Fn_RANGE_START_H, THUMB_ROOT_POS1_L, THUMB_ROOT_POS1_H, ..., THUMB_ROOT_POSn_L, THUMB_ROOT_POSn_H] | |
| HAND_CMD_GET_FINGER_PID | 0x04 | 获取手指PID值,数据类型 float32 | [FINGER_ID] | [FINGER_ID, P_BYTE0, P_BYTE1, P_BYTE2, P_BYTE3, I_BYTE0, I_BYTE1, I_BYTE2, I_BYTE3, D_BYTE0, D_BYTE1, D_BYTE2, D_BYTE3, G_BYTE0, G_BYTE1, G_BYTE2, G_BYTE3] |
| HAND_CMD_GET_FINGER_CURRENT_LIMIT | 0x05 | 获取手指电流限制值,单位mA | [FINGER_ID] | [FINGER_ID, CURRENT_LIMIT_L, CURRENT_LIMIT_H] |
| HAND_CMD_GET_FINGER_CURRENT | 0x06 | 获取手指电流值,单位mA | [FINGER_ID] | [FINGER_ID, CURRENT_L, CURRENT_H] |
| HAND_CMD_GET_FINGER_FORCE_TARGET | 0x07 | 获取手指力量目标值,单位mN, 开机时恢复为默认值0 | [FINGER_ID] | [FINGER_ID, FORCE_TARGET_L, FORCE_TARGET_H] |
| HAND_CMD_GET_FINGER_FORCE | 0x08 | 获取手指当前力量值,单位 mN | [FINGER_ID] | [FINGER_ID, FORCE_ENTRY_CNT, FORCE0_L, FORCE0_H, ..., FORCEn_L, FORCEn_H] |
| HAND_CMD_GET_FINGER_POS_LIMIT | 0x09 | 获取手指绝对位置限制值 | [FINGER_ID] | [FINGER_ID, POS_LIMIT_L, POS_LIMIT_H] |
| HAND_CMD_GET_FINGER_POS_ABS | 0x0A | 获取手指当前绝对位置值 | [FINGER_ID] | [FINGER_ID, ABS_TARGET_POS_L, ABS_TARGET_POS_H, ABSOLUTE_POS_L, ABSOLUTE_POS_H] |
| HAND_CMD_GET_FINGER_POS | 0x0B | 获取手指当前逻辑位置值 | [FINGER_ID] | [FINGER_ID, LOGICAL_TARGET_POS_L, LOGICAL_TARGET_POS_H, LOGICAL_POS_L, LOGICAL_POS_H] |
| HAND_CMD_GET_FINGER_ANGLE | 0x0C | 获取手指第一关节角度,等于实际值 * 100 | [FINGER_ID] | [FINGER_ID, TARGET_ANGLE_L, TARGET_ANGLE_H, CURRENT_ANGLE_L, CURRENT_ANGLE_H] |
| HAND_CMD_GET_THUMB_ROOT_POS | 0x0D | 获取大拇指旋转预设位置, {0, 1, 2, 255}, 255 为未知 | [PRESET_POS] | |
| HAND_CMD_GET_FINGER_POS_ABS_ALL | 0x0E | 获取所有手指当前的绝对位置 | [F0_TARGET_ABS_POS_L, F0_TARGET_ABS_POS_H, ..., Fn_TARGET_ABS_POS_L, Fn_TARGET_ABS_POS_H, F0_CURRENT_ABS_POS_L, F0_CURRENT_ABS_POS_H, ..., Fn_CURRENT_ABS_POS_L, Fn_CURRENT_ABS_POS_H] | |
| HAND_CMD_GET_FINGER_POS_ALL | 0x0F | 获取所有手指当前的逻辑位置 | [F0_TARGET_LOGICAL_POS_L, F0_TARGET_LOGICAL_POS_H, ..., Fn_TARGET_LOGICAL_POS_L, Fn_TARGET_LOGICAL_POS_H, F0_CURRENT_LOGICAL_POS_L, F0_CURRENT_LOGICAL_POS_H, ..., Fn_CURRENT_LOGICAL_POS_L, Fn_CURRENT_LOGICAL_POS_H] | |
| HAND_CMD_GET_FINGER_ANGLE_ALL | 0x10 | 获取所有手指第一关节角度,等于实际值 * 100 | [F0_TARGET_ANGLE_L, F0_TARGET_ANGLE_H, ..., Fn_TARGET_ANGLE_L, Fn_TARGET_ANGLE_H, F0_CURRENT_ANGLE_L, F0_CURRENT_ANGLE_H, ..., Fn_CURRENT_ANGLE_L, Fn_CURRENT_ANGLE_H] | |
| HAND_CMD_GET_FINGER_STOP_PARAMS | 0x11 | 获取手指停机保护参数:速度(逻辑位置/s)、电流(mA)、持续时间(ms)、重试时间(ms) | [FINGER_ID] | [FINGER_ID, SPEED_L, SPEED_H, STOP_CURRENT_L, STOP_CURRENT_H, STOP_AFTER_PERIOD_L, STOP_AFTER_PERIOD_H, RETRY_INTERVAL_L, RETRY_INTERVAL_H] |
| HAND_CMD_GET_FINGER_FORCE_PID | 0x12 | 获取手指力量PID值,数据类型 float32 | [FINGER_ID] | [FINGER_ID, P_BYTE0, P_BYTE1, P_BYTE2, P_BYTE3, I_BYTE0, I_BYTE1, I_BYTE2, I_BYTE3, D_BYTE0, D_BYTE1, D_BYTE2, D_BYTE3, G_BYTE0, G_BYTE1, G_BYTE2, G_BYTE3] |
| HAND_CMD_GET_SELF_TEST_SWITCH | 0x20 | 获取自检开关状态,0:关,1:开 | [ON_OFF] | |
| HAND_CMD_GET_BEEP_SWITCH | 0x21 | 获取蜂鸣器开关状态,0:关,1:开 | [ON_OFF] | |
| HAND_CMD_GET_BUTTON_PRESSED_CNT | 0x22 | 获取按钮按下次数,ROHand请忽略 | [BTN_PRESSED_CNT] | |
| HAND_CMD_GET_UID | 0x23 | 获取手UID | [UID0_BYTE0, UID0_BYTE1, UID0_BYTE2, UID0_BYTE3, UID1_BYTE0, UID1_BYTE1, UID1_BYTE2, UID1_BYTE3, UID2_BYTE0, UID2_BYTE1, UID2_BYTE2, UID2_BYTE3] | |
| HAND_CMD_GET_BATTERY_VOLTAGE | 0x24 | 获取电池电压,单位mV,ROHand请忽略 | [BATTERY_VOLTAGE_L, BATTERY_VOLTAGE_H] | |
| HAND_CMD_GET_USAGE_STAT | 0x25 | 获取使用数据,ROHand请忽略 | [MOTOR_CNT] | [USE_TIME_BYTE0, USE_TIME_BYTE1, USE_TIME_BYTE2, USE_TIME_BYTE3, F0_OPEN_CNT_BYTE0, F0_OPEN_CNT_BYTE1, F0_OPEN_CNT_BYTE2, F0_OPEN_CNT_BYTE3, ..., Fn_OPEN_CNT_BYTE0, Fn_OPEN_CNT_BYTE1, Fn_OPEN_CNT_BYTE2, Fn_OPEN_CNT_BYTE3] |
| HAND_CMD_GET_MANUFACTURE_DATA | 0x3E | 获取厂方数据 | [BYTE0, ..., BYTEn] | |
| HAND_CMD_GET_VENDOR_ID | 0x3F | 获取供应商ID | ['O', 'Y'] | |
| HAND_CMD_RESET | 0x40 | 重启,MODE=0:重启进入工作状态;MODE=1:重启进入DFU模式 | [MODE] | |
| HAND_CMD_POWER_OFF | 0x41 | 关机,ROHand请忽略 | ||
| HAND_CMD_SET_NODE_ID | 0x42 | 设置手节点ID | [NODE_ID] | |
| HAND_CMD_CALIBRATE | 0x43 | 校正手,仅限出厂使用 | [KEY_L, KEY_H] | |
| HAND_CMD_SET_CALI_DATA | 0x44 | 设置校正数据 | [MOTOR_CNT, F0_RANGE_END_L, F0_RANGE_END_H, ..., Fn_RANGE_END_L, Fn_RANGE_END_H, F0_RANGE_START_L, F0_RANGE_START_H, ..., Fn_RANGE_START_L, Fn_RANGE_START_H, THUMB_ROOT_POS_CNT, THUMB_ROOT_POS1_L, THUMB_ROOT_POS1_H, ..., THUMB_ROOT_POSn_L, THUMB_ROOT_POSn_H] | |
| HAND_CMD_SET_FINGER_PID | 0x45 | 设置手指PID值,数据类型 float32 | [FINGER_ID, P_BYTE0, P_BYTE1, P_BYTE2, P_BYTE3, I_BYTE0, I_BYTE1, I_BYTE2, I_BYTE3, D_BYTE0, D_BYTE1, D_BYTE2, D_BYTE3, G_BYTE0, G_BYTE1, G_BYTE2, G_BYTE3] | |
| HAND_CMD_SET_FINGER_CURRENT_LIMIT | 0x46 | 设置手指电流限制,[0, 65535] | [FINGER_ID, CURRENT_LIMIT_L, CURRENT_LIMIT_H] | |
| HAND_CMD_SET_FINGER_FORCE_TARGET | 0x47 | 设置手指目标力量,[0, 65535],单位mN, 置零退出力控模式, 开机时恢复为默认值0 | [FINGER_ID, FORCE_TARGET_L, FORCE_TARGET_H] | |
| HAND_CMD_SET_FINGER_POS_LIMIT | 0x48 | 设置手指绝对位置限制,[0, 65535] | [FINGER_ID, POS_LIMIT_L, POS_LIMIT_H] | |
| HAND_CMD_FINGER_START | 0x49 | 开始移动手指 | ||
| HAND_CMD_FINGER_STOP | 0x4A | 停止移动手指 | ||
| HAND_CMD_SET_FINGER_POS_ABS | 0x4B | 移动手指到绝对位置,[0, 65535] | [FINGER_ID, ABSOLUTE_POS_L, ABSOLUTE_POS_H, SPEED] | |
| HAND_CMD_SET_FINGER_POS | 0x4C | 移动手指到逻辑位置,[0, 65535] | [FINGER_ID, LOGICAL_POS_L, LOGICAL_POS_H, SPEED] | |
| HAND_CMD_SET_FINGER_ANGLE | 0x4D | 设置手指角度,[0, 65535],等于实际值 * 100 | [FINGER_ID, TARGET_ANGLE_L, TARGET_ANGLE_H, SPEED] | |
| HAND_CMD_SET_THUMB_ROOT_POS | 0x4E | 旋转大拇指到预设位置,{0,1,2} | [PRESET_POS] | |
| HAND_CMD_SET_FINGER_POS_ABS_ALL | 0x4F | 设置所有手指的绝对位置 | [F0_ABS_POS_L, F0_ABS_POS_H, F0_SPEED, ..., Fn_ABS_POS_L, Fn_ABS_POS_H, Fn_SPEED] | |
| HAND_CMD_SET_FINGER_POS_ALL | 0x50 | 设置所有手指的逻辑位置 | [F0_POS_L, F0_POS_H, F0_SPEED, ..., Fn_POS_L, Fn_POS_H, Fn_SPEED] | |
| HAND_CMD_SET_FINGER_ANGLE_ALL | 0x51 | 设置所有手指第一关节角度,[0, 65535],等于实际值 * 100 | [F0_ANGLE_L, F0_ANGLE_H, F0_SPEED, ..., Fn_ANGLE_L, Fn_ANGLE_H, Fn_SPEED] | |
| HAND_CMD_SET_FINGER_STOP_PARAMS | 0x52 | 设置手指停机参数:速度(逻辑位置/s)、电流(mA)、持续时间(ms)、重试时间(ms) | [FINGER_ID, SPEED_L, SPEED_H, STOP_CURRENT_L, STOP_CURRENT_H, STOP_AFTER_PERIOD_L, STOP_AFTER_PERIOD_H, RETRY_INTERVAL_L, RETRY_INTERVAL_H] | |
| HAND_CMD_SET_FINGER_FORCE_PID | 0x53 | 设置手指力量PID值,数据类型 float32 | [FINGER_ID, P_BYTE0, P_BYTE1, P_BYTE2, P_BYTE3, I_BYTE0, I_BYTE1, I_BYTE2, I_BYTE3, D_BYTE0, D_BYTE1, D_BYTE2, D_BYTE3, G_BYTE0, G_BYTE1, G_BYTE2, G_BYTE3] | |
| HAND_CMD_RESET_FORCE | 0x54 | 重置力量值 | ||
| HAND_CMD_SET_CUSTOM | 0x5F | 自定义指令 | [MOTOR_CNT, DATA_FLAG, ...] | [...] |
| HAND_CMD_SET_SELF_TEST_LEVEL | 0x60 | 设置自检等级,0:等待指令,1:半自检,2:完整自检 | [SELF_TEST_LEVEL] | |
| HAND_CMD_SET_BEEP_SWITCH | 0x61 | 设置蜂鸣器状态,0:关,1:开 | [ON_OFF] | |
| HAND_CMD_BEEP | 0x62 | 蜂鸣一段时间,单位ms,[0, 65535] | [BEEP_PERIOD_L, BEEP_PERIOD_H] | |
| HAND_CMD_SET_BUTTON_PRESSED_CNT | 0x63 | 设置按钮按下次数,仅限校正 | [BTN_PRESSED_CNT] | |
| HAND_CMD_START_INIT | 0x64 | 开始初始化为了使 SELF_TEST_LEVEL=0 | ||
| HAND_CMD_SET_MANUFACTURE_DATA | 0x65 | 设置厂方数据 | ... |
注:
- 如果不加说明,单字节数据为 uint8 类型,XXX_L, XXX_H 表示 uint16 类型的低字节和高字节;XXX_BYTE0, XXX_BYTE1, XXX_BYTE2, XXX_BYTE3 表示 uint32 类型自低到高 4 个字节;
- 若指定为 float32 类型,XXX_BYTE0, XXX_BYTE1, XXX_BYTE2, XXX_BYTE3 表示 float32 类型自低到高 4 个字节。
6. 灵巧手错误代码
| 错误名 | 代码 | 说明 | 分组 |
|---|---|---|---|
| ERR_PROTOCOL_WRONG_CRC | 0x01 | 校验码错误 | 协议 |
| ERR_COMMAND_INVALID | 0x11 | 无效的命令 | 命令 |
| ERR_COMMAND_INVALID_BYTE_COUNT | 0x12 | 字节数不正确 | 命令 |
| ERR_COMMAND_INVALID_DATA | 0x13 | 无效的值 | 命令 |
| ERR_STATUS_INIT | 0x21 | 正在等待初始化命令或者正在初始化 | 状态 |
| ERR_STATUS_CALI | 0x22 | 等待校正 | 状态 |
| ERR_STATUS_STUCK | 0x23 | 电机堵转 | 状态 |
| ERR_OP_FAILED | 0x31 | 操作失败 | 操作 |
| ERR_SAVE_FAILED | 0x32 | 保存失败 | 操作 |
7. 手指角度
角度定义及运动范围说明:
| 角度 | 图例说明 | 角度范围 |
|---|---|---|
| 食指 中指 无名指 小拇指 | ![]() |
100.22°~178.37° 97.81° ~ 176.06° 101.38° ~ 176.54° 98.84° ~ 174.86° |
| 大拇指弯曲 | 2.26° ~ 36.76° | |
| 大拇指旋转 | 0° ~ 90° |
