本帖最后由 子曰好人 于 2018-9-2 10:21 编辑
经过前期的准备,可以使用电机套件完成一些实验任务了。 首先是任务1和任务2的要求: 任务一和任务二基于workbench生成的代码来做并不难,因为代码里面提供了很多api函数并且做了很多软件上的保护,可以放心写代码,硬件不会那么容易损坏。
拿到一份陌生的代码除了了解我前面几篇帖子所说的内容外,在开始写代码前还需要了解api函数。我们可以打开mc_api.h看一看workbench都给我们提供了什么函数。
- /** @addtogroup MCIAPI
- * @{
- */
- typedef enum {UDRC_STATE_IDLE, UDRC_STATE_REQUESTED, UDRC_STATE_EOC} UDRC_State_t;
- /* Starts Motor 1 */
- bool MC_StartMotor1(void);
- /* Stops Motor 1 */
- bool MC_StopMotor1(void);
- /* Programs a Speed ramp for Motor 1 */
- void MC_ProgramSpeedRampMotor1( int16_t hFinalSpeed, uint16_t hDurationms );
- /* Programs a Torque ramp for Motor 1 */
- void MC_ProgramTorqueRampMotor1( int16_t hFinalTorque, uint16_t hDurationms );
- /* Programs a current reference for Motor 1 */
- void MC_SetCurrentReferenceMotor1( Curr_Components Iqdref );
- /* Returns the state of the last submited command for Motor 1 */
- MCI_CommandState_t MC_GetCommandStateMotor1( void);
- /* Stops the execution of the current speed ramp for Motor 1 if any */
- bool MC_StopSpeedRampMotor1(void);
- /* Returns true if the last submited ramp for Motor 1 has completed, false otherwise */
- bool MC_HasRampCompletedMotor1(void);
- /* Returns the current mechanical rotor speed reference set for Motor 1, expressed in dHz (tenth of Hertz) */
- int16_t MC_GetMecSpeedReferenceMotor1(void);
- /* Returns the last computed average mechanical rotor speed for Motor 1, expressed in dHz (tenth of Hertz) */
- int16_t MC_GetMecSpeedAverageMotor1(void);
- /* Returns the final speed of the last ramp programmed for Motor 1, if this ramp was a speed ramp */
- int16_t MC_GetLastRampFinalSpeedMotor1(void);
- /* Returns the current Control Mode for Motor 1 (either Speed or Torque) */
- STC_Modality_t MC_GetControlModeMotor1(void);
- /* Returns the direction imposed by the last command on Motor 1 */
- int16_t MC_GetImposedDirectionMotor1(void);
- /* Returns the current reliability of the speed sensor used for Motor 1 */
- bool MC_GetSpeedSensorReliabilityMotor1(void);
- /* returns the amplitude of the phase current injected in Motor 1 */
- int16_t MC_GetPhaseCurrentAmplitudeMotor1(void);
- /* returns the amplitude of the phase voltage applied to Motor 1 */
- int16_t MC_GetPhaseVoltageAmplitudeMotor1(void);
- /* returns current Ia and Ib values for Motor 1 */
- Curr_Components MC_GetIabMotor1(void);
- /* returns current Ialpha and Ibeta values for Motor 1 */
- Curr_Components MC_GetIalphabetaMotor1(void);
- /* returns current Iq and Id values for Motor 1 */
- Curr_Components MC_GetIqdMotor1(void);
- /* returns Iq and Id reference values for Motor 1 */
- Curr_Components MC_GetIqdrefMotor1(void);
- /* returns current Vq and Vd values for Motor 1 */
- Volt_Components MC_GetVqdMotor1(void);
- /* returns current Valpha and Vbeta values for Motor 1 */
- Volt_Components MC_GetValphabetaMotor1(void);
- /* returns the electrical angle of the rotor of Motor 1, in DDP format */
- int16_t MC_GetElAngledppMotor1(void);
- /* returns the current electrical torque reference for Motor 1 */
- int16_t MC_GetTerefMotor1(void);
- /* Sets the reference value for Id */
- void MC_SetIdrefMotor1( int16_t hNewIdref );
- /* re-initializes Iq and Id references to their default values */
- void MC_Clear_IqdrefMotor1(void);
- /* Acknowledge a Motor Control fault on Motor 1 */
- bool MC_AcknowledgeFaultMotor1( void );
- /* Returns a bitfiled showing faults that occured since the State Machine of Motor 1 was moved to FAULT_NOW state */
- uint16_t MC_GetOccurredFaultsMotor1(void);
- /* Returns a bitfield showing all current faults on Motor 1 */
- uint16_t MC_GetCurrentFaultsMotor1(void);
- /* returns the current state of Motor 1 state machine */
- State_t MC_GetSTMStateMotor1(void);
- /* programs a user defined ADC regular conversion */
- void MC_ProgramRegularConversion(uint8_t bChannel, uint8_t bSampleTime);
- /* Returns the value of the last executed user defined ADC regular conversion */
- uint16_t MC_GetRegularConversionValue(void);
- /* Returns the status of the last requested user defined ADC regular conversion */
- UDRC_State_t MC_GetRegularConversionState(void);
复制代码上面这些api函数是对单个电机的操作,包含了启动、调速、调转矩、以及电机各种状态的获取。 看了任务一的要求,个人认为电机控制还是需要与外部交互好一点,电机启停不可控对于大功率的电机控制来说比较危险。 任务一代码: - void task_1(void)
- {
- MC_ProgramSpeedRampMotor1(3000/6,1000);
- MC_StartMotor1();
- HAL_Delay(10000);
- MC_StopMotor1();
- HAL_Delay(10000);
- }
复制代码主函数添加的代码: - /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
-
- if(GPIO_PIN_SET == HAL_GPIO_ReadPin(LED11_GPIO_Port,LED11_Pin))
- {
- task_1();
- }
- else
- {
- MC_StopMotor1();
- }
- realspeed = MC_GetMecSpeedAverageMotor1()*6;
- /* USER CODE END WHILE */
复制代码按键中断处理函数代码在ui_task.c这个文件中: - void UI_HandleStartStopButton_cb (void)
- {
- /* USER CODE BEGIN START_STOP_BTN */
- HAL_GPIO_TogglePin(LED11_GPIO_Port,LED11_Pin);
- /* USER CODE END START_STOP_BTN */
- }
复制代码这样可以通过按键来控制任务的运行并且可以通过led的亮灭来观察系统所处的状态。LED11是驱动板上的一颗led,引脚号是PB2,可以通过cubemx来设置初始化代码。 通过monitor可以看到速度变化曲线图: ok,任务一完成。 -------------------------------------------------------------
任务二代码: - void task_2(void)
- {
- int16_t Speed_Kp,Speed_Ki;
- MCT_Handle_t * pMctHdl;
- MC_ProgramSpeedRampMotor1(3000/6,1000);
- MC_StartMotor1();
- HAL_Delay(3000);
- MC_StopMotor1();
- HAL_Delay(1000);
- pMctHdl = GetMCT(M1);
- Speed_Kp = PID_GetKP(pMctHdl->pPIDSpeed);
- Speed_Ki = PID_GetKI(pMctHdl->pPIDSpeed);
- PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp*2);
- PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki*2);
- MC_ProgramSpeedRampMotor1(3000/6,1000);
- MC_StartMotor1();
- HAL_Delay(3000);
- MC_StopMotor1();
- HAL_Delay(1000);
- PID_SetKP(pMctHdl->pPIDSpeed,Speed_Kp/2);
- PID_SetKI(pMctHdl->pPIDSpeed,Speed_Ki/2);
- MC_ProgramSpeedRampMotor1(3000/6,1000);
- MC_StartMotor1();
- HAL_Delay(3000);
- MC_StopMotor1();
- HAL_GPIO_WritePin(LED11_GPIO_Port,LED11_Pin,GPIO_PIN_RESET);
- }
复制代码主函数代码和任务一相同,只是把task_1()改成task_2()就行了。最后一行把LED引脚拉低是为了让代码只运行一次,多次运行可以通过按键进行操作。 可以看到和预期结果是一致的,原始PI调节速度快,有超调现象;Kp、Ki同时增大一倍的时候,调节加快了,并且超调现象被抑制了;当Kp、Ki同时缩小一倍时可以看到虽然调节很快,但是有严重的超调现象。
通过monitor的图形显示速度波形极大的方便调试PID的过程,ST考虑得真周到。
我在这里有个疑问,这个plotter只能显示参考速度的波形吗,还能不能添加其他变量来查看系统某个变量的变化趋势呢。之前我一直是用的Jscope,但是Jscope需要连接Jlink来查看,对于这款套件来说需要额外连接Jlink调试器,有一点点麻烦。后面调试有必要我还是会使用Jscope来查看一些变量的波形,并且分享到论坛。
任务一和任务二已完成,欢迎大家留言讨论。
|