跳转至

电机(Motor)设备组件

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

适用电机种类

该组件当前适用的电机有:GM6020,M3508,M2006,M8910,宇树 A1,宇树 GO-M8010,DM-J4310-2EC,DM-J8006,MF9025v2,MG6012E-i36,MG8016E-i6,各个电机使用注意事项详见对应电机的头文件,电机手册详见附录部分。

使用前准备

使用前需要做以下准备:

  • config.cmake 文件中设置 use_hwcomponents_devices_motor 选项为 ON,若为 OFF 则根驱动配置需求在 CMakeLists.txt 文件中重配置为 ON
  • 外设驱动配置请查看 通用通信驱动 中 CAN 或 FDCAN 部分的配置。

1. 设计说明

由于队内使用的电机均通过 CAN 进行命令的发送与反馈数据的接收(使用 RS485 的电机通过外接自制 CAN 与 RS485 的转换板进行通信)。同时,不同的电机在使用时绝大部分的功能是相同的,同时机器人上常常有不同种类混用的情况,因此根据电机的共有特点,抽象出一个电机基类,其包含基本的电机操作,通过指向具体电机实例的基类指针进行电机操作将带来极大的便利性,同时,当有更换电机种类时,也可实现极少代码的修改实现迁移。作为基类应具有以下基本功能:

  1. 可选择电机的输入方式。常见的方式有原始报文输入、力矩输入、电流输入、指令输入,并在子类中根据实际电机支持的输入方式进行限制。
  2. 电机输出端换算。实际电机的使用中,我们往往更加关注输出端的情况,不管是角度、角速度以及力矩,而电机的反馈数据往往又是转子端的数据,因此组件中应能自行根据减速比进行转子端到输出端的换算(包括角度的计圈)并支持减速比的更换。同时,也应能根据实际需要配置输出端的转动正方向以及角度范围(如 [-π, π) 或是 (-∞, +∞))。
  3. 对于需要使用输出端角度位置信息的情况,对于输出端编码的电机来说,应具有配置角度零点位置的功能。而对于转子端编码的电机来说,应具有将输出端当前角度设置为某一角度值的功能(转子端编码的电机往往需要使用向机械限位转动并堵转一段时间以实现位置确定)。
  4. 应具有将设置的输入编码为报文及将电机反馈报文解码为电机状态的功能。
  5. 需要根据电机本身的性能对设置的输入进行限幅,同时当使用者有更加严格的限制时也应能按要求进行限制。
  6. 提供离线检测功能,以便于使用者在电机离线时采取处理。
  7. 提供电机状态访问接口,最基本的包括:输出端角度,输出端速度,输出端力矩,转子端电流,不同的电机会有进一步的接口,如温度等。
  8. 对于输出端编码的电机,其反馈角速度往往具有较大的噪声,为此可提供微分跟踪器的接口,用于根据输出端角度计算得到输出端的角速度。

2. 使用示例

在项目中引用头文件:

C++
1
2
3
#include "motor.hpp"

namespace hw_motor = hello_world::motor;

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

C++
hw_motor::OptionalParams optional_params = {
  .input_type = hw_motor::InputType::kTorq,                // 力矩输入
  .angle_range = hw_motor::AngleRange::kNegPiToPosPi,      // 角度范围 [-π, π)
  .dir = hw_motor::kDirRev,                                // 电机正方向与规定正方向相反
  .remove_build_in_reducer = true,                         // 移除自带减速器
  .angle_offset = PI,                                      // 电机输出端实际角度与规定角度的差为 π
  .ex_redu_rat = 1,                                        // 电机额外加的减速器减速比为 1
  .max_raw_input_lim = std::numeric_limits<float>::max(),  // 不对报文进行限制
  .max_torq_input_lim = 3.0f,                              // 限制输出端最大输出力矩为 3N·m
  .max_curr_input_lim = 10.0f,                             // 限制电机最大电流为 10A
};

实例化一个电机组件并放入对应电机参数进行初始化,建议再初始化后及时将其添加到 CAN 或 FDCAN 的发送与接收管理器中,如:

C++
hw_motor::Motor* motor_ptr = nullptr;
hw_motor::M2006 motor();

void MotorInit(void)
{
  /* 事先完成管理器的初始化 */

  motor_ptr = new hw_motor::M3508(1, optional_params);
  motor.init(
      1, hw_motor::OptionalParams{
              .angle_range = hw_motor::AngleRange::kNegPiToPosPi,
              .max_torq_input_lim = 2.0f,
          });
  can_rx_mgr_ptr->addReceiver(motor_ptr);
  can_rx_mgr_ptr->addReceiver(&motor);
  can_tx_mgr_ptr->addTransmitter(motor_ptr);
  can_tx_mgr_ptr->addTransmitter(&motor);

  /* 事后调用接收管理器的开启接收 */
}

