大疆电机
一、驱动程序解析
1. 数据结构定义
dji_motor_handle_t 包括电机的各种参数,如速度、电流、角度等重要参数。因此使用之前需要定义电机的句柄以接收这些参数。具体包含以下参数,根据需要使用。
/**
* @brief 电机参数
*/
typedef struct {
/* 3508/2006 参数 */
uint8_t hall; /*!< 可能是霍尔传感器值 */
float real_current; /*!< 实际电流 */
int16_t given_current; /*!< 期望电流,M3508 电机才会赋值 */
int32_t total_angle; /*!< 上电以后为 0 点,以此为基准的总角度 */
uint16_t offset_angle; /*!< 上电后角度初始位置 */
bool got_offset; /*!< 上电以后获取一次角度偏移 */
/* GM6020 参数 */
int16_t torque_current; /*!< 实际转矩电流 */
uint8_t temperature; /*!< 温度 */
/* 共用参数 */
dji_can_id_t motor_id; /*!< 电机 ID */
int16_t set_value; /*!< 设置的值,电压或电流值 */
uint16_t last_angle; /*!< 上次角度 */
uint16_t angle; /*!< 角度,绝对角度,一圈为 8192 */
int16_t speed_rpm; /*!< 速度 */
int32_t round_cnt; /*!< 圈数计数 */
float rotor_degree; /*!< 转子角度
对于 3508 与 2006, 是轴的相对位置.
上电后为 0 度,轴转一圈为 360, 0 (360) 度附近不会跳变.
角度会累加,已经除过减速比;
对于 6020, 是绝对位置 (0 ~ 360).
上电后不为 0, 角度不会累加,0 (360) 度附近会跳变. */
dji_motor_model_t motor_model; /*!< 电机型号 */
} dji_motor_handle_t;
建议将 set_value 作为 PID 计算结果接收参数。
2. 函数用法说明
由于大疆的电机的 CAN 报文中没有针对单个电机设置电流,因此不提供单电机控制。可以自行编写。
/* 驱动初始化:配置电机句柄、型号、ID及CAN通道 */
dji_motor_init
/* 反初始化电机 */
dji_motor_deinit
/* M3508/2006 设置电流 */
dji_motor_set_current
/* GM6020 电机电压控制 */
dji_gm6020_set_voltage
/* GM6020 电机电流控制 */
dji_gm6020_set_current
由于大疆的电机的 CAN 报文中没有针对单个电机设置电流,因此不提供单电机控制,可以自行编写。
3. 核心设计思想
主要是提供统一的接口。
减速比处理:
M3508减速比19:1M2006减速比36:1GM6020直驱- 代码内部直接计算了减速比,输出了
rotor_degree(转子实际角度),上层应用层(如PID控制)无需关心电机到底有没有减速箱,直接用角度即可。
多圈角度解算: 电机编码器原始数据是 08192(0360度),代码通过 last_angle 和 angle 的差值判断(>4096 或 <-4096)来检测过零点,维护了一个 round_cnt(圈数),从而计算出连续的 total_angle。这是闭环控制最关键的数据。
二、驱动代码使用
- 将头文件复制到
User/Bsp/Inc/中,源文件复制到User/Bsp/Src中 - 将
dji_bldc_motor.c添加到工程的Bsp分组中 - 在
bsp.h中包含dji_bldc_motor.h - 如果只使用特定型号的电机,可以在
dji_bldc_motor.h中通过DJI_MOTOR_USE_M3508_2006和DJI_MOTOR_USE_GM6020宏来选择是否使用这些型号
/* demo */
/* 这里使用 ARM DSP 库的 pid */
int main(void) {
bsp_init();
/* 声明大疆电机参数句柄 */
dji_motor_handle_t m3508;
/* 定义 pid 结构体 */
arm_pid_instance_f32 speed_pid = {
.Kp = 1.5f,
.Ki = 0.1f,
.Kd = 0.0f,
};
arm_pid_init_f32(&speed_pid, 1);
/* 电机初始化,M3508 电机,ID 为 1, 使用 CAN1 通信 */
dji_motor_init(&m3508, DJI_M3508, CAN_Motor1_ID, can1_selected);
/* 目标速度 */
float target_speed = 200.0f;
while (1) {
/* ARM DSP 库中的 PID 计算函数。输入为差值,即期望值 - 测量值 */
m3508.set_value =
(int16_t)arm_pid_f32(&speed_pid, (target_speed - m3508.speed_rpm));
dji_motor_set_current(can1_selected, DJI_MOTOR_GROUP1,
m3508.set_value, 0, 0, 0);
HAL_Delay(100);
}
}