Lizongdi 2 weeks ago
parent
commit
7b2717567a
  1. 4
      CMakeLists.txt
  2. 24
      RBcore/BHBF.c
  3. 16
      RBcore/CMakeLists.txt
  4. 63
      RBcore/drv_interface.c
  5. 134
      RBcore/include/BHBF.h
  6. 0
      RBcore/include/drv_interface.h
  7. 135
      RBcore/include/msg_center.h
  8. 373
      RBcore/msg_center.c
  9. 16
      motor/CMakeLists.txt
  10. 183
      motor/include/motor_manager.h
  11. 160
      motor/include/motor_protocol.h
  12. 99
      motor/include/msp_motor_leisai.h
  13. 334
      motor/motor_example.c
  14. 512
      motor/motor_manager.c
  15. 486
      motor/msp_motor_leisai.c
  16. 2
      optional/msp_MK32.c
  17. 2
      optional/msp_TI5MOTOR.c
  18. 5
      project/paint_robot_new/CMakeLists.txt
  19. 39
      project/paint_robot_new/include/paint_robot_new.h
  20. 50
      project/paint_robot_new/paint_robot_new.c

4
CMakeLists.txt

@ -117,9 +117,11 @@ add_module(ringbuffer library/ringbuffer OFF OFF)
add_module(peripheral peripheral OFF ON) add_module(peripheral peripheral OFF ON)
add_module(lua lua OFF ON) add_module(lua lua OFF ON)
add_module(bspMCU bspMCU OFF OFF) add_module(bspMCU bspMCU OFF OFF)
add_module(RBcore project/RBcore OFF OFF) add_module(RBcore RBcore OFF OFF)
add_module(motor motor OFF OFF)
add_module(optional optional OFF OFF) add_module(optional optional OFF OFF)
add_module(Spoolend project/Spoolend OFF OFF) add_module(Spoolend project/Spoolend OFF OFF)
add_module(paint_robot_new project/paint_robot_new OFF OFF)
add_module(Spoolold project_old/Spoolold OFF OFF) add_module(Spoolold project_old/Spoolold OFF OFF)
add_module(paint_robot_old project_old/paint_robot_old OFF OFF) add_module(paint_robot_old project_old/paint_robot_old OFF OFF)

24
project/RBcore/BHBF_robot.c → RBcore/BHBF.c

@ -3,7 +3,7 @@
(C), 2018-2099, Radkil (C), 2018-2099, Radkil
****************************************************************************** ******************************************************************************
: BHBF_robot.c : BHBF.c
: 稿 : 稿
: radkil : radkil
: 202668 : 202668
@ -16,11 +16,9 @@
: :
******************************************************************************/ ******************************************************************************/
#include "BHBF_robot.h" #include "BHBF.h"
#include "common.h" #include "common.h"
#include "cmsis_os.h"
#include "FreeRTOS.h"
#include "task.h" #include "task.h"
/*----------------------------------------------* /*----------------------------------------------*
@ -38,7 +36,7 @@
/*----------------------------------------------* /*----------------------------------------------*
* * * *
*----------------------------------------------*/ *----------------------------------------------*/
GV_struct_define GV = {0}; GV_define GV = {0};
/*----------------------------------------------* /*----------------------------------------------*
* * * *
@ -51,17 +49,17 @@ GV_struct_define GV = {0};
/*----------------------------------------------* /*----------------------------------------------*
* * * *
*----------------------------------------------*/ *----------------------------------------------*/
GV_struct_define *GetGV(void) GV_define *GetGV(void)
{ {
static GV_struct_define tmpGV = {0}; static GV_define tmpGV = {0};
RD_MEMSET(&tmpGV, 0, sizeof(tmpGV)); RD_MEMSET(&tmpGV, 0, sizeof(tmpGV));
RD_MEMCPY(&tmpGV, &GV, sizeof(GV_struct_define)); RD_MEMCPY(&tmpGV, &GV, sizeof(GV_define));
return &tmpGV; return &tmpGV;
} }
void SetGV(GV_struct_define *_pGV) void SetGV(GV_define *_pGV)
{ {
RD_MEMCPY(&GV, _pGV, sizeof(GV_struct_define)); RD_MEMCPY(&GV, _pGV, sizeof(GV_define));
} }
void GF_FsmStart(GF_CMD GFCmd) void GF_FsmStart(GF_CMD GFCmd)
@ -73,15 +71,13 @@ void GF_Dispatch(void *argument)
{ {
while(1) while(1)
{ {
GF_CMD GFCmd = MK32_Task(GV.m_iWorkMode); //GF_CMD GFCmd = MK32_Task(GV.m_iWorkMode);
GF_FsmStart(GFCmd); GF_FsmStart(0);
} }
} }
void GF_Init(void) void GF_Init(void)
{ {
Drv_InterfaceInit();
// const osThreadAttr_t GF_Dispatch_attributes = { // const osThreadAttr_t GF_Dispatch_attributes = {
// .name = "GF_Task", // .name = "GF_Task",
// .stack_size = 1024, // .stack_size = 1024,

16
RBcore/CMakeLists.txt

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.10)
get_filename_component(TARGET_NAME "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
set(COMMON_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../library/CMakeLists.txt")
if(EXISTS ${COMMON_CMAKE_PATH})
include(${COMMON_CMAKE_PATH})
else()
message(FATAL_ERROR "Cannot find common build logic at ${COMMON_CMAKE_PATH}")
endif()
if(TARGET bspMCU)
target_link_libraries(${TARGET_NAME} PUBLIC bspMCU)
else()
message(FATAL_ERROR "[${TARGET_NAME}] Dependency 'bspMCU' not found.")
endif()

63
project/RBcore/drv_interface.c → RBcore/drv_interface.c

@ -16,12 +16,12 @@
: :
******************************************************************************/ ******************************************************************************/
#include "BHBF_robot.h" #include "BHBF.h"
#include "cmsis_os.h" #include "cmsis_os.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h"
#include "msg_center.h"
/*----------------------------------------------* /*----------------------------------------------*
* * * *
*----------------------------------------------*/ *----------------------------------------------*/
@ -255,10 +255,56 @@ void SendAll_Task(void *argument)
} }
} }
void Drv_InterfaceInit(void) extern void MotorInit(void);
extern void MotorMgr_ParseResponse(uint8_t ucMotorID, const uint8_t *pucData, uint32_t uiLen);
// 雷赛电机CAN响应检查函数
// 雷赛响应ID范围:0x581 - 0x5FF (0x580 + MotorID)
static int check_LeiSaiMotor(char *_pBuffer, uint32_t _iSize)
{
if (NULL == _pBuffer || _iSize < 4)
{
return 0;
}
// 从buffer中提取CAN ID(前4字节)
uint32_t uiFrameID = (uint32_t)(_pBuffer[0] & 0xFF)
| ((_pBuffer[1] & 0xFF) << 8)
| ((_pBuffer[2] & 0xFF) << 16)
| ((_pBuffer[3] & 0xFF) << 24);
// 雷赛响应ID范围:0x581 - 0x5FF
if (uiFrameID >= 0x581 && uiFrameID <= 0x5FF)
{
return 8 + 4; // 数据长度8 + CAN ID长度4
}
return 0;
}
// 雷赛电机CAN响应解码函数
static void decode_LeiSaiMotor(const char *_pBuffer, uint32_t _iSize)
{ {
//MK32_Init(); if (NULL == _pBuffer || _iSize < 12) // 4字节CAN ID + 8字节数据
{
return;
}
// 从buffer中提取CAN ID
uint32_t uiFrameID = (uint32_t)(_pBuffer[0] & 0xFF)
| ((_pBuffer[1] & 0xFF) << 8)
| ((_pBuffer[2] & 0xFF) << 16)
| ((_pBuffer[3] & 0xFF) << 24);
// 提取电机ID (0x580 + MotorID)
uint8_t ucMotorID = (uint8_t)(uiFrameID - 0x580);
// 调用电机管理模块解析响应
MotorMgr_ParseResponse(ucMotorID, (const uint8_t *)&_pBuffer[4], 8);
}
void Drv_InterfaceInit(void)
{
const osThreadAttr_t Read_RS485_1_attributes = { const osThreadAttr_t Read_RS485_1_attributes = {
.name = "RS485_1", .name = "RS485_1",
.stack_size = 512, .stack_size = 512,
@ -273,5 +319,12 @@ void Drv_InterfaceInit(void)
}; };
(void)osThreadNew(SendAll_Task, NULL, &send_task_attributes); (void)osThreadNew(SendAll_Task, NULL, &send_task_attributes);
//MoveWheel_Init(); MsgCenter_Init();
// 初始化FDCAN1,使用雷赛电机的回调
TCANUserData *ptCANUserData = CAN_userdata_init(&hfdcan1, 8, 0);
g_ptFDCAN1 = rd_ComCreate(check_LeiSaiMotor, decode_LeiSaiMotor, FDCAN1_Send, CONFIG_UART_BUFFER_SIZE, ptCANUserData);
CAN_IT_init(g_ptFDCAN1);
MotorInit();
} }

134
RBcore/include/BHBF.h

