add-oid编码器

This commit is contained in:
yxming66 2025-11-23 10:51:55 +08:00
parent 2e68c0d0bc
commit b9f7e63025
4 changed files with 748 additions and 2 deletions

View File

@ -1,4 +1,4 @@
bsp,can,dwt,gpio,i2c,mm,spi,uart,pwm,time bsp,can,dwt,gpio,i2c,mm,spi,uart,pwm,time
component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math
device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9 device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid
module,config, module,config,
1 bsp,can,dwt,gpio,i2c,mm,spi,uart,pwm,time
2 component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math
3 device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9 device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid
4 module,config,

View File

@ -224,4 +224,14 @@ devices:
thread_signals: [] thread_signals: []
files: files:
header: "vofa.h" header: "vofa.h"
source: "vofa.c" source: "vofa.c"
oid:
name: "oid编码器"
description: "oid编码器驱动"
dependencies:
bsp: ["time", "can", "mm"]
component: ["user_math"]
thread_signals: []
files:
header: "oid.h"
source: "oid.c"

467
device/oid.c Normal file
View File

@ -0,0 +1,467 @@
/*
oid编码器驱动
*/
/*编码器can通信的默认波特率为500kHZ*/
/* Includes ----------------------------------------------------------------- */
#include "device/oid.h"
#include "bsp/time.h"
#include "mm.h"
/* Private function prototypes ---------------------------------------------- */
static OID_CANManager_t* OID_GetCANManager(BSP_CAN_t can);
/* Private functions -------------------------------------------------------- */
static OID_CANManager_t *can_managers[BSP_CAN_NUM] = {NULL};
/**
* @brief
* @param[in] none
* @retval none
*/
static void OID_ParseFeedbackFrame( OID_t *encoder , uint8_t *rx_data )
{
if(encoder->param.id == rx_data[1])//判断编码器id
{
switch(rx_data[2])//判断指令
{
case 0x01:
encoder->feedback.angle_fbk = rx_data[3]|rx_data[4]<<8|rx_data[5]<<16|rx_data[6]<<24;
encoder->feedback.angle_360 = encoder->feedback.angle_fbk*360.0f/OID_RESOLUTION;
encoder->feedback.angle_2PI = encoder->feedback.angle_fbk*M_2PI/OID_RESOLUTION;
break;
case 0x0A:
encoder->feedback.speed_fbk=rx_data[3]|rx_data[4]<<8|rx_data[5]<<16|rx_data[6]<<24;
encoder->feedback.speed_rpm=encoder->feedback.speed_fbk/OID_RESOLUTION/(0.1f/60.0f);
break;
default:
break;
}
}
}
int8_t OID_Update(OID_Param_t *param)
{
if (param == NULL) return DEVICE_ERR_NULL;
OID_CANManager_t *manager = OID_GetCANManager(param->can);
if (manager == NULL) return DEVICE_ERR_NULL;
OID_t *encoder = NULL;
for (int i = 0; i < manager->encoder_count; i++) {
if (manager->encoders[i] && manager->encoders[i]->param.id == param->id) {
encoder = manager->encoders[i];
break;
}
}
if (encoder == NULL) return DEVICE_ERR_NO_DEV;
// 从CAN队列获取数据
BSP_CAN_Message_t rx_msg;
if (BSP_CAN_GetMessage( param->can , param->id , &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK)
{
uint64_t now_time = BSP_TIME_Get();
if (now_time - encoder->header.last_online_time > 100000) // 100ms超时单位微秒
{
encoder->header.online = false;
}
return DEVICE_ERR;
}
encoder->header.online = true;
encoder->header.last_online_time = BSP_TIME_Get();
// 处理接收到的数据
OID_ParseFeedbackFrame( encoder , rx_msg.data );
return DEVICE_OK; // 没有新数据
}
/**
* @brief
* @return
*/
int8_t OID_UpdateAll(void) {
int8_t ret = DEVICE_OK;
for (int can = 0; can < BSP_CAN_NUM; can++) {
OID_CANManager_t *manager = OID_GetCANManager((BSP_CAN_t)can);
if (manager == NULL) continue;
for (int i = 0; i < manager->encoder_count; i++) {
OID_t *encoder = manager->encoders[i];
if (encoder != NULL) {
if (OID_Update(&encoder->param) != DEVICE_OK) {
ret = DEVICE_ERR;
}
}
}
}
return ret;
}
/**
* @brief CAN总线的管理器
* @param can CAN总线
* @return CAN管理器指针
*/
static OID_CANManager_t* OID_GetCANManager(BSP_CAN_t can) {
if (can >= BSP_CAN_NUM) {
return NULL;
}
return can_managers[can];
}
/**
* @brief CAN管理器
* @param can CAN总线
* @return
*/
static int8_t OID_CreateCANManager(BSP_CAN_t can) {
if (can >= BSP_CAN_NUM) return DEVICE_ERR;
if (can_managers[can] != NULL) return DEVICE_OK;
can_managers[can] = (OID_CANManager_t*)BSP_Malloc(sizeof(OID_CANManager_t));
if (can_managers[can] == NULL) return DEVICE_ERR;
memset(can_managers[can], 0, sizeof(OID_CANManager_t));
can_managers[can]->can = can;
return DEVICE_OK;
}
/**
* @brief
* @param param
* @return
*/
int8_t OID_Register(OID_Param_t *param)
{
if (param == NULL) {
return DEVICE_ERR_NULL;
}
/* 创建CAN管理器 */
if (OID_CreateCANManager(param->can) != DEVICE_OK) {
return DEVICE_ERR;
}
/* 获取CAN管理器 */
OID_CANManager_t *manager = OID_GetCANManager(param->can);
if (manager == NULL) {
return DEVICE_ERR;
}
/* 检查是否已注册 */
for (int i = 0; i < manager->encoder_count; i++) {
if (manager->encoders[i] && manager->encoders[i]->param.id == param->id) {
return DEVICE_ERR_INITED;
}
}
/* 检查是否已达到最大数量 */
if (manager->encoder_count >= OID_MAX_NUM) {
return DEVICE_ERR;
}
/* 分配内存 */
OID_t *encoder = (OID_t *)BSP_Malloc(sizeof(OID_t));
if (encoder == NULL) {
return DEVICE_ERR;
}
/* 初始化电机 */
memset(encoder, 0, sizeof(OID_t));
memcpy(&encoder->param, param, sizeof(OID_Param_t));
encoder->header.online = false;
// encoder->encoder.reverse = param->reverse;
/* 注册CAN接收ID - DM电机使用Master ID接收反馈 */
uint16_t feedback_id = param->id;
if (BSP_CAN_RegisterId(param->can, feedback_id, 3) != BSP_OK) {
BSP_Free(encoder);
return DEVICE_ERR;
}
/* 添加到管理器 */
manager->encoders[manager->encoder_count] = encoder;
manager->encoder_count++;
return DEVICE_OK;
}
/**
* @brief 使线线false
* @param param
* @return
*/
int8_t OID_Offline(OID_Param_t *param) {
if (param == NULL) {
return DEVICE_ERR_NULL;
}
OID_t *encoder = OID_GetEncoder(param);
if (encoder == NULL) {
return DEVICE_ERR_NO_DEV;
}
encoder->header.online = false;
return DEVICE_OK;
}
/**
* @brief
* @param param
* @return
*/
OID_t* OID_GetEncoder(OID_Param_t *param) {
if (param == NULL) {
return NULL;
}
OID_CANManager_t *manager = OID_GetCANManager(param->can);
if (manager == NULL) {
return NULL;
}
/* 查找对应的编码器 */
for (int i = 0; i < manager->encoder_count; i++) {
OID_t *encoder = manager->encoders[i];
if (encoder && encoder->param.can == param->can &&
encoder->param.id == param->id) {
return encoder;
}
}
return NULL;
}
/**
* @brief
* @param[in] id
* @retval none
*/
int8_t OID_Read_Value(OID_Param_t *param)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x01;
frame.data[3] = 0x00;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief id
* @param[in] idid
* @retval none
*/
int8_t OID_Set_ID(OID_Param_t *param,OID_Param_t *param_new)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x02;
frame.data[3] = param_new->id;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief can通讯波特率 0x00500K0x01:1M0x02250K0x03:125K0x04100K
* @param[in] id
* @retval none
*/
int8_t OID_Set_Baudrate(OID_Param_t *param,OID_Baudrate_t encoder_vaud_rate)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x03;
frame.data[3] = encoder_vaud_rate;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief 0x000x020xAA
* @param[in] id
* @retval none
*/
int8_t OID_Set_Mode(OID_Param_t *param,OID_Mode_t encoder_mode)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x04;
frame.data[3] = encoder_mode;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief ()50~6553516
使
* @param[in] id
* @retval none
*/
int8_t OID_Set_AutoFeedbackTime(OID_Param_t *param,uint8_t encoder_time)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x05;
frame.data[3] = encoder_time;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief
* @param[in] id
* @retval none
*/
int8_t OID_Set_ZeroPoint(OID_Param_t *param)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x06;
frame.data[3] = 0x00;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief 0x000x01
* @param[in] id
* @retval none
*/
int8_t OID_Set_Polarity(OID_Param_t *param,OID_Direction_t encoder_direction)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x07;
frame.data[3] = encoder_direction;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief
* @param[in] id
* @retval none
=/
//
1000
32768
100ms(0.1/60min)
=1000/32768/(0.1/60)
=1000*0.0183=18.31/
*/
int8_t OID_Read_AngularVelocity(OID_Param_t *param)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x0A;
frame.data[3] = 0x00;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief ()
* @param[in] id,
* @retval none
*/
int8_t OID_Set_AngularVelocitySamplingTime(OID_Param_t *param,uint8_t encoder_time)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x0B;
frame.data[3] = encoder_time;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief M(M */2)
* @param[in] id
* @retval none
*/
int8_t OID_Set_Midpoint(OID_Param_t *param)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x0C;
frame.data[3] = 0x01;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief 0~XX *- 1
* @param[in] id
* @retval none
*/
int8_t OID_Set_CurrentPosition(OID_Param_t *param,uint8_t encoder_direction)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x0D;
frame.data[3] = encoder_direction;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}
/**
* @brief 5 Z(Z *5)
* @param[in] id
* @retval none
*/
int8_t OID_Set_CurrentValue5Turns(OID_Param_t *param)
{
BSP_CAN_StdDataFrame_t frame;
frame.id = param->id;
frame.dlc = 4;
frame.data[0] = 0x04;
frame.data[1] = param->id;
frame.data[2] = 0x0F;
frame.data[3] = 0x01;
return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR;
}