接收与发送管理器的其他配置按要求进行,详见 通用通信驱动 中 CAN 或 FDCAN 部分的使用方法。

当需要不同种电机一起初始化时,可以调用 CreateMotor 函数进行生成,如:

C++
hw_motor::Motor* motor_ptr_ls[4] = {nullptr};
hw_motor::MotorType motor_type_ls[4] = {
    hw_motor::MotorType::kA1,
    hw_motor::MotorType::kDM_J4310,
    hw_motor::MotorType::kDM_J4310,
    hw_motor::MotorType::kM3508,
};
hw_motor::OptionalParams optional_params_ls[4] = {
    {
        .input_type = hw_motor::InputType::kTorq,
        .dir = hw_motor::kDirFwd,
    },
    {
        .input_type = hw_motor::InputType::kTorq,
        .dir = hw_motor::kDirRev,
    },
    {
        .input_type = hw_motor::InputType::kTorq,
        .dir = hw_motor::kDirFwd,
    },
    {
        .input_type = hw_motor::InputType::kTorq,
        .dir = hw_motor::kDirRev,
    },
};

void MotorInit(void)
{
  /* 事先完成管理器的初始化 */

  for (uint8_t i = 0; i < 4; i++) {
    motor_ptr_ls[i] = hw_motor::CreateMotor(
        motor_type_ls[i], i, optional_params_ls[i]);
    can_rx_mgr_ptr->addReceiver(motor_ptr_ls[i]);
    can_tx_mgr_ptr->addTransmitter(motor_ptr_ls[i]);
  }
}

设定电机的输入(共四种输入方式:期望电流、期望输出力矩、报文原始输入、命令输入,不同的电机有不同的输入方式限制,详见各个电机组件的头文件),如:

C++
float input = 0.1f; // 输出端输出 0.1N·m 的力矩
motor_ptr->setInput(input);
  • 输入的类型由初始化时 OptionalParams 结构体中的 input_type 决定,可通过类方法 get_input_typeset_input_type 进行读取与重设定

电机的发送与接收详见 通用通信驱动 中 CAN 或 FDCAN 部分的使用示例。

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

C++
1
2
3
4
5
motor_ptr->angle();                                // 获取输出端角度
motor_ptr->vel();                                  // 获取输出端转速
motor_ptr->torq();                                 // 获取输出端的输出力矩
motor_ptr->curr();                                 // 获取电机的输入电流
static_cast<hw_motor::M3508*>(motor_ptr)->temp();  // 获取电机温度(个别电机具有)

3. 调试技巧

  1. 电机实例中具有大量电机状态的数据成员,比如角度 angle_,角速度 vel_ 等,实际调试时可在 Ozone 中直接查看,用于判断数据是否正确。
  2. 电机实例中具有解码成功次数 decode_success_cnt_ 和解码失败次数 decode_fail_cnt_ 数据成员,当二者之和随时间增长变大时说明成功收到了电机的反馈。
  3. 电机实例中具有编码成功次数 encode_success_cnt_、编码失败次数 encode_fail_cnt_ 和发送成功次数 transmit_success_cnt_,当 encode_success_cnt_encode_fail_cnt_ 二者之和随时间增长变大时说明电机被调用了 encode 方法,当 encode_success_cnt_transmit_success_cnt_ 差值保持不变时,说明编码成功的报文被及时发出,当 encode_success_cnt_ 随时间增长变大,但 encode_fail_cnt_transmit_success_cnt_ 均保持不变时,说明通报文中有编码失败的发送端。

附录

GM6020

GM6020 电机手册

M3508

M3508 电机手册

C620 电调手册

M2006

M2006 电机手册

C620 电调手册

M8910

M8910 电机通信协议手册

宇树 A1

A1 电机数据手册

A1 电机使用手册

宇树 GO-M8010

GO-M8010 电机数据手册

GO-M8010 电机使用手册

DM-J4310-2EC、DM-J8006

达妙论坛

MF9025v2、MG6012E-i36、MG8016E-i6

领控电机附件

版本说明

版本号 发布日期 说明 贡献者
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.修改电机参数描述
蔡坤镇
2023.12.11 发布电机控制组件(Cpp) 蔡坤镇
2023.12.14 新增简单工厂函数 蔡坤镇
2024.07.26 发布最新说明文档 蔡坤镇