@ -0,0 +1,134 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: BHBF.h
: 稿
: radkil
: 202668
:
: BHBF.c
:
1. : 202668
: radkil
:
******************************************************************************/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
#ifndef __BHBF_H__
#define __BHBF_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*==============================================*
* include header files *
*----------------------------------------------*/
#include "drv_interface.h"
#include "rd_time.h"
#include "msg_center.h"
#include "cmsis_os.h"
#include "FreeRTOS.h"
/*==============================================*
* constants or macros define *
*----------------------------------------------*/
#define MODULE_NAME_MOTOR "motor"
typedef enum {
MOTOR_CMD_SET_SPEED = 0x01, // 设置速度
MOTOR_CMD_SET_POSITION = 0x02, // 设置位置
MOTOR_CMD_STOP = 0x03, // 停止
MOTOR_CMD_GET_STATUS = 0x04, // 获取状态
MOTOR_CMD_SET_HOME = 0x05, // 设置零点
MOTOR_CMD_SPEED_MODE = 0x06, // 速度模式
MOTOR_CMD_POSITION_MODE = 0x07, // 位置模式
} Motor_Cmd_e;
// 电机命令数据结构
typedef struct {
uint8_t m_ucMotorIndex; // 电机索引(0=左轮,1=右轮)
int32_t m_iValue; // 值(速度/位置等)
} Motor_CmdData_t;
// 电机状态数据结构
typedef struct {
uint8_t m_ucMotorIndex;
int32_t m_iPosition;
int32_t m_iVelocity;
uint32_t m_uiFaultCode;
} Motor_StatusData_t;
#define MODULE_NAME_RBCORE "RBcore"
typedef enum {
GF_CMD_DEFAULT_NULL = 0,
GF_CMD_STOP_ALL,
GF_CMD_MANUAL_FORWARD,
GF_CMD_MANUAL_BACKWARD,
GF_CMD_AUTO_FORWARD
} GF_CMD;
typedef struct _GV_struct_define
{
int m_iWorkMode;
GF_CMD m_eGFCmd;
int32_t m_iMoveSpeed[2];//索引1对应左轮,索引2对应右轮
} GV_define;
/*==============================================*
* project-wide global variables *
*----------------------------------------------*/
/*==============================================*
* routines' or functions' implementations *
*----------------------------------------------*/
GV_define *GetGV(void);
void SetGV(GV_define *_pGV);
// 待实现接口
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __BHBF_ROBOT_H__ */

0
project/RBcore/include/drv_interface.h → RBcore/include/drv_interface.h

135
RBcore/include/msg_center.h

@ -0,0 +1,135 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: msg_center.h
: 稿
: radkil
: 2026713
:
: 线
:
1. : 2026713
: radkil
:
******************************************************************************/
#ifndef __MSG_CENTER_H__
#define __MSG_CENTER_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*==============================================*
* include header files *
*----------------------------------------------*/
#include "common.h"
/*==============================================*
* constants or macros define *
*----------------------------------------------*/
#define MSG_CENTER_MAX_MODULES 16 // 最大模块数
#define MSG_CENTER_MAX_NAME_LEN 16 // 模块名称最大长度
#define MSG_CENTER_QUEUE_SIZE 64 // 消息队列大小
#define MSG_CENTER_MAX_DATA_SIZE 32 // 消息数据最大大小
/*==============================================*
* data structures *
*----------------------------------------------*/
// 消息ID定义(各模块自己的命令字)
typedef uint32_t MsgID_t;
// 消息结构
typedef struct {
uint32_t m_uiSrcModule; // 源模块ID
uint32_t m_uiDstModule; // 目标模块ID
MsgID_t m_uiMsgID; // 消息ID(命令字)
uint32_t m_uiDataLen; // 数据长度
uint8_t m_aucData[MSG_CENTER_MAX_DATA_SIZE]; // 消息数据
} Msg_t;
// 消息处理回调函数类型
typedef void (*MsgHandler_t)(const Msg_t *pstMsg);
// 模块注册信息
typedef struct {
char m_szName[MSG_CENTER_MAX_NAME_LEN]; // 模块名称
uint32_t m_uiModuleID; // 模块ID
MsgHandler_t m_pfHandler; // 消息处理回调
} MsgModule_t;
/*==============================================*
* project-wide global variables *
*----------------------------------------------*/
/*==============================================*
* routines' or functions' implementations *
*----------------------------------------------*/
/**
* @brief
*/
void MsgCenter_Init(void);
/**
* @brief
* @param pszName
* @param pfHandler
* @return ID0
*/
uint32_t MsgCenter_Register(const char *pszName, MsgHandler_t pfHandler);
/**
* @brief ID
* @param pszName
* @return ID0
*/
uint32_t MsgCenter_FindModule(const char *pszName);
/**
* @brief 线
* @param pstMsg
* @return 00
*/
int MsgCenter_Send(const Msg_t *pstMsg);
/**
* @brief 便
* @param pszDstName
* @param uiMsgID ID
* @param pData NULL
* @param uiDataLen
* @return 00
*/
int MsgCenter_SendTo(const char *pszDstName, MsgID_t uiMsgID, const void *pData, uint32_t uiDataLen);
/**
* @brief 线
* @param uiModuleID ID
* @return
*/
int MsgCenter_Process(uint32_t uiModuleID);
/**
* @brief
* @param uiModuleID ID
* @param uiTimeoutMs 0
* @return -1
*/
int MsgCenter_ProcessWait(uint32_t uiModuleID, uint32_t uiTimeoutMs);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __MSG_CENTER_H__ */

373
RBcore/msg_center.c

