跳转至

电机(Motor)设备组件

1.1.2版本相比先前版本新增了一部分初始化参数,由先前版本更新为后续版本的程序需修改初始化方式!!!

适用电机种类

该组件当前适用的电机有:GM6020,M3508,M2006,M8910,宇树 A1,DM-J4310-2EC,各个电机使用注意事项详见附录部分

快速开始

组件源码仓库地址:https://github.com/ZJU-HelloWorld/HW-Components

要在项目中使用该组件,需添加仓库内的以下文件:

Text Only
1
2
3
4
5
6
7
devices/dev_motor.c
devices/dev_motor.h
devices/dev_motor_params.c
devices/dev_motor_params.h
devices/dev_config.h
system.h
tool.h

外设驱动配置

在使用 CAN 进行电机报文收发时,使用 CubeMX 配置时将所用 CAN 的波特率调整至 1Mbps,以方便通信。例如对于 RoboMaster 开发板 C 型板载的 CAN,驱动流程如下:

  • 对于 CAN1,预分频值(Prescaler)设置为 3,位段 1 时间片段(Time Quanta in Bit Segment 1)设置为 6,位段 2 时间片段(Time Quanta in Bit Segment 2)设置为 7,以达到 1Mbps 的波特率;
  • 开启 CAN1 的接受中断,如开启接收中断 0(RX0 interrupt)

使用前准备

使用前需要做以下准备:

  • 在使用 STM32CubeMX 生成项目时,请在 Code Generator 界面 Enable Full Assert,来帮助断言设备驱动中的错误;在 main.c 中修改 assert_failed 函数以指示断言结果,如添加 while(1);
  • system.hsystem options: user config 处进行系统设置

示例

在项目中引用头文件:

C
#include "dev_config.h"

实例化一个电机参数配置结构并进行相关配置,如:

C
MotorInitParams_t init_params = {
    .dir = FWD,                 // 电机转动正方向与程序定义正方向一致
    .id = 1,                    // 电调id为1
    .range = ANG_NPI_PPI,               // 输出端角度范围[-π, π)
    .redution_rat = 1,                  // 外加减速箱减速比为1(无外加减速箱)
    .type = M3508,                      // M3508电机
    .ang_offset = 0,                    // 实际角度与程序设定的角度相同
    .remove_build_in_reducer = false,   // 不移除自带减速器
    .max_raw_input = DEFAULT_VALUE,     // 使用默认报文输入限制
    .max_torque = 1,                    // 限制电机输出端最大力矩指令为1N·m
    .max_current = 0.2,                 // 限制电机最大电流指令为0.2A
};
  • 注意只有当设置的输入限制小于原有的默认限制时才可产生作用,比如某电机最大输出端输出力矩为1N·m,则设置2N·m的最大输出端力矩指令限制不会产生作用,实际的输出端力矩指令仍会被限制为1N·m

实例化一个电机组件并放入对应电机参数进行初始化,如:

C
Motor_t motor1;
MotorInit(&motor1, &init_params);

设定电机的输入(部分电机还可以设定期望电流、期望输出力矩,三选一),输入当前正在编码的报文的标识符,当标识符与电机接收报文标识符对应时得到编码后的报文,如:

C
/* 1.设置电机输入 */
int16_t input = 100;
motor1.setRawInput(&motor1, input);
// /* 2.设置电机输出力矩 */
// float32_t torque = 1;
// motor1.setTorque(&motor1, torque);
// /* 3.设置电机电流 */
// float32_t current = 1;
// motor1.setCurrent(&motor1, current);

uint8_t data[8] = {0};
motor1.encode(&motor1, data, 0x200); // 编码报文
  • 可通过类方法 getMotorRxId 获取电机接收报文的标识符

对同一报文控制的多个电机则采用对同一报文多次编码的方式,如:

C
1
2
3
4
5
uint8_t data[8] = {0};
motor1.encode(&motor1, data, 0x200);
motor2.encode(&motor2, data, 0x200);
motor3.encode(&motor3, data, 0x200);
motor4.encode(&motor4, data, 0x200);

然后调用 CAN 发送编码后的报文,如:

C
1
2
3
4
5
6
7
8
CAN_TxHeaderTypeDef TxMessageHeader;
uint32_t pTxMailbox;
TxMessageHeader.StdId = 0x200;
// TxMessageHeader.StdId = motor1.getMotorRxId(&motor1);
TxMessageHeader.IDE = CAN_ID_STD;
TxMessageHeader.RTR = CAN_RTR_DATA;
TxMessageHeader.DLC = 8;
HAL_CAN_AddTxMessage(&hcan1, &TxMessageHeader, data, &pTxMailbox)

电机发回法报文在 CAN 接收中断中进行,在当前报文标识符与电机标识符对应时,对接收到的报文进行解包,得到反馈信息,如:

