单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
主函数
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_ADC2_Init();
MX_TIM1_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_TIM8_Init();
MX_USART1_UART_Init();
MX_MotorControl_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of mediumFrequency */
osThreadDef(mediumFrequency, startMediumFrequencyTask, osPriorityNormal, 0, 128);
mediumFrequencyHandle = osThreadCreate(osThread(mediumFrequency), NULL);
/* definition and creation of safety */
osThreadDef(safety, StartSafetyTask, osPriorityAboveNormal, 0, 128);
safetyHandle = osThreadCreate(osThread(safety), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 168;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
}
启动:
void EXTI4_IRQHandler (void)
{
/* USER CODE BEGIN START_STOP_BTN */
if ( LL_EXTI_ReadFlag_0_31(LL_EXTI_LINE_4) )
{
LL_EXTI_ClearFlag_0_31 (LL_EXTI_LINE_4);
UI_HandleStartStopButton_cb ();
}
}
因为不用上位机,UI_TaskInit用不着。
__weak void MX_MotorControl_Init(void)
{
/* Initialize the Motor Control Subsystem */
MCboot(pMCI,pMCT);
mc_lock_pins();
// /* Initialize the MC User Interface */
// UI_TaskInit(wConfig,NBR_OF_MOTORS,pMCI,pMCT,s_fwVer);
}
这样,
user_interface.c
revup_ctrl.c
没什么作用。
typedef struct
{
STM_Handle_t * pSTM; /*!< State machine object used by MCI.*/
SpeednTorqCtrl_Handle_t * pSTC; /*!< Speed and torque controller object used by MCI.*/
pFOCVars_t pFOCVars; /*!< Pointer to FOC vars used by MCI.*/
MCI_UserCommands_t lastCommand; /*!< Last command coming from the user.*/
int16_t hFinalSpeed; /*!< Final speed of last ExecSpeedRamp command.*/
int16_t hFinalTorque; /*!< Final torque of last ExecTorqueRamp
command.*/
qd_t Iqdref; /*!< Current component of last
SetCurrentReferences command.*/
uint16_t hDurationms; /*!< Duration in ms of last ExecSpeedRamp or
ExecTorqueRamp command.*/
MCI_CommandState_t CommandState; /*!< The status of the buffered command.*/
STC_Modality_t LastModalitySetByUser; /*!< The last STC_Modality_t set by the
user. */
} MCI_Handle_t;
电机的状态:
typedef struct
{
State_t bState; /*!< Variable containing state machine current
state */
uint16_t hFaultNow; /*!< Bit fields variable containing faults
currently present */
uint16_t hFaultOccurred; /*!< Bit fields variable containing faults
historically occurred since the state
machine has been moved to FAULT_NOW state */
} STM_Handle_t;
速度力矩控制:
typedef struct
{
STC_Modality_t Mode; /*!< Modality of STC. It can be one of these two
settings: STC_TORQUE_MODE to enable the
Torque mode or STC_SPEED_MODE to enable the
Speed mode.*/
int16_t TargetFinal; /*!< Backup of hTargetFinal to be applied in the
last step.*/
int32_t SpeedRefUnitExt; /*!< Current mechanical rotor speed reference
expressed in tenths of HZ multiplied by
65536.*/
int32_t TorqueRef; /*!< Current motor torque reference. This value
represents actually the Iq current
expressed in digit multiplied by 65536.*/
uint32_t RampRemainingStep;/*!< Number of steps remaining to complete the
ramp.*/
PID_Handle_t * PISpeed; /*!< The regulator used to perform the speed
control loop.*/
SpeednPosFdbk_Handle_t * SPD;/*!< The speed sensor used to perform the speed
regulation.*/
int32_t IncDecAmount; /*!< Increment/decrement amount to be applied to
the reference value at each
CalcTorqueReference.*/
uint16_t STCFrequencyHz; /*!< Frequency on which the user updates
the torque reference calling
STC_CalcTorqueReference method
expressed in Hz */
uint16_t MaxAppPositiveMecSpeedUnit; /*!< Application maximum positive value
of the rotor mechanical speed. Expressed in
the unit defined by #SPEED_UNIT.*/
uint16_t MinAppPositiveMecSpeedUnit; /*!< Application minimum positive value
of the rotor mechanical speed. Expressed in
the unit defined by #SPEED_UNIT.*/
int16_t MaxAppNegativeMecSpeedUnit; /*!< Application maximum negative value
of the rotor mechanical speed. Expressed in
the unit defined by #SPEED_UNIT.*/
int16_t MinAppNegativeMecSpeedUnit; /*!< Application minimum negative value
of the rotor mechanical speed. Expressed in
the unit defined by #SPEED_UNIT.*/
uint16_t MaxPositiveTorque; /*!< Maximum positive value of motor
torque. This value represents
actually the maximum Iq current
expressed in digit.*/
int16_t MinNegativeTorque; /*!< Minimum negative value of motor
torque. This value represents
actually the maximum Iq current
expressed in digit.*/
STC_Modality_t ModeDefault; /*!< Default STC modality.*/
int16_t MecSpeedRefUnitDefault; /*!< Default mechanical rotor speed
reference expressed in the unit
defined by #SPEED_UNIT.*/
int16_t TorqueRefDefault; /*!< Default motor torque reference.
This value represents actually the
Iq current reference expressed in
digit.*/
int16_t IdrefDefault; /*!< Default Id current reference expressed
in digit.*/
} SpeednTorqCtrl_Handle_t;
FOC参数:
typedef struct
{
ab_t Iab; /**< @brief Stator current on stator reference frame abc */
alphabeta_t Ialphabeta; /**< @brief Stator current on stator reference frame alfa-beta*/
qd_t IqdHF; /**< @brief Stator current on stator reference frame alfa-beta*/
qd_t Iqd; /**< @brief Stator current on rotor reference frame qd */
qd_t Iqdref; /**< @brief Stator current on rotor reference frame qd */
int16_t UserIdref; /**< @brief User value for the Idref stator current */
qd_t Vqd; /**< @brief Phase voltage on rotor reference frame qd */
alphabeta_t Valphabeta; /**< @brief Phase voltage on stator reference frame alpha-beta*/
int16_t hTeref; /**< @brief Reference torque */
int16_t hElAngle; /**< @brief Electrical angle used for reference frame transformation */
uint16_t hCodeError; /**< @brief error message */
CurrRefSource_t bDriveInput; /**< @brief It specifies whether the current reference source must be
* #INTERNAL or #EXTERNAL*/
} FOCVars_t, *pFOCVars_t;
控制命令:
typedef enum
{
MCI_NOCOMMANDSYET, /*!< No command has been set by the user.*/
MCI_EXECSPEEDRAMP, /*!< ExecSpeedRamp command coming from the user.*/
MCI_EXECTORQUERAMP, /*!< ExecTorqueRamp command coming from the user.*/
MCI_SETCURRENTREFERENCES, /*!< SetCurrentReferences command coming from the
user.*/
} MCI_UserCommands_t;
最终速度:
int16_t hFinalSpeed;
最终速度初始化:
__weak void MCI_Init( MCI_Handle_t * pHandle, STM_Handle_t * pSTM, SpeednTorqCtrl_Handle_t * pSTC, pFOCVars_t pFOCVars )
{
pHandle->pSTM = pSTM;
pHandle->pSTC = pSTC;
pHandle->pFOCVars = pFOCVars;
/* Buffer related initialization */
pHandle->lastCommand = MCI_NOCOMMANDSYET;
pHandle->hFinalSpeed = 0;
pHandle->hFinalTorque = 0;
pHandle->hDurationms = 0;
pHandle->CommandState = MCI_BUFFER_EMPTY;
}
__weak void MCI_ExecSpeedRamp( MCI_Handle_t * pHandle, int16_t hFinalSpeed, uint16_t hDurationms )
{
pHandle->lastCommand = MCI_EXECSPEEDRAMP;
pHandle->hFinalSpeed = hFinalSpeed;
pHandle->hDurationms = hDurationms;
pHandle->CommandState = MCI_COMMAND_NOT_ALREADY_EXECUTED;
pHandle->LastModalitySetByUser = STC_SPEED_MODE;
}
__weak void MCI_ExecBufferedCommands( MCI_Handle_t * pHandle )
{
if ( pHandle != MC_NULL )
{
if ( pHandle->CommandState == MCI_COMMAND_NOT_ALREADY_EXECUTED )
{
bool commandHasBeenExecuted = false;
switch ( pHandle->lastCommand )
{
case MCI_EXECSPEEDRAMP:
{
pHandle->pFOCVars->bDriveInput = INTERNAL;
STC_SetControlMode( pHandle->pSTC, STC_SPEED_MODE );
commandHasBeenExecuted = STC_ExecRamp( pHandle->pSTC, pHandle->hFinalSpeed, pHandle->hDurationms );
}
break;
case MCI_EXECTORQUERAMP:
{
pHandle->pFOCVars->bDriveInput = INTERNAL;
STC_SetControlMode( pHandle->pSTC, STC_TORQUE_MODE );
commandHasBeenExecuted = STC_ExecRamp( pHandle->pSTC, pHandle->hFinalTorque, pHandle->hDurationms );
}
break;
case MCI_SETCURRENTREFERENCES:
{
pHandle->pFOCVars->bDriveInput = EXTERNAL;
pHandle->pFOCVars->Iqdref = pHandle->Iqdref;
commandHasBeenExecuted = true;
}
break;
default:
break;
}
if ( commandHasBeenExecuted )
{
pHandle->CommandState = MCI_COMMAND_EXECUTED_SUCCESFULLY;
}
else
{
pHandle->CommandState = MCI_COMMAND_EXECUTED_UNSUCCESFULLY;
}
}
}
}
__weak int16_t MCI_GetImposedMotorDirection( MCI_Handle_t * pHandle )
{
int16_t retVal = 1;
switch ( pHandle->lastCommand )
{
case MCI_EXECSPEEDRAMP:
if ( pHandle->hFinalSpeed < 0 )
{
retVal = -1;
}
break;
case MCI_EXECTORQUERAMP:
if ( pHandle->hFinalTorque < 0 )
{
retVal = -1;
}
break;
case MCI_SETCURRENTREFERENCES:
if ( pHandle->Iqdref.q < 0 )
{
retVal = -1;
}
break;
default:
break;
}
return retVal;
}
__weak int16_t MCI_GetLastRampFinalSpeed( MCI_Handle_t * pHandle )
{
int16_t hRetVal = 0;
/* Examine the last buffered commands */
if ( pHandle->lastCommand == MCI_EXECSPEEDRAMP )
{
hRetVal = pHandle->hFinalSpeed;
}
return hRetVal;
}
执行完MCTM1.pPIDSpeed = pPIDSpeedM1;后hFinalSpeed=250.
修改PID参数还是这样。
#define PID_SPEED_KP_DEFAULT 1 //230/(SPEED_UNIT/10) /* Workbench compute the gain for 01Hz unit*/
#define PID_SPEED_KI_DEFAULT 0 //90/(SPEED_UNIT/10) /* Workbench compute the gain for 01Hz unit*/
#define PID_SPEED_KD_DEFAULT 0/(SPEED_UNIT/10) /* Workbench compute the gain for 01Hz unit*/