@ -0,0 +1,373 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: msg_center.c
: 稿
: radkil
: 2026713
:
: 线
:
1. : 2026713
: radkil
:
******************************************************************************/
#include "msg_center.h"
#include "rd_thread.h"
#include "ringbuffer.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
// 模块注册表
typedef struct {
MsgModule_t stModule;
rd_ringbuf_t *pstRingBuf; // 消息队列(ringbuffer)
rd_mutex_t stMutex; // 互斥锁(保护ringbuffer)
rd_sem_t stSem; // 信号量(阻塞等待)
} MsgModuleEntry_t;
static MsgModuleEntry_t g_astModules[MSG_CENTER_MAX_MODULES];
static uint32_t g_uiModuleCount = 0;
static uint32_t g_uiNextModuleID = 1; // 从1开始,0表示无效
/*----------------------------------------------*
* *
*----------------------------------------------*/
// ringbuffer大小:每个模块可缓存的消息数量
#define MSG_RING_BUFFER_SIZE (MSG_CENTER_QUEUE_SIZE * sizeof(Msg_t))
/*----------------------------------------------*
* *
*----------------------------------------------*/
// 查找模块索引
#define FIND_MODULE_INDEX(uiModuleID) \
((uiModuleID) > 0 && (uiModuleID) <= g_uiModuleCount ? \
(uiModuleID) - 1 : -1)
/*****************************************************************************
: MsgCenter_Init
:
:
:
: void
*****************************************************************************/
void MsgCenter_Init(void)
{
g_uiModuleCount = 0;
g_uiNextModuleID = 1;
RD_MEMSET(g_astModules, 0, sizeof(g_astModules));
}
/*****************************************************************************
: MsgCenter_Register
:
: const char *pszName
MsgHandler_t pfHandler
:
: uint32_t ID0
*****************************************************************************/
uint32_t MsgCenter_Register(const char *pszName, MsgHandler_t pfHandler)
{
if (NULL == pszName || NULL == pfHandler)
{
return 0;
}
if (g_uiModuleCount >= MSG_CENTER_MAX_MODULES)
{
return 0; // 模块数已满
}
// 检查名称是否重复
for (uint32_t i = 0; i < g_uiModuleCount; i++)
{
if (RD_STRCMP(g_astModules[i].stModule.m_szName, pszName) == 0)
{
return 0; // 名称重复
}
}
// 注册模块
uint32_t uiIndex = g_uiModuleCount;
uint32_t uiModuleID = g_uiNextModuleID++;
RD_STRNCPY(g_astModules[uiIndex].stModule.m_szName, pszName, MSG_CENTER_MAX_NAME_LEN - 1);
g_astModules[uiIndex].stModule.m_szName[MSG_CENTER_MAX_NAME_LEN - 1] = '\0';
g_astModules[uiIndex].stModule.m_uiModuleID = uiModuleID;
g_astModules[uiIndex].stModule.m_pfHandler = pfHandler;
// 创建 ringbuffer
g_astModules[uiIndex].pstRingBuf = rd_RingbufferCreate(MSG_RING_BUFFER_SIZE);
if (NULL == g_astModules[uiIndex].pstRingBuf)
{
return 0;
}
// 初始化互斥锁
if (Rd_MutexInit(&g_astModules[uiIndex].stMutex) != RD_SUCCESS)
{
rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf);
return 0;
}
// 初始化信号量(初始值为0,表示无消息)
if (Rd_SemInit(&g_astModules[uiIndex].stSem, 0, 0) != RD_SUCCESS)
{
Rd_MutexDestroy(&g_astModules[uiIndex].stMutex);
rd_RingbufferDestroy(g_astModules[uiIndex].pstRingBuf);
return 0;
}
g_uiModuleCount++;
return uiModuleID;
}
/*****************************************************************************
: MsgCenter_FindModule
: ID
: const char *pszName
:
: uint32_t ID0
*****************************************************************************/
uint32_t MsgCenter_FindModule(const char *pszName)
{
if (NULL == pszName)
{
return 0;
}
for (uint32_t i = 0; i < g_uiModuleCount; i++)
{
if (RD_STRCMP(g_astModules[i].stModule.m_szName, pszName) == 0)
{
return g_astModules[i].stModule.m_uiModuleID;
}
}
return 0;
}
/*****************************************************************************
: MsgCenter_Send
: 线
: const Msg_t *pstMsg
:
: int 00
*****************************************************************************/
int MsgCenter_Send(const Msg_t *pstMsg)
{
if (NULL == pstMsg)
{
return RD_NULL;
}
int iDstIndex = FIND_MODULE_INDEX(pstMsg->m_uiDstModule);
if (iDstIndex < 0 || NULL == g_astModules[iDstIndex].pstRingBuf)
{
return RD_FAILURE;
}
// 加锁保护ringbuffer
Rd_MutexLock(&g_astModules[iDstIndex].stMutex, __func__, NULL);
// 写入ringbuffer
int iRet = rd_RingbufferPut(g_astModules[iDstIndex].pstRingBuf,
(const char *)pstMsg, sizeof(Msg_t));
Rd_MutexUnlock(&g_astModules[iDstIndex].stMutex, __func__, NULL);
if (iRet > 0)
{
// 发送信号量,通知有新消息
Rd_SemPost(&g_astModules[iDstIndex].stSem, __func__, NULL);
return RD_SUCCESS;
}
return RD_FAILURE; // 队列满
}
/*****************************************************************************
: MsgCenter_SendTo
: 便
: const char *pszDstName
MsgID_t uiMsgID ID
const void *pData NULL
uint32_t uiDataLen
:
: int 00
*****************************************************************************/
int MsgCenter_SendTo(const char *pszDstName, MsgID_t uiMsgID, const void *pData, uint32_t uiDataLen)
{
if (NULL == pszDstName)
{
return RD_NULL;
}
uint32_t uiDstModuleID = MsgCenter_FindModule(pszDstName);
if (0 == uiDstModuleID)
{
return RD_FAILURE;
}
Msg_t stMsg;
RD_MEMSET(&stMsg, 0, sizeof(Msg_t));
stMsg.m_uiDstModule = uiDstModuleID;
stMsg.m_uiMsgID = uiMsgID;
if (NULL != pData && uiDataLen > 0)
{
if (uiDataLen > MSG_CENTER_MAX_DATA_SIZE)
{
uiDataLen = MSG_CENTER_MAX_DATA_SIZE;
}
RD_MEMCPY(stMsg.m_aucData, pData, uiDataLen);
stMsg.m_uiDataLen = uiDataLen;
}
return MsgCenter_Send(&stMsg);
}
/*****************************************************************************
: MsgCenter_ProcessOne
: ringbuffer读取一条消息
: int iIndex
Msg_t *pstMsg
:
: int 10
*****************************************************************************/
static int MsgCenter_ProcessOne(int iIndex, Msg_t *pstMsg)
{
// 加锁保护ringbuffer
Rd_MutexLock(&g_astModules[iIndex].stMutex, __func__, NULL);
int iRet = rd_RingbufferGet(g_astModules[iIndex].pstRingBuf,
(char *)pstMsg, sizeof(Msg_t));
Rd_MutexUnlock(&g_astModules[iIndex].stMutex, __func__, NULL);
return (iRet > 0) ? 1 : 0;
}
/*****************************************************************************
: MsgCenter_Process
: 线
: uint32_t uiModuleID ID
:
: int
*****************************************************************************/
int MsgCenter_Process(uint32_t uiModuleID)
{
int iIndex = FIND_MODULE_INDEX(uiModuleID);
if (iIndex < 0 || NULL == g_astModules[iIndex].pstRingBuf)
{
return 0;
}
int iCount = 0;
Msg_t stMsg;
// 非阻塞读取所有待处理消息
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}
/*****************************************************************************
: MsgCenter_ProcessWait
:
: uint32_t uiModuleID ID
uint32_t uiTimeoutMs 0
:
: int -1
*****************************************************************************/
int MsgCenter_ProcessWait(uint32_t uiModuleID, uint32_t uiTimeoutMs)
{
int iIndex = FIND_MODULE_INDEX(uiModuleID);
if (iIndex < 0 || NULL == g_astModules[iIndex].pstRingBuf)
{
return -1;
}
Msg_t stMsg;
// 等待信号量(有新消息到达)
if (uiTimeoutMs > 0)
{
// 带超时等待
Rd_SemWait(&g_astModules[iIndex].stSem, __func__, NULL);
}
else
{
// 非阻塞,直接检查ringbuffer
if (!MsgCenter_ProcessOne(iIndex, &stMsg))
{
return 0;
}
// 处理第一条消息
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
// 继续处理剩余消息
int iCount = 1;
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}
// 信号量被触发,处理消息
int iCount = 0;
while (MsgCenter_ProcessOne(iIndex, &stMsg))
{
if (g_astModules[iIndex].stModule.m_pfHandler != NULL)
{
g_astModules[iIndex].stModule.m_pfHandler(&stMsg);
}
iCount++;
}
return iCount;
}

