You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
19 KiB

/******************************************************************************
(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;
}