/**
******************************************************************************
* @file user_interface.c
* @author Motor Control SDK Team, ST Microelectronics
* @brief This file provides firmware functions that implement the following features
* of the user interface component of the Motor Control SDK.
******************************************************************************
* @attention
*
*
© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Pre-compiler coherency check */
#include "mc_type.h"
#include "mc_math.h"
#include "mc_config.h"
#include "user_interface.h"
/** @addtogroup MCSDK
* @{
*/
/** @defgroup MCUI Motor Control User Interface
* @brief User Interface Components of the Motor Control SDK
*
* These components aim at connecting the Application with the outside. There are two categories
* of UI Componentes:
*
* - Some connect the application with the Motor Conrol Monitor tool via a UART link. The Motor
* Control Monitor can control the motor(s) driven by the application and also read and write
* internal variables of the Motor Control subsystem.
* - Others UI components allow for using the DAC(s) peripherals in
* order to output internal variables of the Motor Control subsystem for debug purposes.
*
* @{
*/
/**
* @brief Initialize the user interface component.
*
* Perform the link between the UI, MC interface and MC tuning components.
* @param pHandle: Pointer on Handle structure of UI component.
* @param bMCNum Number of MC instance present in the list.
* @param pMCI Pointer on the list of MC interface component to inked with UI.
* @param pMCT Pointer on the list of MC tuning component to inked with UI.
* @param pUICfg Pointer on the user interface configuration list.
* Each element of the list must be a bit field containing one (or more) of
* the exported configuration option UI_CFGOPT_xxx (eventually OR-ed).
* @retval none.
*/
__weak void UI_Init(UI_Handle_t *pHandle, uint8_t bMCNum, MCI_Handle_t ** pMCI, MCT_Handle_t** pMCT, uint32_t* pUICfg)
{
pHandle->bDriveNum = bMCNum;
pHandle->pMCI = pMCI;
pHandle->pMCT = pMCT;
pHandle->bSelectedDrive = 0u;
pHandle->pUICfg = pUICfg;
}
/**
* @brief Allow to select the MC on which UI operates.
* @param pHandle: Pointer on Handle structure of UI component.
* @param bSelectMC: The new selected MC, zero based, on which UI operates.
* @retval Boolean set to true if the bSelectMC is valid oterwise return false.
*/
__weak bool UI_SelectMC(UI_Handle_t *pHandle,uint8_t bSelectMC)
{
bool retVal = true;
if (bSelectMC >= pHandle->bDriveNum)
{
retVal = false;
}
else
{
pHandle->bSelectedDrive = bSelectMC;
}
return retVal;
}
/**
* @brief Allow to retrieve the MC on which UI currently operates.
* @param pHandle: Pointer on Handle structure of UI component.
* @retval Return the currently selected MC, zero based, on which UI operates.
*/
__weak uint8_t UI_GetSelectedMC(UI_Handle_t *pHandle)
{
return (pHandle->bSelectedDrive);
}
/**
* @brief Retrieve the configuration of the MC on which UI currently operates.
* @param pHandle: Pointer on Handle structure of UI component.
* @retval Return the currently configuration of selected MC on which UI operates.
* It represents a bit field containing one (or more) of
* the exported configuration option UI_CFGOPT_xxx (eventually OR-ed).
*/
__weak uint32_t UI_GetSelectedMCConfig(UI_Handle_t *pHandle)
{
return pHandle->pUICfg[pHandle->bSelectedDrive];
}
/**
* @brief Allow to execute a SetReg command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param bRegID: Code of register to update.
* See MC_PROTOCOL_REG_xxx for code definition.
* @param wValue: New value to set.
* @retval Return the currently selected MC, zero based, on which UI operates.
*/
__weak bool UI_SetReg(UI_Handle_t *pHandle, MC_Protocol_REG_t bRegID, int32_t wValue)
{
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
MCT_Handle_t * pMCT = pHandle->pMCT[pHandle->bSelectedDrive];
bool retVal = true;
switch (bRegID)
{
case MC_PROTOCOL_REG_TARGET_MOTOR:
{
retVal = UI_SelectMC(pHandle,(uint8_t)wValue);
}
break;
case MC_PROTOCOL_REG_RAMP_FINAL_SPEED:
{
MCI_ExecSpeedRamp(pMCI,(int16_t)((wValue*SPEED_UNIT)/_RPM),0);
}
break;
case MC_PROTOCOL_REG_SPEED_KP:
{
PID_SetKP(pMCT->pPIDSpeed,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_SPEED_KI:
{
PID_SetKI(pMCT->pPIDSpeed,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_SPEED_KD:
{
PID_SetKD(pMCT->pPIDSpeed,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_CONTROL_MODE:
{
if ((STC_Modality_t)wValue == STC_TORQUE_MODE)
{
MCI_ExecTorqueRamp(pMCI, MCI_GetTeref(pMCI),0);
}
if ((STC_Modality_t)wValue == STC_SPEED_MODE)
{
MCI_ExecSpeedRamp(pMCI, MCI_GetMecSpeedRefUnit(pMCI),0);
}
}
break;
case MC_PROTOCOL_REG_TORQUE_REF:
{
qd_t currComp;
currComp = MCI_GetIqdref(pMCI);
currComp.q = (int16_t)wValue;
MCI_SetCurrentReferences(pMCI,currComp);
}
break;
case MC_PROTOCOL_REG_TORQUE_KP:
{
PID_SetKP(pMCT->pPIDIq,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_TORQUE_KI:
{
PID_SetKI(pMCT->pPIDIq,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_TORQUE_KD:
{
PID_SetKD(pMCT->pPIDIq,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_FLUX_REF:
{
qd_t currComp;
currComp = MCI_GetIqdref(pMCI);
currComp.d = (int16_t)wValue;
MCI_SetCurrentReferences(pMCI,currComp);
}
break;
case MC_PROTOCOL_REG_FLUX_KP:
{
PID_SetKP(pMCT->pPIDId,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_FLUX_KI:
{
PID_SetKI(pMCT->pPIDId,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_FLUX_KD:
{
PID_SetKD(pMCT->pPIDId,(int16_t)wValue);
}
break;
case MC_PROTOCOL_REG_IQ_SPEEDMODE:
{
MCI_SetIdref(pMCI,(int16_t)wValue);
}
break;
default:
retVal = false;
break;
}
return retVal;
}
/* Used to execute a GetReg command coming from the user. */
__weak int32_t UI_GetReg(UI_Handle_t *pHandle, MC_Protocol_REG_t bRegID, bool * success)
{
MCT_Handle_t* pMCT = pHandle->pMCT[pHandle->bSelectedDrive];
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
int32_t bRetVal = 0;
if ( success != (bool *) 0 )
{
*success = true;
}
switch (bRegID)
{
case MC_PROTOCOL_REG_TARGET_MOTOR:
{
bRetVal = (int32_t)UI_GetSelectedMC(pHandle);
}
break;
case MC_PROTOCOL_REG_FLAGS:
{
bRetVal = (int32_t)STM_GetFaultState(pMCT->pStateMachine);
}
break;
case MC_PROTOCOL_REG_STATUS:
{
bRetVal = (int32_t)STM_GetState(pMCT->pStateMachine);
}
break;
case MC_PROTOCOL_REG_SPEED_REF:
{
bRetVal = (int32_t)((MCI_GetMecSpeedRefUnit(pMCI)*_RPM)/SPEED_UNIT);
}
break;
case MC_PROTOCOL_REG_SPEED_KP:
{
bRetVal = (int32_t)PID_GetKP(pMCT->pPIDSpeed);
}
break;
case MC_PROTOCOL_REG_SPEED_KI:
{
bRetVal = (int32_t)PID_GetKI(pMCT->pPIDSpeed);
}
break;
case MC_PROTOCOL_REG_SPEED_KD:
{
bRetVal = (int32_t)PID_GetKD(pMCT->pPIDSpeed);
}
break;
case MC_PROTOCOL_REG_BUS_VOLTAGE:
{
bRetVal = (int32_t)VBS_GetAvBusVoltage_V(pMCT->pBusVoltageSensor);
}
break;
case MC_PROTOCOL_REG_HEATS_TEMP:
{
bRetVal = (int32_t)NTC_GetAvTemp_C(pMCT->pTemperatureSensor);
}
break;
case MC_PROTOCOL_REG_SPEED_MEAS:
{
bRetVal = (int32_t)((MCI_GetAvrgMecSpeedUnit(pMCI) * _RPM)/SPEED_UNIT);
}
break;
case MC_PROTOCOL_REG_UID:
{
bRetVal = (int32_t)(MC_UID);
}
break;
case MC_PROTOCOL_REG_CTRBDID:
{
bRetVal = CTRBDID;
}
break;
case MC_PROTOCOL_REG_PWBDID:
{
bRetVal = PWBDID;
}
break;
case MC_PROTOCOL_REG_PWBDID2:
{
bRetVal = (uint32_t) 0;
}
break;
case MC_PROTOCOL_REG_TORQUE_REF:
{
qd_t currComp;
currComp = MCI_GetIqdref(pMCI);
bRetVal = (int32_t)currComp.q;
}
break;
case MC_PROTOCOL_REG_FLUX_REF:
{
qd_t currComp;
currComp = MCI_GetIqdref(pMCI);
bRetVal = (int32_t)currComp.d;
}
break;
case MC_PROTOCOL_REG_CONTROL_MODE:
{
bRetVal = (int32_t)MCI_GetControlMode(pMCI);
}
break;
case MC_PROTOCOL_REG_RAMP_FINAL_SPEED:
{
if (MCI_GetControlMode(pMCI) == STC_SPEED_MODE)
{
bRetVal = (int32_t)((MCI_GetLastRampFinalSpeed(pMCI) * _RPM)/SPEED_UNIT) ;
}
else
{
bRetVal = (int32_t)((MCI_GetMecSpeedRefUnit(pMCI) * _RPM)/SPEED_UNIT) ;
}
}
break;
case MC_PROTOCOL_REG_SPEED_KP_DIV:
{
bRetVal = (int32_t)PID_GetKPDivisor(pMCT->pPIDSpeed);
}
break;
case MC_PROTOCOL_REG_SPEED_KI_DIV:
{
bRetVal = (int32_t)PID_GetKIDivisor(pMCT->pPIDSpeed);
}
break;
case MC_PROTOCOL_REG_TORQUE_KP:
{
bRetVal = (int32_t)PID_GetKP(pMCT->pPIDIq);
}
break;
case MC_PROTOCOL_REG_TORQUE_KI:
{
bRetVal = (int32_t)PID_GetKI(pMCT->pPIDIq);
}
break;
case MC_PROTOCOL_REG_TORQUE_KD:
{
bRetVal = (int32_t)PID_GetKD(pMCT->pPIDIq);
}
break;
case MC_PROTOCOL_REG_IQ_SPEEDMODE:
{
qd_t currComp;
currComp = MCI_GetIqdref(pMCI);
bRetVal = (int32_t)currComp.d;
}
break;
case MC_PROTOCOL_REG_FLUX_KP:
{
bRetVal = (int32_t)PID_GetKP(pMCT->pPIDId);
}
break;
case MC_PROTOCOL_REG_FLUX_KI:
{
bRetVal = (int32_t)PID_GetKI(pMCT->pPIDId);
}
break;
case MC_PROTOCOL_REG_FLUX_KD:
{
bRetVal = (int32_t)PID_GetKD(pMCT->pPIDId);
}
break;
case MC_PROTOCOL_REG_MOTOR_POWER:
{
bRetVal = MPM_GetAvrgElMotorPowerW(pMCT->pMPM);
}
break;
case MC_PROTOCOL_REG_MEAS_EL_ANGLE:
{
uint32_t hUICfg = pHandle->pUICfg[pHandle->bSelectedDrive];
SpeednPosFdbk_Handle_t* pSPD = MC_NULL;
if ((MAIN_SCFG_VALUE(hUICfg) == UI_SCODE_ENC) ||
(MAIN_SCFG_VALUE(hUICfg) == UI_SCODE_HALL))
{
pSPD = pMCT->pSpeedSensorMain;
}
if ((AUX_SCFG_VALUE(hUICfg) == UI_SCODE_ENC) ||
(AUX_SCFG_VALUE(hUICfg) == UI_SCODE_HALL))
{
pSPD = pMCT->pSpeedSensorAux;
}
if (pSPD != MC_NULL)
{
bRetVal = SPD_GetElAngle(pSPD);
}
}
break;
case MC_PROTOCOL_REG_MEAS_ROT_SPEED:
{
uint32_t hUICfg = pHandle->pUICfg[pHandle->bSelectedDrive];
SpeednPosFdbk_Handle_t* pSPD = MC_NULL;
if ((MAIN_SCFG_VALUE(hUICfg) == UI_SCODE_ENC) ||
(MAIN_SCFG_VALUE(hUICfg) == UI_SCODE_HALL))
{
pSPD = pMCT->pSpeedSensorMain;
}
if ((AUX_SCFG_VALUE(hUICfg) == UI_SCODE_ENC) ||
(AUX_SCFG_VALUE(hUICfg) == UI_SCODE_HALL))
{
pSPD = pMCT->pSpeedSensorAux;
}
if (pSPD != MC_NULL)
{
bRetVal = SPD_GetS16Speed(pSPD);
}
}
break;
case MC_PROTOCOL_REG_MAX_APP_SPEED:
{
bRetVal = (STC_GetMaxAppPositiveMecSpeedUnit(pMCT->pSpeednTorqueCtrl) * _RPM)/SPEED_UNIT ;
}
break;
case MC_PROTOCOL_REG_MIN_APP_SPEED:
{
bRetVal = (STC_GetMinAppNegativeMecSpeedUnit(pMCT->pSpeednTorqueCtrl) * _RPM)/SPEED_UNIT ;
}
break;
case MC_PROTOCOL_REG_TORQUE_MEAS:
case MC_PROTOCOL_REG_I_Q:
{
bRetVal = MCI_GetIqd(pMCI).q;
}
break;
case MC_PROTOCOL_REG_FLUX_MEAS:
case MC_PROTOCOL_REG_I_D:
{
bRetVal = MCI_GetIqd(pMCI).d;
}
break;
case MC_PROTOCOL_REG_RUC_STAGE_NBR:
{
if (pMCT->pRevupCtrl)
{
bRetVal = (int32_t)RUC_GetNumberOfPhases(pMCT->pRevupCtrl);
}
else
{
bRetVal = (uint32_t) 0;
}
}
break;
case MC_PROTOCOL_REG_I_A:
{
bRetVal = MCI_GetIab(pMCI).a;
}
break;
case MC_PROTOCOL_REG_I_B:
{
bRetVal = MCI_GetIab(pMCI).b;
}
break;
case MC_PROTOCOL_REG_I_ALPHA:
{
bRetVal = MCI_GetIalphabeta(pMCI).alpha;
}
break;
case MC_PROTOCOL_REG_I_BETA:
{
bRetVal = MCI_GetIalphabeta(pMCI).beta;
}
break;
case MC_PROTOCOL_REG_I_Q_REF:
{
bRetVal = MCI_GetIqdref(pMCI).q;
}
break;
case MC_PROTOCOL_REG_I_D_REF:
{
bRetVal = MCI_GetIqdref(pMCI).d;
}
break;
case MC_PROTOCOL_REG_V_Q:
{
bRetVal = MCI_GetVqd(pMCI).q;
}
break;
case MC_PROTOCOL_REG_V_D:
{
bRetVal = MCI_GetVqd(pMCI).d;
}
break;
case MC_PROTOCOL_REG_V_ALPHA:
{
bRetVal = MCI_GetValphabeta(pMCI).alpha;
}
break;
case MC_PROTOCOL_REG_V_BETA:
{
bRetVal = MCI_GetValphabeta(pMCI).beta;
}
break;
default:
{
if ( success != (bool *) 0 )
{
*success = false;
}
}
break;
}
return bRetVal;
}
/**
* @brief Allow to execute a command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param bCmdID: Code of command to execute.
* See MC_PROTOCOL_CMD_xxx for code definition.
* @retval Return true if the command executed succesfully, otherwise false.
*/
__weak bool UI_ExecCmd(UI_Handle_t *pHandle, uint8_t bCmdID)
{
bool retVal = true;
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
switch (bCmdID)
{
case MC_PROTOCOL_CMD_START_MOTOR:
{
/* Call MCI Start motor; */
MCI_StartMotor(pMCI);
}
break;
case MC_PROTOCOL_CMD_STOP_MOTOR:
case MC_PROTOCOL_CMD_SC_STOP:
{
/* Call MCI Stop motor; */
MCI_StopMotor(pMCI);
}
break;
case MC_PROTOCOL_CMD_STOP_RAMP:
{
if (MCI_GetSTMState(pMCI) == RUN)
{
MCI_StopRamp(pMCI);
}
}
break;
case MC_PROTOCOL_CMD_PING:
{
/* Do nothing at the moment */
}
break;
case MC_PROTOCOL_CMD_START_STOP:
{
/* Queries the STM and a command start or stop depending on the state. */
if (MCI_GetSTMState(pMCI) == IDLE)
{
MCI_StartMotor(pMCI);
}
else
{
MCI_StopMotor(pMCI);
}
}
break;
case MC_PROTOCOL_CMD_RESET:
{
/* Do nothing at the moment */
}
break;
case MC_PROTOCOL_CMD_FAULT_ACK:
{
MCI_FaultAcknowledged(pMCI);
}
break;
case MC_PROTOCOL_CMD_ENCODER_ALIGN:
{
MCI_EncoderAlign(pMCI);
}
break;
case MC_PROTOCOL_CMD_IQDREF_CLEAR:
{
MCI_Clear_Iqdref(pMCI);
}
break;
default:
{
retVal = false;
}
break;
}
return retVal;
}
/**
* @brief Allow to execute a speed ramp command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param wFinalMecSpeedUnit: Final speed value expressed in the unit defined by #SPEED_UNIT.
* @param hDurationms: Duration of the ramp expressed in milliseconds.
* It is possible to set 0 to perform an instantaneous change in the value.
* @retval Return true if the command executed succesfully, otherwise false.
*/
__weak bool UI_ExecSpeedRamp(UI_Handle_t *pHandle, int32_t wFinalMecSpeedUnit, uint16_t hDurationms)
{
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
/* Call MCI Exec Ramp */
MCI_ExecSpeedRamp(pMCI,(int16_t)((wFinalMecSpeedUnit*SPEED_UNIT)/_RPM),hDurationms);
return true;
}
/**
* @brief It is used to execute a torque ramp command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param hTargetFinal: final torque value. See MCI interface for more
details.
* @param hDurationms: the duration of the ramp expressed in milliseconds. It
* is possible to set 0 to perform an instantaneous change in the value.
* @retval Return true if the command executed succesfully, otherwise false.
*/
__weak bool UI_ExecTorqueRamp(UI_Handle_t *pHandle, int16_t hTargetFinal, uint16_t hDurationms)
{
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
/* Call MCI Exec Ramp */
MCI_ExecTorqueRamp(pMCI,hTargetFinal,hDurationms);
return true;
}
/**
* @brief Executes a get Revup data command coming from the user
*
* @param pHandle Pointer on Handle structure of UI component.
* @param bStage Rev up phase to be read (zero based).
* @param pDurationms Pointer to an uint16_t variable used to retrieve
* the duration of the Revup stage.
* @param pFinalMecSpeedUnit Pointer to an int16_t variable used to
* retrieve the mechanical speed at the end of that stage. Expressed in
* the unit defined by #SPEED_UNIT.
* @param pFinalTorque Pointer to an int16_t variable used to
* retrieve the value of motor torque at the end of that stage.
* This value represents actually the Iq current expressed in digit.
*
* @retval Returns true if the command executed successfully, false otherwise.
*/
__weak bool UI_GetRevupData(UI_Handle_t *pHandle, uint8_t bStage, uint16_t* pDurationms,
int16_t* pFinalMecSpeedUnit, int16_t* pFinalTorque )
{
bool hRetVal = true;
RevUpCtrl_Handle_t *pRevupCtrl = pHandle->pMCT[pHandle->bSelectedDrive]->pRevupCtrl;
if (pRevupCtrl)
{
*pDurationms = RUC_GetPhaseDurationms(pRevupCtrl, bStage);
*pFinalMecSpeedUnit = RUC_GetPhaseFinalMecSpeedUnit(pRevupCtrl, bStage);
*pFinalTorque = RUC_GetPhaseFinalTorque(pRevupCtrl, bStage);
}
else
{
hRetVal = false;
}
return hRetVal;
}
/**
* @brief It is used to execute a set Revup data command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param bStage: is the rev up phase, zero based, to be modified.
* @param hDurationms: is the new duration of the Revup stage.
* @param hFinalMecSpeedUnit: is the new mechanical speed at the end of that
* stage expressed in the unit defined by SPEED_UNIT.
* @param hFinalTorque: is the new value of motor torque at the end of that
* stage. This value represents actually the Iq current expressed in
* digit.
* @retval Return true if the command executed successfully, otherwise false.
*/
__weak bool UI_SetRevupData(UI_Handle_t *pHandle, uint8_t bStage, uint16_t hDurationms,
int16_t hFinalMecSpeedUnit, int16_t hFinalTorque )
{
RevUpCtrl_Handle_t *pRevupCtrl = pHandle->pMCT[pHandle->bSelectedDrive]->pRevupCtrl;
RUC_SetPhaseDurationms(pRevupCtrl, bStage, hDurationms);
RUC_SetPhaseFinalMecSpeedUnit(pRevupCtrl, bStage, hFinalMecSpeedUnit);
RUC_SetPhaseFinalTorque(pRevupCtrl, bStage, hFinalTorque);
return true;
}
/**
* @brief Allow to execute a set current reference command coming from the user.
* @param pHandle: Pointer on Handle structure of UI component.
* @param hIqRef: Current Iq reference on qd reference frame.
* This value is expressed in digit.
* @note current convertion formula (from digit to Amps):
* Current(Amps) = [Current(digit) * Vdd micro] / [65536 * Rshunt * Aop]
* @param hIdRef: Current Id reference on qd reference frame.
* This value is expressed in digit. See hIqRef param description.
* @retval none.
*/
__weak void UI_SetCurrentReferences(UI_Handle_t *pHandle, int16_t hIqRef, int16_t hIdRef)
{
MCI_Handle_t * pMCI = pHandle->pMCI[pHandle->bSelectedDrive];
qd_t currComp;
currComp.q = hIqRef;
currComp.d = hIdRef;
MCI_SetCurrentReferences(pMCI,currComp);
}
/**
* @brief Allow to get information about MP registers available for each step.
* PC send to the FW the list of steps to get the available registers.
* The FW returs the list of available registers for that steps.
* @param stepList: List of requested steps.
* @param pMPInfo: The returned list of register.
* It is populated by this function.
* @retval true if MP is enabled, false otherwise.
*/
__weak bool UI_GetMPInfo(pMPInfo_t stepList, pMPInfo_t pMPInfo)
{
return false;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT 2019 STMicroelectronics *****END OF FILE****/