16
motor/CMakeLists.txt

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.10)
get_filename_component(TARGET_NAME "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
set(COMMON_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../library/CMakeLists.txt")
if(EXISTS ${COMMON_CMAKE_PATH})
include(${COMMON_CMAKE_PATH})
else()
message(FATAL_ERROR "Cannot find common build logic at ${COMMON_CMAKE_PATH}")
endif()
if(TARGET RBcore)
target_link_libraries(${TARGET_NAME} PUBLIC RBcore)
else()
message(FATAL_ERROR "[${TARGET_NAME}] Dependency 'RBcore' not found.")
endif()

183
motor/include/motor_manager.h

@ -0,0 +1,183 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: motor_manager.h
: 稿
: radkil
: 2026713
:
:
:
1. : 2026713
: radkil
:
******************************************************************************/
#ifndef __MOTOR_MANAGER_H__
#define __MOTOR_MANAGER_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*==============================================*
* include header files *
*----------------------------------------------*/
#include "motor_protocol.h"
/*==============================================*
* constants or macros define *
*----------------------------------------------*/
#define MOTOR_INSTANCE_MAX 8 //支持最大电机实例数
/*==============================================*
* data structures *
*----------------------------------------------*/
/*==============================================*
* project-wide global variables *
*----------------------------------------------*/
/*==============================================*
* routines' or functions' implementations *
*----------------------------------------------*/
/**
* @brief
*/
void MotorMgr_Init(void);
/**
* @brief
* @param pstConfig
* @param ptCAN CAN控制器
* @param pstProtocol
* @param pstPrivData NULL
* @return NULL
*/
Motor_Instance_t* MotorMgr_Create(const Motor_Config_t *pstConfig,
TComCtrl *ptCAN,
const Motor_Protocol_t *pstProtocol,
void *pstPrivData);
/**
* @brief
* @param pstMotor
* @return 00
*/
int MotorMgr_Destroy(Motor_Instance_t *pstMotor);
/**
* @brief
* @param pszName
* @return NULL
*/
Motor_Instance_t* MotorMgr_FindByName(const char *pszName);
/**
* @brief ID查找电机实例
* @param ucMotorID ID
* @return NULL
*/
Motor_Instance_t* MotorMgr_FindByID(uint8_t ucMotorID);
/**
* @brief
*/
int MotorMgr_ResetAll(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_ActivateAll(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_SetHome(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_SetWatchdog(Motor_Instance_t *pstMotor, uint32_t uiTimeMs);
/**
* @brief
*/
int MotorMgr_RequestPosition(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_RequestVelocity(Motor_Instance_t *pstMotor);
/**
* @brief /
*/
int MotorMgr_RequestTorque(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_RequestFault(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_SpeedModeInit(Motor_Instance_t *pstMotor);
/**
* @brief
*/
int MotorMgr_SetTargetSpeed(Motor_Instance_t *pstMotor, int32_t iTargetSpeed);
/**
* @brief
*/
int MotorMgr_PositionModeInit(Motor_Instance_t *pstMotor, int32_t iAccel, int32_t iDecel, int32_t iTargetSpeed);
/**
* @brief
*/
int MotorMgr_SetTargetPosition(Motor_Instance_t *pstMotor, int32_t iTargetPos);
/**
* @brief
*/
int MotorMgr_SetDO(Motor_Instance_t *pstMotor, uint8_t ucDoIndex, uint8_t ucState);
/**
* @brief CAN响应数据
* @param ucMotorID ID
* @param pucData
* @param uiLen
*/
void MotorMgr_ParseResponse(uint8_t ucMotorID, const uint8_t *pucData, uint32_t uiLen);
/**
* @brief
*/
int32_t MotorMgr_SpeedConvert(Motor_Instance_t *pstMotor, int32_t iSpeedUserUnit);
/**
* @brief
*/
const Motor_Data_t* MotorMgr_GetData(Motor_Instance_t *pstMotor);
/**
* @brief
*/
Motor_State_e MotorMgr_GetState(Motor_Instance_t *pstMotor);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __MOTOR_MANAGER_H__ */

160
motor/include/motor_protocol.h

@ -0,0 +1,160 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: motor_protocol.h
: 稿
: radkil
: 2026713
:
:
:
1. : 2026713
: radkil
:
******************************************************************************/
#ifndef __MOTOR_PROTOCOL_H__
#define __MOTOR_PROTOCOL_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*==============================================*
* include header files *
*----------------------------------------------*/
#include "common.h"
#include "slist.h"
#include "com.h"
/*==============================================*
* constants or macros define *
*----------------------------------------------*/
#define MOTOR_MAX_NAME_LEN 16
/*==============================================*
* data structures *
*----------------------------------------------*/
// 电机状态枚举
typedef enum {
MOTOR_STATE_IDLE = 0, // 空闲
MOTOR_STATE_INIT, // 初始化中
MOTOR_STATE_READY, // 就绪
MOTOR_STATE_RUNNING, // 运行中
MOTOR_STATE_ERROR, // 错误
} Motor_State_e;
// 电机运行数据
typedef struct {
int32_t m_iRealPosition; // 实际位置(脉冲)
int32_t m_iRealVelocity; // 实际速度(脉冲/秒)
int32_t m_iRealTorque; // 实际转矩
uint32_t m_uiFaultCode; // 故障码
double m_dRealDistance; // 实际距离(米)
int32_t m_iStartMeasurePos; // 测量起始位置
int32_t m_iLastPosition; // 上次位置
int32_t m_iRoundCount; // 圈数计数
uint8_t m_ucStartMeasureFlag; // 开始测量标志
} Motor_Data_t;
// 电机物理配置
typedef struct {
uint8_t m_ucMotorID; // 电机节点ID
uint32_t m_uiPulsePerRound; // 每圈脉冲数
uint32_t m_uiReductionRatio; // 减速比
float m_fWheelDiameter; // 轮直径(米)
} Motor_Config_t;
// 前向声明
struct Motor_Instance;
// 协议操作函数表(虚函数表)
typedef struct {
// 协议名称
char m_szName[MOTOR_MAX_NAME_LEN];
// 初始化电机(协议特定的初始化序列)
int (*pfInit)(struct Motor_Instance *pstMotor);
// 复位所有节点
int (*pfResetAll)(struct Motor_Instance *pstMotor);
// 激活所有节点
int (*pfActivateAll)(struct Motor_Instance *pstMotor);
// 设置当前位置为零点
int (*pfSetHome)(struct Motor_Instance *pstMotor);
// 设置看门狗时间
int (*pfSetWatchdog)(struct Motor_Instance *pstMotor, uint32_t uiTimeMs);
// 读取电机位置
int (*pfRequestPosition)(struct Motor_Instance *pstMotor);
// 读取电机速度
int (*pfRequestVelocity)(struct Motor_Instance *pstMotor);
// 读取电机电流/转矩
int (*pfRequestTorque)(struct Motor_Instance *pstMotor);
// 读取故障码
int (*pfRequestFault)(struct Motor_Instance *pstMotor);
// 速度模式初始化
int (*pfSpeedModeInit)(struct Motor_Instance *pstMotor);
// 设置目标速度
int (*pfSetTargetSpeed)(struct Motor_Instance *pstMotor, int32_t iTargetSpeed);
// 位置模式初始化
int (*pfPositionModeInit)(struct Motor_Instance *pstMotor, int32_t iAccel, int32_t iDecel, int32_t iTargetSpeed);
// 设置目标位置(相对运动)
int (*pfSetTargetPosition)(struct Motor_Instance *pstMotor, int32_t iTargetPos);
// 设置数字输出
int (*pfSetDO)(struct Motor_Instance *pstMotor, uint8_t ucDoIndex, uint8_t ucState);
// 解析CAN响应数据
int (*pfParseResponse)(struct Motor_Instance *pstMotor, const uint8_t *pucData, uint32_t uiLen);
// 速度单位转换:用户单位 -> 脉冲/秒
int32_t (*pfSpeedConvert)(struct Motor_Instance *pstMotor, int32_t iSpeedUserUnit);
} Motor_Protocol_t;
// 电机实例结构体
typedef struct Motor_Instance {
rd_slist_t node; // slist链表节点
char m_szName[MOTOR_MAX_NAME_LEN]; // 实例名称
Motor_Config_t m_stConfig; // 配置
Motor_Data_t m_stData; // 运行数据
Motor_State_e m_eState; // 状态
TComCtrl *m_ptCAN; // 绑定的CAN控制器
uint32_t m_uiLastHeartbeat; // 上次心跳时间
const Motor_Protocol_t *m_pstProtocol; // 协议操作函数表
void *m_pstPrivData; // 协议私有数据
} Motor_Instance_t;
/*==============================================*
* project-wide global variables *
*----------------------------------------------*/
/*==============================================*
* routines' or functions' implementations *
*----------------------------------------------*/
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __MOTOR_PROTOCOL_H__ */

99
motor/include/msp_motor_leisai.h

@ -0,0 +1,99 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: msp_motor_leisai.h
: 稿
: radkil
: 2026713
:
: ISV2电机CAN协议实现
:
1. : 2026713
: radkil
:
******************************************************************************/
#ifndef __MOTOR_LEISAI_H__
#define __MOTOR_LEISAI_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
/*==============================================*
* include header files *
*----------------------------------------------*/
#include "motor_manager.h"
/*==============================================*
* constants or macros define *
*----------------------------------------------*/
// SDO命令字
#define LEISAI_SDO_CMD_READ 0x40
#define LEISAI_SDO_CMD_WRITE_1B 0x2F
#define LEISAI_SDO_CMD_WRITE_2B 0x2B
#define LEISAI_SDO_CMD_WRITE_3B 0x27
#define LEISAI_SDO_CMD_WRITE_4B 0x23
// CANopen 对象字典索引
#define LEISAI_OD_CONTROL_WORD 0x6040
#define LEISAI_OD_STATUS_WORD 0x6041
#define LEISAI_OD_MODE_OF_OPERATION 0x6060
#define LEISAI_OD_POSITION_ACTUAL 0x6064
#define LEISAI_OD_VELOCITY_ACTUAL 0x606C
#define LEISAI_OD_TORQUE_ACTUAL 0x6077
#define LEISAI_OD_TARGET_VELOCITY 0x60FF
#define LEISAI_OD_TARGET_POSITION 0x607A
#define LEISAI_OD_ACCELERATION 0x6083
#define LEISAI_OD_DECELERATION 0x6084
#define LEISAI_OD_FAULT_CODE 0x603F
#define LEISAI_OD_HOMING_METHOD 0x6098
#define LEISAI_OD_WATCHDOG_TIME 0x5004
// 操作模式
#define LEISAI_MODE_PROFILE_POS 0x01
#define LEISAI_MODE_PROFILE_VEL 0x03
#define LEISAI_MODE_HOMING 0x06
// 控制字命令
#define LEISAI_CTRL_SHUTDOWN 0x06
#define LEISAI_CTRL_SWITCH_ON 0x07
#define LEISAI_CTRL_ENABLE 0x0F
#define LEISAI_CTRL_START_MOVE 0x5F
#define LEISAI_CTRL_RELATIVE_MOVE 0x4F
/*==============================================*
* data structures *
*----------------------------------------------*/
/*==============================================*
* project-wide global variables *
*----------------------------------------------*/
// 雷赛协议操作函数表(全局单例)
extern const Motor_Protocol_t g_stLeiSaiProtocol;
/*==============================================*
* routines' or functions' implementations *
*----------------------------------------------*/
/**
* @brief
* @return
*/
const Motor_Protocol_t* LeiSai_GetProtocol(void);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* __MOTOR_LEISAI_H__ */

334
motor/motor_example.c

@ -0,0 +1,334 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: motor_example.c
: 稿
: radkil
: 2026713
:
: 使
:
1. : 2026713
: radkil
:
******************************************************************************/
#include "BHBF.h"
#include "motor_manager.h"
#include "msp_motor_leisai.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
static Motor_Instance_t *g_apstMotors[MOTOR_INSTANCE_MAX] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static uint32_t g_uiMotorModuleID = 0;
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
#if 0
/*****************************************************************************
: MotorExample_LeiSai
: 使
:
:
: void
*****************************************************************************/
void MotorExample_LeiSai(void)
{
// 1. 初始化电机管理模块
MotorMgr_Init();
// 2. 配置左轮电机
Motor_Config_t stLeftConfig = {
.m_ucMotorID = 1,
.m_uiPulsePerRound = 10000,
.m_uiReductionRatio = 70,
.m_fWheelDiameter = 0.26f
};
// 3. 创建电机实例(使用雷赛协议)
Motor_Instance_t *pstLeftMotor = MotorMgr_Create(&stLeftConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
// 4. 配置右轮电机
Motor_Config_t stRightConfig = {
.m_ucMotorID = 2,
.m_uiPulsePerRound = 10000,
.m_uiReductionRatio = 70,
.m_fWheelDiameter = 0.26f
};
Motor_Instance_t *pstRightMotor = MotorMgr_Create(&stRightConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
// 5. 复位并激活所有电机
if (pstLeftMotor != NULL)
{
MotorMgr_ResetAll(pstLeftMotor);
Rd_Delay(1000);
MotorMgr_ActivateAll(pstLeftMotor);
Rd_Delay(1000);
}
// 6. 设置当前位置为零点
if (pstLeftMotor != NULL)
{
MotorMgr_SetHome(pstLeftMotor);
Rd_Delay(100);
}
if (pstRightMotor != NULL)
{
MotorMgr_SetHome(pstRightMotor);
Rd_Delay(100);
}
// 7. 初始化速度模式
if (pstLeftMotor != NULL)
{
MotorMgr_SpeedModeInit(pstLeftMotor);
}
if (pstRightMotor != NULL)
{
MotorMgr_SpeedModeInit(pstRightMotor);
}
// 8. 设置目标速度
if (pstLeftMotor != NULL)
{
MotorMgr_SetTargetSpeed(pstLeftMotor, 100000);
}
if (pstRightMotor != NULL)
{
MotorMgr_SetTargetSpeed(pstRightMotor, -100000);
}
// 9. 定期读取电机状态
while(1)
{
if (pstLeftMotor != NULL)
{
MotorMgr_RequestPosition(pstLeftMotor);
MotorMgr_RequestVelocity(pstLeftMotor);
MotorMgr_RequestFault(pstLeftMotor);
const Motor_Data_t *pstData = MotorMgr_GetData(pstLeftMotor);
if (pstData != NULL)
{
RD_PRINTF("Left Motor: Pos=%ld, Vel=%ld, Dist=%.3f m\n",
pstData->m_iRealPosition,
pstData->m_iRealVelocity,
pstData->m_dRealDistance);
}
}
Rd_Delay(100);
}
}
/*****************************************************************************
: MotorExample_MultiProtocol
: 使
:
:
: void
1. Motor_Protocol_t
2. MotorMgr_Create
*****************************************************************************/
void MotorExample_MultiProtocol(void)
{
MotorMgr_Init();
// 使用雷赛协议的电机
Motor_Config_t stConfig1 = { .m_ucMotorID = 1 };
Motor_Instance_t *pstMotor1 = MotorMgr_Create(&stConfig1, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
// 假设未来有其他协议
// Motor_Config_t stConfig2 = { .m_ucMotorID = 2 };
// Motor_Instance_t *pstMotor2 = MotorMgr_Create(&stConfig2, g_ptFDCAN2, OtherProtocol_GetProtocol(), NULL);
// 统一的管理接口
MotorMgr_SpeedModeInit(pstMotor1);
MotorMgr_SetTargetSpeed(pstMotor1, 50000);
// 通过名称查找
Motor_Instance_t *pstFound = MotorMgr_FindByName("Motor_1");
if (pstFound != NULL)
{
RD_PRINTF("Found motor: %s\n", pstFound->m_szName);
}
}
#endif
void MotorTask(void *argument)
{
// 等待系统稳定
Rd_Delay(1000);
// 复位并激活所有电机
for (int i = 0; i < MOTOR_INSTANCE_MAX; i++)
{
if (g_apstMotors[i] != NULL)
{
MotorMgr_ResetAll(g_apstMotors[i]);
Rd_Delay(500);
MotorMgr_ActivateAll(g_apstMotors[i]);
Rd_Delay(500);
MotorMgr_SetHome(g_apstMotors[i]);
Rd_Delay(100);
MotorMgr_SpeedModeInit(g_apstMotors[i]);
}
}
while(1)
{
// 处理消息
MsgCenter_ProcessWait(g_uiMotorModuleID, 2);
for (int i = 0; i < MOTOR_INSTANCE_MAX; i++)
{
if (g_apstMotors[i] != NULL)
{
// 读取位置、速度、故障
MotorMgr_RequestPosition(g_apstMotors[i]);
MotorMgr_RequestFault(g_apstMotors[i]);
MotorMgr_RequestVelocity(g_apstMotors[i]);
}
}
Rd_Delay(2); // 2ms周期
}
}
/*==============================================*
* *
*==============================================*/
static void Motor_ModuleHandler(const Msg_t *pstMsg)
{
if (NULL == pstMsg)
{
return;
}
switch (pstMsg->m_uiMsgID)
{
case MOTOR_CMD_SET_SPEED:
{
if (pstMsg->m_uiDataLen >= sizeof(Motor_CmdData_t))
{
Motor_CmdData_t *pstData = (Motor_CmdData_t *)pstMsg->m_aucData;
if (pstData->m_ucMotorIndex < 2 && g_apstMotors[pstData->m_ucMotorIndex] != NULL)
{
MotorMgr_SetTargetSpeed(g_apstMotors[pstData->m_ucMotorIndex], pstData->m_iValue);
}
}
break;
}
case MOTOR_CMD_STOP:
{
for (int i = 0; i < 2; i++)
{
if (g_apstMotors[i] != NULL)
{
MotorMgr_SetTargetSpeed(g_apstMotors[i], 0);
}
}
break;
}
case MOTOR_CMD_SET_HOME:
{
if (pstMsg->m_uiDataLen >= sizeof(Motor_CmdData_t))
{
Motor_CmdData_t *pstData = (Motor_CmdData_t *)pstMsg->m_aucData;
if (pstData->m_ucMotorIndex < 2 && g_apstMotors[pstData->m_ucMotorIndex] != NULL)
{
MotorMgr_SetHome(g_apstMotors[pstData->m_ucMotorIndex]);
}
}
break;
}
case MOTOR_CMD_GET_STATUS:
{
// 回复状态给请求者
Motor_StatusData_t stStatus;
for (int i = 0; i < 2; i++)
{
if (g_apstMotors[i] != NULL)
{
const Motor_Data_t *pstData = MotorMgr_GetData(g_apstMotors[i]);
if (pstData != NULL)
{
stStatus.m_ucMotorIndex = i;
stStatus.m_iPosition = pstData->m_iRealPosition;
stStatus.m_iVelocity = pstData->m_iRealVelocity;
stStatus.m_uiFaultCode = pstData->m_uiFaultCode;
// 回复给请求者
MsgCenter_SendTo(MODULE_NAME_RBCORE, 0x10, &stStatus, sizeof(stStatus));
}
}
}
break;
}
default:
break;
}
}
void MotorInit(void)
{
// 初始化电机管理模块
MotorMgr_Init();
// 配置左轮电机
Motor_Config_t stLeftMotorConfig = {
.m_ucMotorID = 1,
.m_uiPulsePerRound = 10000,
.m_uiReductionRatio = 70,
.m_fWheelDiameter = 0.26f
};
g_apstMotors[0] = MotorMgr_Create(&stLeftMotorConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
// 配置右轮电机
Motor_Config_t stRightMotorConfig = {
.m_ucMotorID = 2,
.m_uiPulsePerRound = 10000,
.m_uiReductionRatio = 70,
.m_fWheelDiameter = 0.26f
};
g_apstMotors[1] = MotorMgr_Create(&stRightMotorConfig, g_ptFDCAN1, LeiSai_GetProtocol(), NULL);
g_uiMotorModuleID = MsgCenter_Register(MODULE_NAME_MOTOR, Motor_ModuleHandler);
// 创建电机任务
const osThreadAttr_t motor_task_attributes = {
.name = "motor_task",
.stack_size = 1024,
.priority = (osPriority_t) osPriorityHigh5,
};
(void)osThreadNew(MotorTask, NULL, &motor_task_attributes);
}

512
motor/motor_manager.c

@ -0,0 +1,512 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: motor_manager.c
: 稿
: radkil
: 2026713
:
:
:
1. : 2026713
: radkil
:
******************************************************************************/
#include "motor_manager.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
static rd_slist_t g_stMotorList; // 电机链表头
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
// 宏:检查协议函数是否存在并调用
#define MOTOR_PROTOCOL_CALL(pstMotor, func, ...) \
((pstMotor)->m_pstProtocol && (pstMotor)->m_pstProtocol->func) ? \
(pstMotor)->m_pstProtocol->func(pstMotor, ##__VA_ARGS__) : RD_NULL
/*****************************************************************************
: MotorMgr_Init
:
:
:
: void
:
:
:
1. : 2026713
: radkil
:
*****************************************************************************/
void MotorMgr_Init(void)
{
rd_slist_init(&g_stMotorList);
}
/*****************************************************************************
: MotorMgr_Create
:
: const Motor_Config_t *pstConfig
TComCtrl *ptCAN CAN控制器
const Motor_Protocol_t *pstProtocol
void *pstPrivData
:
: Motor_Instance_t*
:
:
:
1. : 2026713
: radkil
:
*****************************************************************************/
Motor_Instance_t* MotorMgr_Create(const Motor_Config_t *pstConfig,
TComCtrl *ptCAN,
const Motor_Protocol_t *pstProtocol,
void *pstPrivData)
{
if (NULL == pstConfig || NULL == ptCAN || NULL == pstProtocol)
{
return NULL;
}
// 检查是否已存在相同ID的电机
rd_slist_t *pos;
rd_slist_t *n;
rd_slist_for_each(pos, n, &g_stMotorList)
{
Motor_Instance_t *pstCheck = rd_slist_entry(pos, Motor_Instance_t, node);
if (pstCheck->m_stConfig.m_ucMotorID == pstConfig->m_ucMotorID)
{
return NULL; // ID重复
}
}
// 分配内存
Motor_Instance_t *pstMotor = (Motor_Instance_t *)RD_CALLOC(1, sizeof(Motor_Instance_t));
if (NULL == pstMotor)
{
return NULL;
}
// 初始化链表节点
pstMotor->node.next = NULL;
// 复制配置
pstMotor->m_stConfig.m_ucMotorID = pstConfig->m_ucMotorID;
pstMotor->m_stConfig.m_uiPulsePerRound = pstConfig->m_uiPulsePerRound > 0 ? pstConfig->m_uiPulsePerRound : 10000;
pstMotor->m_stConfig.m_uiReductionRatio = pstConfig->m_uiReductionRatio > 0 ? pstConfig->m_uiReductionRatio : 70;
pstMotor->m_stConfig.m_fWheelDiameter = pstConfig->m_fWheelDiameter > 0 ? pstConfig->m_fWheelDiameter : 0.26f;
// 初始化运行数据
pstMotor->m_stData.m_iRealPosition = 0;
pstMotor->m_stData.m_iRealVelocity = 0;
pstMotor->m_stData.m_iRealTorque = 0;
pstMotor->m_stData.m_uiFaultCode = 0;
pstMotor->m_stData.m_dRealDistance = 0.0;
pstMotor->m_stData.m_iStartMeasurePos = 0;
pstMotor->m_stData.m_iLastPosition = 0;
pstMotor->m_stData.m_iRoundCount = 0;
pstMotor->m_stData.m_ucStartMeasureFlag = 1;
// 绑定CAN控制器和协议
pstMotor->m_ptCAN = ptCAN;
pstMotor->m_eState = MOTOR_STATE_IDLE;
pstMotor->m_uiLastHeartbeat = 0;
pstMotor->m_pstProtocol = pstProtocol;
pstMotor->m_pstPrivData = pstPrivData;
// 设置实例名称
RD_SNPRINTF(pstMotor->m_szName, MOTOR_MAX_NAME_LEN, "Motor_%d", pstConfig->m_ucMotorID);
// 添加到链表尾部
rd_slist_append(&g_stMotorList, &pstMotor->node);
return pstMotor;
}
/*****************************************************************************
: MotorMgr_Destroy
:
: Motor_Instance_t *pstMotor
:
: int 00
:
:
:
1. : 2026713
: radkil
:
*****************************************************************************/
int MotorMgr_Destroy(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
// 从链表中移除
rd_slist_remove(&g_stMotorList, &pstMotor->node);
RD_FREE(pstMotor);
return RD_SUCCESS;
}
/*****************************************************************************
: MotorMgr_FindByName
:
: const char *pszName
:
: Motor_Instance_t*
:
:
:
1. : 2026713
: radkil
:
*****************************************************************************/
Motor_Instance_t* MotorMgr_FindByName(const char *pszName)
{
if (NULL == pszName)
{
return NULL;
}
rd_slist_t *pos;
rd_slist_t *n;
rd_slist_for_each(pos, n, &g_stMotorList)
{
Motor_Instance_t *pstMotor = rd_slist_entry(pos, Motor_Instance_t, node);
if (RD_STRCMP(pstMotor->m_szName, pszName) == 0)
{
return pstMotor;
}
}
return NULL;
}
/*****************************************************************************
: MotorMgr_FindByID
: ID查找电机实例
: uint8_t ucMotorID ID
:
: Motor_Instance_t*
:
:
:
1. : 2026713
: radkil
:
*****************************************************************************/
Motor_Instance_t* MotorMgr_FindByID(uint8_t ucMotorID)
{
rd_slist_t *pos;
rd_slist_t *n;
rd_slist_for_each(pos, n, &g_stMotorList)
{
Motor_Instance_t *pstMotor = rd_slist_entry(pos, Motor_Instance_t, node);
if (pstMotor->m_stConfig.m_ucMotorID == ucMotorID)
{
return pstMotor;
}
}
return NULL;
}
/*****************************************************************************
: MotorMgr_ResetAll
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_ResetAll(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfResetAll);
}
/*****************************************************************************
: MotorMgr_ActivateAll
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_ActivateAll(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfActivateAll);
}
/*****************************************************************************
: MotorMgr_SetHome
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_SetHome(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfSetHome);
}
/*****************************************************************************
: MotorMgr_SetWatchdog
:
: Motor_Instance_t *pstMotor
uint32_t uiTimeMs
:
: int 00
*****************************************************************************/
int MotorMgr_SetWatchdog(Motor_Instance_t *pstMotor, uint32_t uiTimeMs)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfSetWatchdog, uiTimeMs);
}
/*****************************************************************************
: MotorMgr_RequestPosition
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_RequestPosition(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfRequestPosition);
}
/*****************************************************************************
: MotorMgr_RequestVelocity
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_RequestVelocity(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfRequestVelocity);
}
/*****************************************************************************
: MotorMgr_RequestTorque
: /
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_RequestTorque(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfRequestTorque);
}
/*****************************************************************************
: MotorMgr_RequestFault
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_RequestFault(Motor_Instance_t *pstMotor)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfRequestFault);
}
/*****************************************************************************
: MotorMgr_SpeedModeInit
:
: Motor_Instance_t *pstMotor
:
: int 00
*****************************************************************************/
int MotorMgr_SpeedModeInit(Motor_Instance_t *pstMotor)
{
int iRet = MOTOR_PROTOCOL_CALL(pstMotor, pfSpeedModeInit);
if (iRet == RD_SUCCESS)
{
pstMotor->m_eState = MOTOR_STATE_READY;
}
return iRet;
}
/*****************************************************************************
: MotorMgr_SetTargetSpeed
:
: Motor_Instance_t *pstMotor
int32_t iTargetSpeed (/)
:
: int 00
*****************************************************************************/
int MotorMgr_SetTargetSpeed(Motor_Instance_t *pstMotor, int32_t iTargetSpeed)
{
int iRet = MOTOR_PROTOCOL_CALL(pstMotor, pfSetTargetSpeed, iTargetSpeed);
if (iRet == RD_SUCCESS)
{
pstMotor->m_eState = MOTOR_STATE_RUNNING;
}
return iRet;
}
/*****************************************************************************
: MotorMgr_PositionModeInit
:
: Motor_Instance_t *pstMotor
int32_t iAccel (/²)
int32_t iDecel (/²)
int32_t iTargetSpeed (/)
:
: int 00
*****************************************************************************/
int MotorMgr_PositionModeInit(Motor_Instance_t *pstMotor, int32_t iAccel, int32_t iDecel, int32_t iTargetSpeed)
{
int iRet = MOTOR_PROTOCOL_CALL(pstMotor, pfPositionModeInit, iAccel, iDecel, iTargetSpeed);
if (iRet == RD_SUCCESS)
{
pstMotor->m_eState = MOTOR_STATE_READY;
}
return iRet;
}
/*****************************************************************************
: MotorMgr_SetTargetPosition
:
: Motor_Instance_t *pstMotor
int32_t iTargetPos ()
:
: int 00
*****************************************************************************/
int MotorMgr_SetTargetPosition(Motor_Instance_t *pstMotor, int32_t iTargetPos)
{
int iRet = MOTOR_PROTOCOL_CALL(pstMotor, pfSetTargetPosition, iTargetPos);
if (iRet == RD_SUCCESS)
{
pstMotor->m_eState = MOTOR_STATE_RUNNING;
}
return iRet;
}
/*****************************************************************************
: MotorMgr_SetDO
:
: Motor_Instance_t *pstMotor
uint8_t ucDoIndex (12)
uint8_t ucState (01)
:
: int 00
*****************************************************************************/
int MotorMgr_SetDO(Motor_Instance_t *pstMotor, uint8_t ucDoIndex, uint8_t ucState)
{
return MOTOR_PROTOCOL_CALL(pstMotor, pfSetDO, ucDoIndex, ucState);
}
/*****************************************************************************
: MotorMgr_ParseResponse
: CAN响应数据
: uint8_t ucMotorID ID
const uint8_t *pucData
uint32_t uiLen
:
: void
*****************************************************************************/
void MotorMgr_ParseResponse(uint8_t ucMotorID, const uint8_t *pucData, uint32_t uiLen)
{
if (NULL == pucData || uiLen < 8)
{
return;
}
Motor_Instance_t *pstMotor = MotorMgr_FindByID(ucMotorID);
if (NULL == pstMotor)
{
return;
}
if (pstMotor->m_pstProtocol && pstMotor->m_pstProtocol->pfParseResponse)
{
pstMotor->m_pstProtocol->pfParseResponse(pstMotor, pucData, uiLen);
}
}
/*****************************************************************************
: MotorMgr_SpeedConvert
:
: Motor_Instance_t *pstMotor
int32_t iSpeedUserUnit
:
: int32_t /
*****************************************************************************/
int32_t MotorMgr_SpeedConvert(Motor_Instance_t *pstMotor, int32_t iSpeedUserUnit)
{
if (pstMotor->m_pstProtocol && pstMotor->m_pstProtocol->pfSpeedConvert)
{
return pstMotor->m_pstProtocol->pfSpeedConvert(pstMotor, iSpeedUserUnit);
}
return 0;
}
/*****************************************************************************
: MotorMgr_GetData
:
: Motor_Instance_t *pstMotor
:
: const Motor_Data_t*
*****************************************************************************/
const Motor_Data_t* MotorMgr_GetData(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return NULL;
}
return &pstMotor->m_stData;
}
/*****************************************************************************
: MotorMgr_GetState
:
: Motor_Instance_t *pstMotor
:
: Motor_State_e
*****************************************************************************/
Motor_State_e MotorMgr_GetState(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return MOTOR_STATE_IDLE;
}
return pstMotor->m_eState;
}

486
motor/msp_motor_leisai.c

@ -0,0 +1,486 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: msp_motor_leisai.c
: 稿
: radkil
: 2026713
:
: ISV2电机CAN协议实现
:
1. : 2026713
: radkil
:
******************************************************************************/
#include "msp_motor_leisai.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
static int LeiSai_SendSDO(Motor_Instance_t *pstMotor, uint8_t ucCmd,
uint16_t usIndex, uint8_t ucSubIndex,
int32_t iValue);
static void LeiSai_UpdateDistance(Motor_Instance_t *pstMotor);
static int LeiSai_Init(Motor_Instance_t *pstMotor);
static int LeiSai_ResetAll(Motor_Instance_t *pstMotor);
static int LeiSai_ActivateAll(Motor_Instance_t *pstMotor);
static int LeiSai_SetHome(Motor_Instance_t *pstMotor);
static int LeiSai_SetWatchdog(Motor_Instance_t *pstMotor, uint32_t uiTimeMs);
static int LeiSai_RequestPosition(Motor_Instance_t *pstMotor);
static int LeiSai_RequestVelocity(Motor_Instance_t *pstMotor);
static int LeiSai_RequestTorque(Motor_Instance_t *pstMotor);
static int LeiSai_RequestFault(Motor_Instance_t *pstMotor);
static int LeiSai_SpeedModeInit(Motor_Instance_t *pstMotor);
static int LeiSai_SetTargetSpeed(Motor_Instance_t *pstMotor, int32_t iTargetSpeed);
static int LeiSai_PositionModeInit(Motor_Instance_t *pstMotor, int32_t iAccel, int32_t iDecel, int32_t iTargetSpeed);
static int LeiSai_SetTargetPosition(Motor_Instance_t *pstMotor, int32_t iTargetPos);
static int LeiSai_SetDO(Motor_Instance_t *pstMotor, uint8_t ucDoIndex, uint8_t ucState);
static int LeiSai_ParseResponse(Motor_Instance_t *pstMotor, const uint8_t *pucData, uint32_t uiLen);
static int32_t LeiSai_SpeedConvert(Motor_Instance_t *pstMotor, int32_t iSpeedE01Mmin);
/*----------------------------------------------*
* *
*----------------------------------------------*/
// 雷赛协议操作函数表
const Motor_Protocol_t g_stLeiSaiProtocol = {
.m_szName = "LeiSai_ISV2",
.pfInit = LeiSai_Init,
.pfResetAll = LeiSai_ResetAll,
.pfActivateAll = LeiSai_ActivateAll,
.pfSetHome = LeiSai_SetHome,
.pfSetWatchdog = LeiSai_SetWatchdog,
.pfRequestPosition = LeiSai_RequestPosition,
.pfRequestVelocity = LeiSai_RequestVelocity,
.pfRequestTorque = LeiSai_RequestTorque,
.pfRequestFault = LeiSai_RequestFault,
.pfSpeedModeInit = LeiSai_SpeedModeInit,
.pfSetTargetSpeed = LeiSai_SetTargetSpeed,
.pfPositionModeInit = LeiSai_PositionModeInit,
.pfSetTargetPosition = LeiSai_SetTargetPosition,
.pfSetDO = LeiSai_SetDO,
.pfParseResponse = LeiSai_ParseResponse,
.pfSpeedConvert = LeiSai_SpeedConvert,
};
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*****************************************************************************
: LeiSai_GetProtocol
:
:
:
: const Motor_Protocol_t*
*****************************************************************************/
const Motor_Protocol_t* LeiSai_GetProtocol(void)
{
return &g_stLeiSaiProtocol;
}
/*****************************************************************************
: LeiSai_SendSDO
: SDO命令
*****************************************************************************/
static int LeiSai_SendSDO(Motor_Instance_t *pstMotor, uint8_t ucCmd,
uint16_t usIndex, uint8_t ucSubIndex,
int32_t iValue)
{
if (NULL == pstMotor || NULL == pstMotor->m_ptCAN)
{
return RD_NULL;
}
uint8_t aucData[8];
aucData[0] = ucCmd;
aucData[1] = (uint8_t)(usIndex & 0xFF);
aucData[2] = (uint8_t)((usIndex >> 8) & 0xFF);
aucData[3] = ucSubIndex;
aucData[4] = (uint8_t)(iValue & 0xFF);
aucData[5] = (uint8_t)((iValue >> 8) & 0xFF);
aucData[6] = (uint8_t)((iValue >> 16) & 0xFF);
aucData[7] = (uint8_t)((iValue >> 24) & 0xFF);
uint32_t uiFrameID = 0x600 + pstMotor->m_stConfig.m_ucMotorID;
return rd_ComIDSend(pstMotor->m_ptCAN, uiFrameID, (char *)aucData, 8);
}
/*****************************************************************************
: LeiSai_UpdateDistance
:
*****************************************************************************/
static void LeiSai_UpdateDistance(Motor_Instance_t *pstMotor)
{
double dCircleLength = 3.14 * pstMotor->m_stConfig.m_fWheelDiameter;
double dDeltaCounts = pstMotor->m_stData.m_iRealPosition - pstMotor->m_stData.m_iStartMeasurePos;
pstMotor->m_stData.m_dRealDistance = (dDeltaCounts / pstMotor->m_stConfig.m_uiPulsePerRound
/ pstMotor->m_stConfig.m_uiReductionRatio
+ (double)pstMotor->m_stData.m_iRoundCount)
* dCircleLength;
}
/*****************************************************************************
: LeiSai_Init
:
*****************************************************************************/
static int LeiSai_Init(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
pstMotor->m_eState = MOTOR_STATE_IDLE;
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_ResetAll
: NMT命令
*****************************************************************************/
static int LeiSai_ResetAll(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor || NULL == pstMotor->m_ptCAN)
{
return RD_NULL;
}
uint8_t aucData[2] = {0x81, 0x00};
return rd_ComIDSend(pstMotor->m_ptCAN, 0x000, (char *)aucData, 2);
}
/*****************************************************************************
: LeiSai_ActivateAll
: NMT命令
*****************************************************************************/
static int LeiSai_ActivateAll(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor || NULL == pstMotor->m_ptCAN)
{
return RD_NULL;
}
uint8_t aucData1[2] = {0x01, 0x01};
rd_ComIDSend(pstMotor->m_ptCAN, 0x000, (char *)aucData1, 2);
uint8_t aucData2[2] = {0x01, 0x02};
return rd_ComIDSend(pstMotor->m_ptCAN, 0x000, (char *)aucData2, 2);
}
/*****************************************************************************
: LeiSai_SetHome
:
*****************************************************************************/
static int LeiSai_SetHome(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_1B, LEISAI_OD_MODE_OF_OPERATION, 0x00, LEISAI_MODE_HOMING);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_1B, LEISAI_OD_HOMING_METHOD, 0x00, 0x23);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SHUTDOWN);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SWITCH_ON);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_ENABLE);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_START_MOVE);
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_SetWatchdog
:
*****************************************************************************/
static int LeiSai_SetWatchdog(Motor_Instance_t *pstMotor, uint32_t uiTimeMs)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_WATCHDOG_TIME, 0x06, (int32_t)uiTimeMs);
}
/*****************************************************************************
: LeiSai_RequestPosition
:
*****************************************************************************/
static int LeiSai_RequestPosition(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_READ, LEISAI_OD_POSITION_ACTUAL, 0x00, 0);
}
/*****************************************************************************
: LeiSai_RequestVelocity
:
*****************************************************************************/
static int LeiSai_RequestVelocity(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_READ, LEISAI_OD_VELOCITY_ACTUAL, 0x00, 0);
}
/*****************************************************************************
: LeiSai_RequestTorque
: /
*****************************************************************************/
static int LeiSai_RequestTorque(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_READ, LEISAI_OD_TORQUE_ACTUAL, 0x00, 0);
}
/*****************************************************************************
: LeiSai_RequestFault
:
*****************************************************************************/
static int LeiSai_RequestFault(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_READ, LEISAI_OD_FAULT_CODE, 0x00, 0);
}
/*****************************************************************************
: LeiSai_SpeedModeInit
:
*****************************************************************************/
static int LeiSai_SpeedModeInit(Motor_Instance_t *pstMotor)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SHUTDOWN);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SWITCH_ON);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_ENABLE);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_1B, LEISAI_OD_MODE_OF_OPERATION, 0x00, LEISAI_MODE_PROFILE_VEL);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_TARGET_VELOCITY, 0x00, 0);
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_SetTargetSpeed
:
*****************************************************************************/
static int LeiSai_SetTargetSpeed(Motor_Instance_t *pstMotor, int32_t iTargetSpeed)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_TARGET_VELOCITY, 0x00, iTargetSpeed);
}
/*****************************************************************************
: LeiSai_PositionModeInit
:
*****************************************************************************/
static int LeiSai_PositionModeInit(Motor_Instance_t *pstMotor, int32_t iAccel, int32_t iDecel, int32_t iTargetSpeed)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SHUTDOWN);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_SWITCH_ON);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_ENABLE);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_1B, LEISAI_OD_MODE_OF_OPERATION, 0x00, LEISAI_MODE_PROFILE_POS);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_ACCELERATION, 0x00, iAccel);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_DECELERATION, 0x00, iDecel);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_TARGET_VELOCITY, 0x00, iTargetSpeed);
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_SetTargetPosition
:
*****************************************************************************/
static int LeiSai_SetTargetPosition(Motor_Instance_t *pstMotor, int32_t iTargetPos)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, LEISAI_OD_TARGET_POSITION, 0x00, iTargetPos);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_RELATIVE_MOVE);
LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_2B, LEISAI_OD_CONTROL_WORD, 0x00, LEISAI_CTRL_START_MOVE);
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_SetDO
:
*****************************************************************************/
static int LeiSai_SetDO(Motor_Instance_t *pstMotor, uint8_t ucDoIndex, uint8_t ucState)
{
if (NULL == pstMotor)
{
return RD_NULL;
}
uint16_t usIndex = 0;
switch (ucDoIndex)
{
case 1:
usIndex = 0x2410;
break;
case 2:
usIndex = 0x2411;
break;
default:
return RD_INVALUE;
}
return LeiSai_SendSDO(pstMotor, LEISAI_SDO_CMD_WRITE_4B, usIndex, 0x00, ucState ? 1 : 0);
}
/*****************************************************************************
: LeiSai_ParseResponse
: CAN响应数据
*****************************************************************************/
static int LeiSai_ParseResponse(Motor_Instance_t *pstMotor, const uint8_t *pucData, uint32_t uiLen)
{
if (NULL == pstMotor || NULL == pucData || uiLen < 8)
{
return RD_NULL;
}
uint16_t usFunctionCode = (uint16_t)(pucData[1] | (pucData[2] << 8));
switch (usFunctionCode)
{
case LEISAI_OD_POSITION_ACTUAL:
{
pstMotor->m_stData.m_iRealPosition = (int32_t)(pucData[4]
| (pucData[5] << 8)
| (pucData[6] << 16)
| (pucData[7] << 24));
if (pstMotor->m_stData.m_ucStartMeasureFlag == 1)
{
pstMotor->m_stData.m_ucStartMeasureFlag = 0;
pstMotor->m_stData.m_iRoundCount = 0;
pstMotor->m_stData.m_iStartMeasurePos = pstMotor->m_stData.m_iRealPosition;
pstMotor->m_stData.m_iLastPosition = pstMotor->m_stData.m_iRealPosition;
}
else
{
if (abs(pstMotor->m_stData.m_iRealPosition - pstMotor->m_stData.m_iLastPosition) >= 0x3FFFFFFF)
{
if (pstMotor->m_stData.m_iRealPosition > 0)
{
pstMotor->m_stData.m_iRoundCount -= 1;
}
else
{
pstMotor->m_stData.m_iRoundCount += 1;
}
}
}
pstMotor->m_stData.m_iLastPosition = pstMotor->m_stData.m_iRealPosition;
LeiSai_UpdateDistance(pstMotor);
break;
}
case LEISAI_OD_FAULT_CODE:
{
pstMotor->m_stData.m_uiFaultCode = (uint32_t)(pucData[4]
| (pucData[5] << 8)
| (pucData[6] << 16)
| (pucData[7] << 24));
if (pstMotor->m_stData.m_uiFaultCode != 0)
{
pstMotor->m_eState = MOTOR_STATE_ERROR;
}
break;
}
case LEISAI_OD_VELOCITY_ACTUAL:
{
pstMotor->m_stData.m_iRealVelocity = (int32_t)(pucData[4]
| (pucData[5] << 8)
| (pucData[6] << 16)
| (pucData[7] << 24));
break;
}
case LEISAI_OD_TORQUE_ACTUAL:
{
pstMotor->m_stData.m_iRealTorque = (int32_t)(pucData[4]
| (pucData[5] << 8)
| (pucData[6] << 16)
| (pucData[7] << 24));
break;
}
default:
break;
}
return RD_SUCCESS;
}
/*****************************************************************************
: LeiSai_SpeedConvert
: 0.1m/min -> /
*****************************************************************************/
static int32_t LeiSai_SpeedConvert(Motor_Instance_t *pstMotor, int32_t iSpeedE01Mmin)
{
if (NULL == pstMotor)
{
return 0;
}
double dSpeedMs = iSpeedE01Mmin * 0.1 / 60.0;
double dWheelCircumference = 3.14 * pstMotor->m_stConfig.m_fWheelDiameter;
double dPulsePerSec = dSpeedMs / dWheelCircumference
* pstMotor->m_stConfig.m_uiReductionRatio
* pstMotor->m_stConfig.m_uiPulsePerRound;
return (int32_t)dPulsePerSec;
}

