304 lines
9.6 KiB
C
304 lines
9.6 KiB
C
#ifndef __MF4010V2__H__
|
||
#define __MF4010V2__H__
|
||
|
||
/**
|
||
* @file mf4010v2.h
|
||
* @brief MF4010V2 无刷电机驱动程序
|
||
* @note 改进版本:
|
||
* - 添加错误处理和返回值
|
||
* - 添加 CAN 超时机制
|
||
* - 使用安全的内联函数替代危险宏
|
||
* - 使用 HAL 层解耦硬件依赖
|
||
*
|
||
* 电机 CAN ID: 0x141 (默认)
|
||
* CAN 波特率:1 Mbps
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
#include <stddef.h>
|
||
|
||
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* ============================================================================
|
||
* 状态码和错误定义
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief MF4010V2 状态码
|
||
*/
|
||
typedef enum {
|
||
MF4010_OK = 0, /**< 成功 */
|
||
MF4010_ERR_TIMEOUT = -1, /**< CAN 通信超时 */
|
||
MF4010_ERR_INVALID_ID = -2, /**< 无效的 CAN ID */
|
||
MF4010_ERR_NO_RESPONSE = -3, /**< 无响应 */
|
||
MF4010_ERR_INVALID_PARAM = -4, /**< 无效参数 */
|
||
MF4010_ERR_BUS_OFF = -5, /**< CAN 总线关闭 */
|
||
MF4010_ERR_CRC = -6, /**< CRC 校验错误 */
|
||
MF4010_ERR_HARDWARE = -7, /**< 硬件错误 */
|
||
MF4010_ERR_CAN_SEND = -8, /**< CAN 发送失败 */
|
||
MF4010_ERR_CAN_RECV = -9, /**< CAN 接收失败 */
|
||
MF4010_ERR_BAD_RECV = -10
|
||
} mf4010_status_t;
|
||
|
||
/**
|
||
* @brief 电机状态标志
|
||
*/
|
||
typedef enum {
|
||
MF4010_FLAG_NONE = 0x00, /**< 无标志 */
|
||
MF4010_FLAG_RUNNING = 0x01, /**< 电机运行中 */
|
||
MF4010_FLAG_ENABLED = 0x02, /**< 电机已使能 */
|
||
MF4010_FLAG_FAULT = 0x04, /**< 故障状态 */
|
||
MF4010_FLAG_CONNECTED = 0x08 /**< 已连接 */
|
||
} mf4010_flag_t;
|
||
|
||
/* ============================================================================
|
||
* 电机结构体定义
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief 电机结构体(优化版)
|
||
*/
|
||
|
||
|
||
typedef struct __mf4010v2_t {
|
||
int can_ch; /**< CAN 通道 (0 或 1) */
|
||
uint16_t id; /**< CAN ID (0x000-0x7FF) */
|
||
uint8_t last_response[8]; /**< 最后一次响应数据 */
|
||
uint32_t last_comm_time; /**< 最后通信时间戳 (ms) */
|
||
uint16_t error_count; /**< 通信错误计数 */
|
||
uint16_t success_count; /**< 成功通信计数 */
|
||
uint8_t flags; /**< 状态标志 (@ref mf4010_flag_t) */
|
||
int32_t target_angle; /**< 目标角度 (0.01 度) */
|
||
int32_t current_angle; /**< 当前角度 (0.01 度) - 从编码器读取 */
|
||
} mf4010v2_t;
|
||
|
||
|
||
typedef struct {
|
||
uint8_t angle_kp;
|
||
uint8_t angle_ki;
|
||
uint8_t speed_kp;
|
||
uint8_t speed_ki;
|
||
uint8_t iq_kp;
|
||
uint8_t iq_ki;
|
||
} pid_param;
|
||
|
||
|
||
/* ============================================================================
|
||
* 核心 API 函数
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief 初始化电机结构体
|
||
* @param motor: 电机结构体指针
|
||
* @param id: 电机 CAN ID (范围 0x000-0x7FF,如 0x141)
|
||
* @param can_ch: CAN 通道 (0=CAN1, 1=CAN2)
|
||
* @retval 成功返回 MF4010_OK,失败返回错误码
|
||
*/
|
||
int mf4010v2_init(mf4010v2_t* motor, uint16_t id, int can_ch);
|
||
|
||
/**
|
||
* @brief 发送命令并接收响应(带超时)
|
||
* @param motor: 电机结构体指针
|
||
* @param command: 8 字节命令数据
|
||
* @retval 成功返回 MF4010_OK,失败返回错误码
|
||
*/
|
||
int mf4010v2_send_command(mf4010v2_t* motor, const uint8_t command[8]);
|
||
|
||
|
||
void mf4010v2_run(mf4010v2_t* motor);
|
||
void mf4010v2_stop(mf4010v2_t* motor);
|
||
void mf4010v2_close(mf4010v2_t* motor);
|
||
int mf4010v2_set_speed(mf4010v2_t* motor, int32_t speed_0_01dps);
|
||
int mf4010v2_set_angle(mf4010v2_t* motor, int32_t angle_0_01deg);
|
||
int mf4010v2_read_pid_param(mf4010v2_t* motor, pid_param* pid);
|
||
int mf4010v2_get_motor_state(mf4010v2_t* motor, int8_t* tempture, int16_t* iq, int16_t* speed, int16_t* encoder);
|
||
|
||
/* Non-blocking variants — fire-and-forget, no CAN response polling */
|
||
int mf4010v2_set_speed_nb(mf4010v2_t* motor, int32_t speed_0_01dps);
|
||
int mf4010v2_close_nb(mf4010v2_t* motor);
|
||
|
||
/* ============================================================================
|
||
* 命令宏定义(8 字节 CAN 命令帧)
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief 电机关闭命令
|
||
* @note 命令字:0x80
|
||
*/
|
||
#define COMMAND_MOTOR_CLOSE {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
|
||
/**
|
||
* @brief 电机运行命令
|
||
* @note 命令字:0x88
|
||
*/
|
||
#define COMMAND_MOTOR_RUNNING {0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
|
||
/**
|
||
* @brief 电机停止命令
|
||
* @note 命令字:0x81
|
||
*/
|
||
#define COMMAND_MOTOR_STOP {0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
|
||
/**
|
||
* @brief 读取 PID 参数命令
|
||
* @note 命令字:0x30
|
||
*/
|
||
#define COMMAND_READ_PID_PARAMS {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
||
|
||
/* ============================================================================
|
||
* 安全命令生成函数(使用内联函数避免指针问题)
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief 转矩闭环控制命令
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param iq: 转矩控制量 (-2048 ~ 2048)
|
||
* @note 分辨率:1 LSB = 1 单位
|
||
*/
|
||
void cmd_torque_control(uint8_t* buf, int16_t iq);
|
||
|
||
/**
|
||
* @brief 速度闭环控制命令
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param speed: 速度控制量
|
||
* @note 分辨率:0.01 DPS/LSB
|
||
* 范围:-204800 ~ +204800 (对应 -2048 ~ +2048 DPS)
|
||
* @example
|
||
* uint8_t cmd[8];
|
||
* cmd_speed_control(cmd, 10000); // 100 DPS
|
||
*/
|
||
void cmd_speed_control(uint8_t* buf, int32_t speed);
|
||
|
||
|
||
|
||
/**
|
||
* @brief 多圈位置闭环控制命令
|
||
* @param buf
|
||
* @param angleControl 0.01degree/LSB 36000表示360°
|
||
*/
|
||
|
||
void cmd_mult_ring_pos(uint8_t* buf, int32_t angleControl);
|
||
|
||
/**
|
||
* @brief 多圈位置闭环控制命令带速度限制
|
||
* @param buf
|
||
* @param maxSpeed 表示实际转速1dp/LSB 360表示360 dps
|
||
* @param angleControl 0.01degree/LSB 36000表示360°
|
||
*/
|
||
|
||
void cmd_mult_ring_pos_with_speed(uint8_t* buf, uint16_t maxSpeed, int32_t angleControl);
|
||
|
||
/**
|
||
* @brief 单圈位置闭环控制命令
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param direction: 旋转方向 (0x00=顺时针,0x01=逆时针)
|
||
* @param angle: 目标角度 (单位:0.01°, 如 36000=360°)
|
||
*/
|
||
void cmd_single_ring_pos(uint8_t* buf, uint8_t direction, uint32_t angle);
|
||
/**
|
||
* @brief 单圈位置闭环控制命令(带最大速度)
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param spinDirection: 旋转方向 (0x00=顺时针,0x01=逆时针)
|
||
* @param maxSpeed: 最大速度 (单位:DPS, 如 360=360 DPS)
|
||
* @param angleControl: 目标角度 (单位:0.01°, 如 36000=360°)
|
||
*/
|
||
void cmd_single_ring_pos_with_speed(uint8_t* buf, uint8_t spinDirection,
|
||
uint16_t maxSpeed, uint32_t angleControl);
|
||
|
||
/**
|
||
* @brief 增量位置闭环控制命令
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param angle_increment: 角度增量 (单位:0.01°, 如 36000=360°)
|
||
* @note 正值 = 逆时针,负值 = 顺时针
|
||
*/
|
||
void cmd_incr_pos(uint8_t* buf, int32_t angle_increment);
|
||
|
||
/**
|
||
* @brief 增量位置闭环控制命令(带最大速度)
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param max_speed 1dps/LSB
|
||
* @param angle_increment: 角度增量 (单位:0.01°, 如 36000=360°)
|
||
* @note 正值 = 逆时针,负值 = 顺时针
|
||
*/
|
||
void cmd_incr_pos_with_speed(uint8_t* buf, uint16_t max_speed, int32_t angle_increment);
|
||
|
||
|
||
|
||
/**
|
||
* @brief PID 参数写入命令
|
||
* @param buf: 8 字节缓冲区(输出)
|
||
* @param location: 写入位置 (0x31=RAM, 0x32=ROM)
|
||
* @param angle_kp: 角度环 Kp (0-255)
|
||
* @param angle_ki: 角度环 Ki (0-255)
|
||
* @param speed_kp: 速度环 Kp (0-255)
|
||
* @param speed_ki: 速度环 Ki (0-255)
|
||
* @param iq_kp: 电流环 Kp (0-255)
|
||
* @param iq_ki: 电流环 Ki (0-255)
|
||
*/
|
||
void cmd_write_pid_params(uint8_t* buf, uint8_t location,
|
||
uint8_t angle_kp, uint8_t angle_ki,
|
||
uint8_t speed_kp, uint8_t speed_ki,
|
||
uint8_t iq_kp, uint8_t iq_ki);
|
||
|
||
/* ============================================================================
|
||
* 辅助函数和宏
|
||
* ============================================================================ */
|
||
|
||
/**
|
||
* @brief 检查电机是否在线
|
||
*/
|
||
bool mf4010v2_is_connected(mf4010v2_t* motor);
|
||
|
||
/**
|
||
* @brief 检查电机是否运行
|
||
*/
|
||
bool mf4010v2_is_running(mf4010v2_t* motor);
|
||
|
||
|
||
/**
|
||
* @brief 检查电机是否错误
|
||
*/
|
||
bool mf4010v2_is_fault(mf4010v2_t* motor);
|
||
|
||
/**
|
||
* @brief 获取电机错误计数
|
||
*/
|
||
uint16_t mf4010v2_get_error_count(mf4010v2_t* motor);
|
||
|
||
/**
|
||
* @brief 重置错误计数
|
||
*/
|
||
void mf4010v2_reset_errors(mf4010v2_t* motor);
|
||
|
||
/**
|
||
* @brief 获取响应中的命令字节
|
||
*/
|
||
#define MF4010_GET_RESPONSE_CMD(motor) ((motor)->last_response[0])
|
||
|
||
/**
|
||
* @brief 获取响应中的数据字节
|
||
*/
|
||
#define MF4010_GET_RESPONSE_DATA(motor, index) ((motor)->last_response[(index) + 1])
|
||
|
||
/**
|
||
* @brief 检查响应是否包含错误
|
||
* @note 如果响应字节 0 的最高位为 1,表示有错误
|
||
*/
|
||
bool mf4010v2_response_has_error(mf4010v2_t* motor);
|
||
|
||
/**
|
||
* @brief 获取错误码(从响应中)
|
||
*/
|
||
uint8_t mf4010v2_get_error_code(mf4010v2_t* motor);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* __MF4010V2__H__ */
|