C610 电调 CAN 通信协议Arduino Mega2560使用指南

未分类
1.1k 词

C610电调CAN通信协议及使用指南

基本信息及资料

  • 通信协议:C610电调采用CAN通信协议
  • 协议参考文档:40. CAN—通讯实验 — [野火]STM32 HAL库开发实战指南——基于H743_Pro_V
  • 硬件适配:Arduino Mega2560无CAN差分信号引脚,需外接MCP2515(实现CAN差分信号与SPI信号转换)
  • 推荐库GitHub - autowp/arduino-mcp2515(Arduino MCP2515 CAN接口库)

报文接收格式

用于向电调发送控制指令控制电调的电流输出,两个标识符(0x200和0x1FF)各自对应 控制4个ID的电调。控制转矩电流值范围-10000-0-10000,对应电调输出的转矩电流 范围-10-0-10A。

即0x200用于控制1-4号电调

数据域 内容 电调ID
DATA[0] 控制电流值高8位 1
DATA[1] 控制电流值低8位 1
DATA[2] 控制电流值高8位 2
DATA[3] 控制电流值低8位 2
DATA[4] 控制电流值高8位 3
DATA[5] 控制电流值低8位 3
DATA[6] 控制电流值高8位 4
DATA[7] 控制电流值低8位 4

0x1FF用于控制5-8号电调

数据域 内容 电调ID
DATA[0] 控制电流值高8位 5
DATA[1] 控制电流值低8位 5
DATA[2] 控制电流值高8位 6
DATA[3] 控制电流值低8位 6
DATA[4] 控制电流值高8位 7
DATA[5] 控制电流值低8位 7
DATA[6] 控制电流值高8位 8
DATA[7] 控制电流值低8位 8

报文反馈格式

数据域定义

数据索引 内容
DATA[0] 转子机械角度高8位
DATA[1] 转子机械角度低8位
DATA[2] 转子转速高8位
DATA[3] 转子转速低8位
DATA[4] 实际输出转矩高8位
DATA[5] 实际输出转矩低8位
DATA[6] Null
DATA[7] Null

接收数据时的CANID若为0x201则为ID为1的电调的数据,以此类推。
若是ID为0x1FF+ID则为ID为5-8的电调的数据。

关键参数

  • 发送频率:默认1KHz(可通过RoboMaster Assistant软件修改)
  • 转子机械角度范围:08191(对应物理角度0360°)
  • 转子转速单位:rpm(转/分钟)

高8位与低8位的理解

C610电调中16位数据会拆分为高8位和低8位传输,具体说明如下:

  1. 数据拆分逻辑
    16位原始数据(如二进制0011 0000 1100 0100)拆分为:

    • 高8位:0011 0000(通过16位数据右移8位获取:原始数据 >> 8
    • 低8位:1100 0100(直接截取原始数据的低8位)
  2. 赋值方式
    高8位赋值给DATA[n],低8位赋值给DATA[n+1](如角度数据中,DATA[0]存高8位,DATA[1]存低8位)

CAN数据包解析方法

解析接收的CAN数据是拆分过程的逆操作,步骤如下:

  1. 将高8位数据(如DATA[0])转换为16位变量(自动补高位0,例:0011 00000000 0000 0011 0000);
  2. 将高8位数据左移8位(例:0000 0000 0011 0000 << 80011 0000 0000 0000);
  3. 与低8位数据(如DATA[1])相加,还原16位原始数据(例:0011 0000 0000 0000 + 1100 01000011 0000 1100 0100);
  4. 转换为十进制输出即得目标数据。

示例程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
struct can_frame canMsg1;
MCP2515 mcp2515(10); // 初始化MCP2515,CS引脚为10

int16_t current = 1000; // 设定电流值
int16_t result_angle = 0; // 解析后的角度值
int16_t result_torque = 0; // 解析后的转矩值
int16_t result_speed = 0; // 解析后的转速值

void setup() {
Serial.begin(115200); // 初始化串口通信

// 初始化MCP2515
mcp2515.reset();
mcp2515.setBitrate(CAN_1000KBPS, MCP_8MHZ); // 波特率1000KBPS,时钟8MHz
mcp2515.setNormalMode();

// 配置发送报文
canMsg1.can_id = 0x200; // 报文ID
canMsg1.can_dlc = 8; // 数据长度8字节
// 填充数据(高8位与低8位拆分)
canMsg1.data[0] = (current >> 8);
canMsg1.data[1] = current;
canMsg1.data[2] = (current >> 8);
canMsg1.data[3] = current;
canMsg1.data[4] = (current >> 8);
canMsg1.data[5] = current;
canMsg1.data[6] = (current >> 8);
canMsg1.data[7] = current;
}

void loop() {
// 发送报文
mcp2515.sendMessage(&canMsg1);

// 接收并解析报文
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
Serial.print(canMsg.can_id, HEX); // 输出CAN ID(十六进制)
Serial.print(" ");
Serial.print(canMsg.can_dlc, HEX); // 输出数据长度(十六进制)
Serial.print(" ");

// 解析转子转速(高8位左移8位+低8位)
Serial.print("转子转速:");
result_speed = ((uint16_t)canMsg.data[2] << 8) + canMsg.data[3];
Serial.print(result_speed / 36, DEC); // 输出转速(十进制)
Serial.print("; ");
}
}