2
optional/msp_MK32.c

@ -17,7 +17,7 @@
******************************************************************************/ ******************************************************************************/
#include "msp_MK32.h" #include "msp_MK32.h"
#include "BHBF_robot.h" #include "BHBF.h"
#include <math.h> #include <math.h>

2
optional/msp_TI5MOTOR.c

@ -17,7 +17,7 @@
******************************************************************************/ ******************************************************************************/
#include "msp_TI5MOTOR.h" #include "msp_TI5MOTOR.h"
#include "BHBF_robot.h" #include "BHBF.h"
/*----------------------------------------------* /*----------------------------------------------*
* * * *

5
project/RBcore/CMakeLists.txt → project/paint_robot_new/CMakeLists.txt

@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
get_filename_component(TARGET_NAME "${CMAKE_CURRENT_SOURCE_DIR}" NAME)
set(COMMON_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../library/CMakeLists.txt") set(COMMON_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../library/CMakeLists.txt")
if(EXISTS ${COMMON_CMAKE_PATH}) if(EXISTS ${COMMON_CMAKE_PATH})
@ -9,7 +10,7 @@ else()
endif() endif()
if(TARGET bspMCU) if(TARGET bspMCU)
target_link_libraries(RBcore PUBLIC bspMCU) target_link_libraries(${TARGET_NAME} PUBLIC bspMCU)
else() else()
message(WARNING "[RBcore] Dependency 'bspMCU' not found.") message(FATAL_ERROR "[${TARGET_NAME}] Dependency 'bspMCU' not found.")
endif() endif()

39
project/RBcore/include/BHBF_robot.h → project/paint_robot_new/include/paint_robot_new.h

@ -3,15 +3,15 @@
(C), 2018-2099, Radkil (C), 2018-2099, Radkil
****************************************************************************** ******************************************************************************
: BHBF_robot.h : paint_robot_new.h
: 稿 : 稿
: radkil : radkil
: 202668 : 2026714
: :
: BHBF_robot.c : paint_robot_new.c
: :
1. : 202668 1. : 2026714
: radkil : radkil
: :
@ -45,8 +45,8 @@
* * * *
*----------------------------------------------*/ *----------------------------------------------*/
#ifndef __BHBF_ROBOT_H__ #ifndef __PAINT_ROBOT_NEW_H__
#define __BHBF_ROBOT_H__ #define __PAINT_ROBOT_NEW_H__
#ifdef __cplusplus #ifdef __cplusplus
@ -59,27 +59,14 @@ extern "C"{
/*==============================================* /*==============================================*
* include header files * * include header files *
*----------------------------------------------*/ *----------------------------------------------*/
#include "drv_interface.h"
#include "rd_time.h"
/*==============================================* /*==============================================*
* constants or macros define * * constants or macros define *
*----------------------------------------------*/ *----------------------------------------------*/
typedef enum {
GF_CMD_DEFAULT_NULL = 0,
GF_CMD_STOP_ALL,
GF_CMD_MANUAL_FORWARD,
GF_CMD_MANUAL_BACKWARD,
GF_CMD_AUTO_FORWARD
} GF_CMD;
typedef struct _GV_struct_define
{
int m_iWorkMode;
GF_CMD m_eGFCmd;
int32_t m_iMoveSpeed[2];//索引1对应左轮,索引2对应右轮
} GV_struct_define;
/*==============================================* /*==============================================*
* project-wide global variables * * project-wide global variables *
@ -90,11 +77,7 @@ typedef struct _GV_struct_define
/*==============================================* /*==============================================*
* routines' or functions' implementations * * routines' or functions' implementations *
*----------------------------------------------*/ *----------------------------------------------*/
// 待实现接口
void MK32_Init(void);
GF_CMD MK32_Task(int mode);
void MoveWheel_Init(void);
void MoveWheel_Task(int32_t Target_Velcity[]);
#ifdef __cplusplus #ifdef __cplusplus
#if __cplusplus #if __cplusplus
@ -103,4 +86,4 @@ void MoveWheel_Task(int32_t Target_Velcity[]);
#endif /* __cplusplus */ #endif /* __cplusplus */
#endif /* __BHBF_ROBOT_H__ */ #endif /* __PAINT_ROBOT_NEW_H__ */

50
project/paint_robot_new/paint_robot_new.c

@ -0,0 +1,50 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: paint_robot_new.c
: 稿
: radkil
: 2026714
:
:
:
1. : 2026714
: radkil
:
******************************************************************************/
#include "paint_robot_new.h"
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
Loading…
Cancel
Save