269
device/oid.h Normal file
View File

@ -0,0 +1,269 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include "device/device.h"
#include "bsp/can.h"
#include "component/user_math.h"
/* Exported constants ------------------------------------------------------- */
#define OID_MAX_NUM 32
#define OID_RESOLUTION 1024 //编码器分辨率
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
/**
* @brief
*/
typedef enum {
OID_MODE_QUERY = 0x00, // 查询模式
OID_MODE_AUTO_SPEED = 0x02, // 自动返回编码器角速度值
OID_MODE_AUTO_POSITION = 0xAA // 自动返回编码器值
} OID_Mode_t;
/**
* @brief
*/
typedef enum {
OID_DIR_CW = 0x00, // 顺时针
OID_DIR_CCW = 0x01 // 逆时针
} OID_Direction_t;
/**
* @brief
* ID和波特率更改后
*
*
* - (0) : 500K
* - (1) : 1M
* - (2) : 250K
* - (3) : 125K
* - 绿(4) : 100K
* - (5) :
*/
typedef enum {
OID_BAUD_500K = 0x00, // 蓝色 - 500K默认
OID_BAUD_1M = 0x01, // 青色 - 1M
OID_BAUD_250K = 0x02, // 橙色 - 250K
OID_BAUD_125K = 0x03, // 紫色 - 125K
OID_BAUD_100K = 0x04 // 绿色 - 100K
} OID_Baudrate_t;
typedef struct {
BSP_CAN_t can;
uint16_t id;
} OID_Param_t;
typedef struct {
//0x01 编码器值反馈
float angle_fbk;
float angle_360;
float angle_2PI;
//0x0A 速度反馈
float speed_fbk;
float speed_rpm;
} OID_Feedback_t;
typedef struct {
DEVICE_Header_t header;
OID_Param_t param;
OID_Feedback_t feedback;
} OID_t;
/*CAN管理器管理一个CAN总线上所有的编码器*/
typedef struct {
BSP_CAN_t can;
OID_t *encoders[OID_MAX_NUM];
uint8_t encoder_count;
} OID_CANManager_t;
/**
* @brief
* @param param
* @return
* - DEVICE_OK:
* - DEVICE_ERR_NULL:
* - DEVICE_ERR_NO_DEV:
* - DEVICE_ERR:
*/
int8_t OID_Update(OID_Param_t *param);
/**
* @brief
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_UpdateAll(void);
/**
* @brief
* @param param
* @return
* - DEVICE_OK:
* - DEVICE_ERR_NULL:
* - DEVICE_ERR_INITED:
* - DEVICE_ERR:
*/
int8_t OID_Register(OID_Param_t *param);
/**
* @brief 线
* @param param
* @return
* - DEVICE_OK:
* - DEVICE_ERR_NULL:
* - DEVICE_ERR_NO_DEV:
*/
int8_t OID_Offline(OID_Param_t *param);
/**
* @brief
* @param param
* @return NULL
*/
OID_t* OID_GetEncoder(OID_Param_t *param);
/**
* @brief ID
* @param param
* @param param_new ID
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_ID(OID_Param_t *param, OID_Param_t *param_new);
/**
* @brief CAN通信波特率
* @param param
* @param encoder_vaud_rate
* - 0x00: 500K
* - 0x01: 1M
* - 0x02: 250K
* - 0x03: 125K
* - 0x04: 100K
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_Baudrate(OID_Param_t *param, OID_Baudrate_t encoder_vaud_rate);
/**
* @brief
* @param param
* @param encoder_mode
* - 0x00:
* - 0x02:
* - 0xAA:
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_Mode(OID_Param_t *param, OID_Mode_t encoder_mode);
/**
* @brief
* @param param
* @param encoder_time
* 50~6553516
* @note 使
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_AutoFeedbackTime(OID_Param_t *param, uint8_t encoder_time);
/**
* @brief
* @param param
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_ZeroPoint(OID_Param_t *param);
/**
* @brief
* @param param
* @param encoder_direction
* - 0x00:
* - 0x01:
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_Polarity(OID_Param_t *param, OID_Direction_t encoder_direction);
/**
* @brief
* @param param
* @param encoder_time
* @note
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_AngularVelocitySamplingTime(OID_Param_t *param, uint8_t encoder_time);
/**
* @brief
* @param param
* @note MM × / 2
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_Midpoint(OID_Param_t *param);
/**
* @brief
* @param param
* @param encoder_direction
* 0~XX × - 1
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_CurrentPosition(OID_Param_t *param, uint8_t encoder_direction);
/**
* @brief 5
* @param param
* @note ZZ × 5
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Set_CurrentValue5Turns(OID_Param_t *param);
/**
* @brief
* @param param
* @note = / / /
* 100032768100ms(0.1/60min)
* = 1000 / 32768 / (0.1/60) = 1000 × 0.0183 = 18.31/
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Read_AngularVelocity(OID_Param_t *param);
/**
* @brief
* @param param
* @return
* - DEVICE_OK:
* - DEVICE_ERR:
*/
int8_t OID_Read_Value(OID_Param_t *param);
#ifdef __cplusplus
}
#endif