C
CAN_RxHeaderTypeDef RxMessageHeader;
uint8_t rawData[8];

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if (hcan == &hcan1)
    {
        if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxMessageHeader, rawData) == HAL_OK) // 获得接收到的数据头和数据
        {
            // 若与某电机can和接收id对应,则会进行解码
            motor1.decode(&motor1, rawData, RxMessageHeader.StdId);
        }
    }
    HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); // 再次使能FIFO0接收中断
}

接收到电机的反馈信号后,可以调用类方法 getStates 获取电机的状态(包括输入电流,输出端力矩,输出端角度,输出端角速度),如:

C
MotorStates_t states;
motor1.getStates(&motor1, &states);

组件说明

MotorParams_t 结构体

存储电机参数,用户不可操作

名称 类型 示例值 描述
kMaxRawInput int16_t / 电机接收报文最大输入
kCross0Val uint16_t / 电机编码器过零点编码值
kMaxTorque float / 电机转子端最大允许输出力矩,单位 N·m
kMaxCurrent float / 电机最大允许电流,单位 A
kTorqueConst float / 电机转子的转矩常数,单位 N·m/A
kReduRat float / 电机减速比
kAngRat float / 电机编码器的角度分辨率
kOmgRat float / 电机编码器的角速度分辨率
kCurrentRat float / 电机电流的分辨率
  • 该结构体涉及大量电机参数,程序会自行设置,当需要查看电机相关参数时请通过类方法 getMotorParams 获取

MotorInitParams_t 结构体

电机初始化结构

名称 类型 示例值 描述
type MotorType_e M3508 电机种类
dir int8_t FWD 电机转动正方向与程序设定正方向间的关系
id uint8_t 1 电机电调序号
range AngRange_e ANG_NPI_PPI 电机输出端角度范围
redution_rat float 1 电机外接减速器减速比(不含电机自带减速器的减速比)
ang_offset float 0 实际输出端角度与程序设定的角度之差
remove_build_in_reducer bool false 是否去除自带减速器
max_raw_input int16_t 16384 程序中电机接收报文最大输入限制
max_torque float 2 程序中电机输出端最大允许输出力矩限制,单位 N·m
max_current float 2 程序中电机最大允许电流限制,单位 A

MotorStates_t 结构体

电机反馈的状态

名称 类型 示例值 描述
omg float / 电机输出端的角速度,单位 rad/s
ang float / 电机输出端角度,单位 rad
current float / 电机输入的电流,单位 A
torque float / 电机输出端的力矩,单位 N·m
temp uint8_t / 电机的温度,单位 ℃(一直为零则表明没有温度反馈)

Motor_t

电机控制类

属性

名称 类型 示例值 描述
kType Motor_Type M3508 电机的类型
kDir int8_t FWD 电机正方向与程序定义正方向关系,值可为 motor_dir 中的类型
kRxId uint32_t / 电机接收报文的标识符
kTxId uint32_t / 电机发送报文的标识符
kId uint8_t 1 电机的 id
param MotorParams_t / 电机参数
ang_offset float 0 电机输出端角度偏置值,单位 rad
kAngRange AngRange_e ANG_NPI_PPI 电机*输出端*角度范围,单位 rad
is_start bool true 电机是否开启
input.torque float / 电机输出端的期望输出力矩,单位 N·m
input.current float / 向电机施加的期望电流,单位 A
input.input int16_t / 电机的输入
feedback.omg float / 电机输出端的转速,单位 rad/s
feedback.ang float / 电机输出端角度,单位为 rad
feedback.actual_ang float / 电机输出端未修正角度角度,单位 rad
feedback.round float / 电机转子记圈,用于计算输出端角度
feedback.current float / 电机反馈的电流大小,单位 A
feedback.torque float / 电机反馈的力矩大小,单位 N·m
feedback.ang_raw float / 电机转子端编码器反馈值
feedback.ang_raw_last float / 上一时刻电机转子端编码器反馈值
feedback.temp uint8_t / 电机的温度反馈值,单位℃(一直为零则表明没有温度反馈)

方法

名称 参数说明 描述
MotorInit init_params:电机初始化参数 根据参数初始化电机
setAngVal ang:当前电机所处的定义角度,单位 rad 将当前电机所处位置定义为某一角度
setTorque torque:电机输出端期望力矩,单位 N·m 设置电机输出端的期望力矩(限幅),返回实际设定的期望输出力矩,适用于个别电机,不适用的电机调用会报错
setCurrent current:电机的期望输入电流,单位 A 设置电机输入电流(限幅),返回实际设定的期望输入电流,适用于个别电机,不适用的电机调用会报错
setInput raw_input:电机报文中的期望设定值 设置电机控制报文的设定值(限幅),返回实际报文中的设定值,适用于个别电机,不适用的电机调用会报错
encode data:返回需要编码的报文内容;tx_msg_std_id:当前进行编码报文的标识符 当当前进行编码的报文的标识符与电机对应时,会根据电机输入设置进行报文编码,返回是否进行编码
decode data:需要进行解码的报文内容;rx_msg_std_id:当前接收到的报文的标识符 当当前接收到的报文的标识符与电机对应时,会根据电机反馈报文的内容更新电机状态,返回是否进行解码
getStates states:返回当前电机的状态 获取当前电机的状态
getMotorParams params: 返回的电机参数 获取电机的参数
getMotorRxId / 获取电机接收的报文的标识符

