mirror of
https://gitee.com/dlmu-cone/bf_original_balance_chassis
synced 2026-07-24 11:37:45 +08:00
finish all bsp utilities
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#include "dji_motor.h"
|
||||
|
||||
#define PI2 3.141592f
|
||||
#define ECD_ANGLE_COEF 3.835e-4 // ecd/8192*pi
|
||||
|
||||
static uint8_t idx = 0; // register idx,是该文件的全局电机索引,在注册时使用
|
||||
|
||||
/* DJI电机的实例,此处仅保存指针,内存的分配将通过电机实例初始化时通过malloc()进行 */
|
||||
@@ -33,7 +36,7 @@ static uint8_t sender_enable_flag[6] = {0};
|
||||
* @brief 当注册的电机id冲突时,会进入这个函数并提示冲突的ID
|
||||
* @todo 通过segger jlink 发送日志
|
||||
*/
|
||||
static void IDcrash_Handler()
|
||||
static void IDcrash_Handler(uint8_t conflict_motor_idx, uint8_t temp_motor_idx)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
@@ -67,7 +70,7 @@ static void MotorSenderGrouping(can_instance_config *config)
|
||||
}
|
||||
|
||||
// 计算接收id并设置分组发送id
|
||||
config->rx_id = 0x200 + motor_id+1;
|
||||
config->rx_id = 0x200 + motor_id + 1;
|
||||
sender_enable_flag[motor_grouping] = 1;
|
||||
dji_motor_info[idx]->message_num = motor_send_num;
|
||||
dji_motor_info[idx]->sender_group = motor_grouping;
|
||||
@@ -76,7 +79,7 @@ static void MotorSenderGrouping(can_instance_config *config)
|
||||
for (size_t i = 0; i < idx; i++)
|
||||
{
|
||||
if (dji_motor_info[i]->motor_can_instance.can_handle == config->can_handle && dji_motor_info[i]->motor_can_instance.rx_id == config->rx_id)
|
||||
IDcrash_Handler();
|
||||
IDcrash_Handler(i, idx);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -100,7 +103,7 @@ static void MotorSenderGrouping(can_instance_config *config)
|
||||
for (size_t i = 0; i < idx; i++)
|
||||
{
|
||||
if (dji_motor_info[i]->motor_can_instance.can_handle == config->can_handle && dji_motor_info[i]->motor_can_instance.rx_id == config->rx_id)
|
||||
IDcrash_Handler();
|
||||
IDcrash_Handler(i, idx);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -110,22 +113,33 @@ static void MotorSenderGrouping(can_instance_config *config)
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo 是否可以简化多圈角度的计算?
|
||||
* @brief 根据返回的can_instance对反馈报文进行解析
|
||||
*
|
||||
* @param _instance 收到数据的instance,通过遍历与所有电机进行对比以选择正确的实例
|
||||
*/
|
||||
static void DecodeDJIMotor(can_instance *_instance)
|
||||
{
|
||||
uint8_t *rxbuff = _instance->rx_buff;
|
||||
static uint8_t *rxbuff;
|
||||
static dji_motor_measure *measure;
|
||||
for (size_t i = 0; i < DJI_MOTOR_CNT; i++)
|
||||
{
|
||||
if (&dji_motor_info[i]->motor_can_instance == _instance)
|
||||
{
|
||||
dji_motor_info[i]->motor_measure.last_ecd = dji_motor_info[i]->motor_measure.ecd;
|
||||
dji_motor_info[i]->motor_measure.ecd = (uint16_t)(rxbuff[0] << 8 | rxbuff[1]);
|
||||
dji_motor_info[i]->motor_measure.speed_rpm = (uint16_t)(rxbuff[2] << 8 | rxbuff[3]);
|
||||
dji_motor_info[i]->motor_measure.given_current = (uint16_t)(rxbuff[4] << 8 | rxbuff[5]);
|
||||
dji_motor_info[i]->motor_measure.temperate = rxbuff[6];
|
||||
rxbuff = _instance->rx_buff;
|
||||
measure = &dji_motor_info[i]->motor_measure;
|
||||
// resolve data and apply filter to current and speed
|
||||
measure->last_ecd = measure->ecd;
|
||||
measure->ecd = (uint16_t)(rxbuff[0] << 8 | rxbuff[1]);
|
||||
measure->speed_rpm = (1 - SPEED_SMOOTH_COEF) * measure->speed_rpm + SPEED_SMOOTH_COEF * (int16_t)(rxbuff[2] << 8 | rxbuff[3]);
|
||||
measure->given_current = (1 - CURRENT_SMOOTH_COEF) * measure->given_current + CURRENT_SMOOTH_COEF * (uint16_t)(rxbuff[4] << 8 | rxbuff[5]);
|
||||
measure->temperate = rxbuff[6];
|
||||
// multi round calc
|
||||
if (measure->ecd - measure->last_ecd > 4096)
|
||||
measure->total_round--;
|
||||
else if (measure->ecd - measure->last_ecd < -4096)
|
||||
measure->total_round++;
|
||||
measure->total_angle = measure->total_round * PI2 + measure->ecd * ECD_ANGLE_COEF; // @todo simplify the calculation
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -138,6 +152,7 @@ dji_motor_instance *DJIMotorInit(can_instance_config can_config,
|
||||
Motor_Type_e type)
|
||||
{
|
||||
dji_motor_info[idx] = (dji_motor_instance *)malloc(sizeof(dji_motor_instance));
|
||||
memset(dji_motor_info[idx], 0, sizeof(dji_motor_instance));
|
||||
|
||||
// motor basic setting
|
||||
dji_motor_info[idx]->motor_type = type;
|
||||
@@ -159,15 +174,15 @@ dji_motor_instance *DJIMotorInit(can_instance_config can_config,
|
||||
}
|
||||
|
||||
// 改变反馈来源
|
||||
void DJIMotorChangeFeed(dji_motor_instance *motor,Closeloop_Type_e loop,Feedback_Source_e type)
|
||||
void DJIMotorChangeFeed(dji_motor_instance *motor, Closeloop_Type_e loop, Feedback_Source_e type)
|
||||
{
|
||||
if(loop==ANGLE_LOOP)
|
||||
if (loop == ANGLE_LOOP)
|
||||
{
|
||||
motor->motor_settings.angle_feedback_source=type;
|
||||
motor->motor_settings.angle_feedback_source = type;
|
||||
}
|
||||
if(loop==SPEED_LOOP)
|
||||
if (loop == SPEED_LOOP)
|
||||
{
|
||||
motor->motor_settings.speed_feedback_source=type;
|
||||
motor->motor_settings.speed_feedback_source = type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,14 +191,13 @@ void DJIMotorSetRef(dji_motor_instance *motor, float ref)
|
||||
{
|
||||
motor->motor_controller.pid_ref = ref;
|
||||
}
|
||||
|
||||
|
||||
// 计算三环PID,发送控制报文
|
||||
void DJIMotorControl()
|
||||
{
|
||||
{
|
||||
// 预先通过静态变量定义避免反复释放分配栈空间,直接保存一次指针引用从而减小访存的开销
|
||||
static uint8_t group, num;
|
||||
static int16_t set;
|
||||
static dji_motor_instance* motor;
|
||||
static dji_motor_instance *motor;
|
||||
static Motor_Control_Setting_s *motor_setting;
|
||||
static Motor_Controller_s *motor_controller;
|
||||
static dji_motor_measure *motor_measure;
|
||||
@@ -193,33 +207,33 @@ void DJIMotorControl()
|
||||
{
|
||||
if (dji_motor_info[i])
|
||||
{
|
||||
motor=dji_motor_info[i];
|
||||
motor_setting=&motor->motor_settings;
|
||||
motor_controller=&motor->motor_controller;
|
||||
motor_measure=&motor->motor_measure;
|
||||
|
||||
motor = dji_motor_info[i];
|
||||
motor_setting = &motor->motor_settings;
|
||||
motor_controller = &motor->motor_controller;
|
||||
motor_measure = &motor->motor_measure;
|
||||
|
||||
if (motor_setting->close_loop_type & ANGLE_LOOP) // 计算位置环
|
||||
{
|
||||
if (motor_setting->angle_feedback_source == OTHER_FEED)
|
||||
pid_measure=*motor_controller->other_angle_feedback_ptr;
|
||||
pid_measure = *motor_controller->other_angle_feedback_ptr;
|
||||
else // MOTOR_FEED
|
||||
pid_measure=motor_measure->total_angle;
|
||||
pid_measure = motor_measure->total_angle;
|
||||
// 更新pid_ref进入下一个环
|
||||
motor_controller->pid_ref=PID_Calculate(&motor_controller->angle_PID,pid_measure,motor_controller->pid_ref);
|
||||
motor_controller->pid_ref = PID_Calculate(&motor_controller->angle_PID, pid_measure, motor_controller->pid_ref);
|
||||
}
|
||||
|
||||
if (motor_setting->close_loop_type & SPEED_LOOP) // 计算速度环
|
||||
{
|
||||
if (motor_setting->speed_feedback_source == OTHER_FEED)
|
||||
pid_measure=*motor_controller->other_speed_feedback_ptr;
|
||||
pid_measure = *motor_controller->other_speed_feedback_ptr;
|
||||
else
|
||||
pid_measure=motor_measure->speed_rpm;
|
||||
motor_controller->pid_ref=PID_Calculate(&motor_controller->speed_PID,pid_measure,motor_controller->pid_ref);
|
||||
pid_measure = motor_measure->speed_rpm;
|
||||
motor_controller->pid_ref = PID_Calculate(&motor_controller->speed_PID, pid_measure, motor_controller->pid_ref);
|
||||
}
|
||||
|
||||
if (motor_setting->close_loop_type & CURRENT_LOOP) //计算电流环
|
||||
{
|
||||
motor_controller->pid_ref=PID_Calculate(&motor_controller->current_PID,motor_measure->given_current,motor_controller->pid_ref);
|
||||
motor_controller->pid_ref = PID_Calculate(&motor_controller->current_PID, motor_measure->given_current, motor_controller->pid_ref);
|
||||
}
|
||||
|
||||
set = (int16_t)motor_controller->pid_ref;
|
||||
@@ -230,7 +244,7 @@ void DJIMotorControl()
|
||||
group = motor->sender_group;
|
||||
num = motor->message_num;
|
||||
sender_assignment[group].tx_buff[num] = 0xff & set >> 8;
|
||||
sender_assignment[group].tx_buff[num+1] = 0xff & set;
|
||||
sender_assignment[group].tx_buff[num + 1] = 0xff & set;
|
||||
}
|
||||
else // 遇到空指针说明所有遍历结束,退出循环
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
/**
|
||||
* @file dji_motor.h
|
||||
* @author neozng
|
||||
* @brief DJI智能电机头文件
|
||||
* @version 0.1
|
||||
* @date 2022-11-01
|
||||
*
|
||||
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DJI_MOTOR_H
|
||||
#define DJI_MOTOR_H
|
||||
|
||||
#define DJI_MOTOR_CNT 12
|
||||
#define SPEED_SMOOTH_COEF 0.85f // better to be greater than 0.8
|
||||
#define CURRENT_SMOOTH_COEF 0.98f // this coef must be greater than 0.95
|
||||
|
||||
#include "bsp_can.h"
|
||||
#include "controller.h"
|
||||
@@ -45,7 +58,6 @@ typedef struct
|
||||
|
||||
} dji_motor_instance;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 调用此函数注册一个DJI智能电机,需要传递较多的初始化参数,请在application初始化的时候调用此函数
|
||||
* 推荐传参时像标准库一样构造initStructure然后传入此函数.
|
||||
@@ -55,20 +67,20 @@ typedef struct
|
||||
* ....};
|
||||
* 请注意不要在一条总线上挂载过多的电机(超过6个),若一定要这么做,请降低每个电机的反馈频率(设为500Hz),
|
||||
* 并减小DJIMotorControl()任务的运行频率.
|
||||
*
|
||||
*
|
||||
* @attention M3508和M2006的反馈报文都是0x200+id,而GM6020的反馈是0x204+id,请注意前两者和后者的id不要冲突.
|
||||
* 如果产生冲突,在初始化电机的时候会进入IDcrash_Handler(),可以通过debug来判断是否出现冲突.
|
||||
*
|
||||
*
|
||||
* @param config 电机can设置,对于DJI电机仅需要将tx_id设置为电调闪动次数(c620,615,610)或拨码开关的值(GM6020)
|
||||
* 你不需要自己查表计算发送和接收id,我们会帮你处理好!
|
||||
*
|
||||
*
|
||||
* @param motor_setting 电机的控制设置,包括是否反转,闭环类型和是否使用编码器之外的反馈值
|
||||
*
|
||||
*
|
||||
* @param controller_init 电机控制器的参数设置,包括其他的反馈来源数据指针和三环PID的参数.
|
||||
* 如果不需要其他数据来源或不需要三个环,将不需要指针置为NULL即可
|
||||
*
|
||||
*
|
||||
* @param type 电机的类型枚举,包括m2006,m3508和gm6020
|
||||
*
|
||||
*
|
||||
* @return dji_motor_instance* 返回一个电机实例指针给应用,方便其对电机的参考值进行设置,即调用DJIMotorSetRef()
|
||||
*/
|
||||
dji_motor_instance *DJIMotorInit(can_instance_config config,
|
||||
@@ -76,32 +88,28 @@ dji_motor_instance *DJIMotorInit(can_instance_config config,
|
||||
Motor_Controller_Init_s controller_init,
|
||||
Motor_Type_e type);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 被application层的应用调用,给电机设定参考值.
|
||||
* 对于应用,可以将电机视为传递函数为1的设备,不需要关心底层的闭环
|
||||
*
|
||||
*
|
||||
* @param motor 要设置的电机
|
||||
* @param ref 设定参考值
|
||||
*/
|
||||
void DJIMotorSetRef(dji_motor_instance *motor, float ref);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 切换反馈的目标来源,如将角速度和角度的来源换为IMU(小陀螺模式常用)
|
||||
*
|
||||
*
|
||||
* @param motor 要切换反馈数据来源的电机
|
||||
* @param loop 要切换反馈数据来源的控制闭环
|
||||
* @param type 目标反馈模式
|
||||
*/
|
||||
void DJIMotorChangeFeed(dji_motor_instance *motor,Closeloop_Type_e loop,Feedback_Source_e type);
|
||||
|
||||
void DJIMotorChangeFeed(dji_motor_instance *motor, Closeloop_Type_e loop, Feedback_Source_e type);
|
||||
|
||||
/**
|
||||
* @brief 该函数被motor_task调用运行在rtos上,motor_stask内通过osDelay()确定控制频率
|
||||
* @todo 增加前馈功能
|
||||
* @todo 增加前馈功能
|
||||
*/
|
||||
void DJIMotorControl();
|
||||
|
||||
|
||||
#endif // !DJI_MOTOR_H
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
/**
|
||||
* @file motor_def.h
|
||||
* @author neozng
|
||||
* @brief 电机通用的数据结构定义
|
||||
* @version beta
|
||||
* @date 2022-11-01
|
||||
*
|
||||
* @copyright Copyright (c) 2022 HNU YueLu EC all rights reserved
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MOTOR_DEF_H
|
||||
#define MOTOR_DEF_H
|
||||
|
||||
/**
|
||||
* @brief 闭环类型,如果需要多个闭环,则使用或运算
|
||||
* 例如需要速度环和电流环: CURRENT_LOOP|SPEED_LOOP
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CURRENT_LOOP = 0b0001,
|
||||
@@ -13,18 +28,21 @@ typedef enum
|
||||
___ = 0b0111
|
||||
} Closeloop_Type_e;
|
||||
|
||||
/* 反馈来源设定,若设为OTHER_FEED则需要指定数据来源指针,详见Motor_Controller_s*/
|
||||
typedef enum
|
||||
{
|
||||
MOTOR_FEED = 0,
|
||||
OTHER_FEED = 1
|
||||
} Feedback_Source_e;
|
||||
|
||||
/* 电机正反转标志 */
|
||||
typedef enum
|
||||
{
|
||||
MOTOR_DIRECTION_NORMAL = 0,
|
||||
MOTOR_DIRECTION_REVERSE = 1
|
||||
} Reverse_Flag_e;
|
||||
|
||||
/* 电机控制设置,包括闭环类型,反转标志和反馈来源 */
|
||||
typedef struct
|
||||
{
|
||||
Closeloop_Type_e close_loop_type;
|
||||
@@ -34,6 +52,7 @@ typedef struct
|
||||
|
||||
} Motor_Control_Setting_s;
|
||||
|
||||
/* 电机控制器,包括其他来源的反馈数据指针,3环控制器和电机的参考输入*/
|
||||
typedef struct
|
||||
{
|
||||
float *other_angle_feedback_ptr;
|
||||
@@ -43,10 +62,10 @@ typedef struct
|
||||
PID_t speed_PID;
|
||||
PID_t angle_PID;
|
||||
|
||||
// 将会作为每个环的输入和输出
|
||||
float pid_ref;
|
||||
float pid_ref; // 将会作为每个环的输入和输出顺次通过串级闭环
|
||||
} Motor_Controller_s;
|
||||
|
||||
/* 电机类型枚举 */
|
||||
typedef enum
|
||||
{
|
||||
GM6020 = 0,
|
||||
@@ -56,6 +75,11 @@ typedef enum
|
||||
HT04 = 4
|
||||
} Motor_Type_e;
|
||||
|
||||
/**
|
||||
* @brief 电机控制器初始化结构体,包括三环PID的配置以及两个反馈数据来源指针
|
||||
* 如果不需要某个控制环,可以不设置对应的pid config
|
||||
* 需要其他数据来源进行反馈闭环,不仅要设置这里的指针还需要在Motor_Control_Setting_s启用其他数据来源标志
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
float *other_angle_feedback_ptr;
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* @file motor_task.h
|
||||
* @author neozng
|
||||
* @brief 对所有电机,舵机等控制任务的进一步封装,MotorControlTask()将在操作系统中按一定频率调用
|
||||
* @version beta
|
||||
* @date 2022-11-01
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#ifndef MOTOR_TASK_H
|
||||
#define MOTOR_TASK_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user