附录

电机使用注意事项

  • GM6020
  • 该电机为电压控制,只可使用 setRawInput 方法对电机进行控制
  • 电机 id 1-4为同一条控制报文,电机 id 5-7为同一条控制报文
  • M3508
  • 该电机可使用 setRawInputsetCurrentsetTorque 方法进行控制
  • 电机 id 1-4为同一条控制报文,电机 id 5-8为同一条控制报文
  • M2006
  • 该电机可使用 setRawInputsetCurrentsetTorque 方法进行控制
  • 电机 id 1-4为同一条控制报文,电机 id 5-8为同一条控制报文
  • M8910
  • 该电机可使用 setRawInputsetCurrentsetTorque 方法进行控制
  • 电机 id 1-4为同一条控制报文,电机 id 5-8为同一条控制报文
  • 宇树 A1
  • 该电机可使用 setRawInputsetCurrentsetTorque 方法进行控制
  • 电机 id 1-3为同一条控制报文,电机 id 4-6为同一条控制报文
  • 该电机实际通过 RS485 进行通信,为使用该统一代码进行控制,需结合对应的转换板进行使用
  • DM-J4310-2EC
  • 该电机控制报文中数值无实际物理意义,因此只能使用 setCurrentsetTorque 方法进行控制
  • 电机每个 id 对应一条独立的控制报文
  • 该电机需要使用控制帧开启电机,设定输入后预先发送的为电机开启帧,当电机反馈信息被成功解码后,电机状态会设为开启,后续发送的即为设置的控制报文(为保证电机中途重启后程序仍能正常发送开启帧,建议对一定时间内接受电机的报文数进行统计,当数量少于一定次数时将电机状态修改为未开启,此时程序将发送开启帧直至电机反馈信息被成功解码)
  • 使用该电机前,请先使用达妙调试助手根据文档对电机进行配置,以确保能正常通过该代码进行控制

电机标定说明

转向关系标定

标定电机时先确定电机转动正方向与自定转动正方向是否相同,可通过先在电机配置中选择电机转动正方向与自定转动正方向相同,烧录程序,用手转动电机输出端,在debug中查看数据变化是否与期望的相同,若不同则电机转动正方向与自定转动正方向相反,一次配置转向关系

减速比标定

程序中电机默认的的减速比为电机自带减速器的减速比。 1. 当电机实际使用时在自带减速器外还额外增加减速器时,应当在电机初始化时将初始化结构体中redution_rat属性设置为外加减速器的减速比,同时将remove_build_in_reducer属性设置为false 2. 当电机实际使用时拆除了电机自带的减速器,又外加了减速器时,应当在电机初始化时将初始化结构体中redution_rat属性设置为外加减速器的减速比,同时将remove_build_in_reducer属性设置为true

电机零点标定(转向关系与减速比标定后进行)

  1. 通过机械限位标定 通过机械限位标定可采取在程序一开始使先使对电机进行速度闭环,使其往固定方向转动,当读取到反馈的速度的值小于设定转速一定程度时便可认为到达机械限位,此时可调用setAngVal方法设定当前的角度,值为到达机械限位时应该到达的角度值。采用此方法的往往是没有输出端绝对编码的电机,因此对于这类电机在每次程序重启后都需要进行标定后才可正常使用
  2. 通过绝对位置标定 通过绝对位置标定可采取在电机属性初始化时将ang_offset属性设置为0,然后烧录程序,将电机输出端转动到实际定义的0位后,通过debug读取此时对应的角度值,然后将ang_offset属性设置为读取到的角度值,便可完成标定。

版本说明

版本号 发布日期 说明 贡献者
2023.01.15 发布电机控制组件测试版 蔡坤镇
2023.02.06 完成电机测试,新增达妙电机 蔡坤镇
2023.02.09 新增移除自带减速器配置 蔡坤镇
2023.03.02 1.修复读取的数据为未处理完成的状态
2.修改类型及变量命名
蔡坤镇
2023.03.02 1.优化角度解算方式
2.修复达妙电机解算错误问题
蔡坤镇
2023.03.02 1.修改M3508与M2006扭矩常数 蔡坤镇
2023.03.02 1.修复高速旋转时计圈错误问题 蔡坤镇
2023.04.14 1.修复计圈滞后问题
2. 更正A1减速比
蔡坤镇
2023.05.08 1.新增部分电机温度读取 蔡坤镇
2023.05.14 1.新增程序设定电机输入指令限制
2.修改电机参数描述
蔡坤镇