Preface
The previous post described the main program structure generated by the STM32 Motor Control Workbench. Here we will continue to explain the three core task flows and structures that depend on the main structure, which are mainly divided into three parts: safety tasks, medium frequency tasks, and high frequency tasks. The safety task mainly focuses on protecting temperature, voltage, and current, while the medium frequency task executes speed loop and status execution. Finally, the high frequency task is responsible for executing the FOC algorithm.
Security Task
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-76.png)
__weak void TSK_SafetyTask_PWMOFF(uint8_t bMotor)
{
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 0 */
/* USER CODE END TSK_SafetyTask_PWMOFF 0 */
uint16_t CodeReturn = MC_NO_ERROR; //錯誤Flag
uint16_t errMask[NBR_OF_MOTORS] = {VBUS_TEMP_ERR_MASK};//壓力溫度Flag,初始化錯誤
//檢測溫度是否超過
CodeReturn |= errMask[bMotor] & NTC_CalcAvTemp(pTemperatureSensor[bMotor]); /* check for fault if FW protection is activated. It returns MC_OVER_TEMP or MC_NO_ERROR */
//檢測電流是否過大
CodeReturn |= PWMC_CheckOverCurrent(pwmcHandle[bMotor]); /* check for fault. It return MC_BREAK_IN or MC_NO_FAULTS
(for STM32F30x can return MC_OVER_VOLT in case of HW Overvoltage) */
if(bMotor == M1)//馬達1
{
CodeReturn |= errMask[bMotor] &RVBS_CalcAvVbus(pBusSensorM1);//檢測主電壓,獲取電壓狀態
}
//更新狀態信息
STM_FaultProcessing(&STM[bMotor], CodeReturn, ~CodeReturn); /* Update the STM according error code */
//獲取狀態值
switch (STM_GetState(&STM[bMotor])) /* Acts on PWM outputs in case of faults */
{
case FAULT_NOW: //當前有錯誤
PWMC_SwitchOffPWM(pwmcHandle[bMotor]);//关闭PWM输出
FOC_Clear(bMotor); //初始化電壓電流變量。
//此外,它清除 qd 電流 PI 控制器、電壓傳感器和SpeednTorquecontroller
MPM_Clear((MotorPowMeas_Handle_t*)pMPM[bMotor]);//清除測量緩衝區並初始化索引
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 1 */
/* USER CODE END TSK_SafetyTask_PWMOFF 1 */
break;
case FAULT_OVER://當故障消失時,應用程序打算保持的持久狀態。
//後續狀態通常是 STOP_IDLE,一旦用戶確認故障條件,狀態機就會移動。
PWMC_SwitchOffPWM(pwmcHandle[bMotor]);//關閉PWM輸出
/* USER CODE BEGIN TSK_SafetyTask_PWMOFF 2 */
/* USER CODE END TSK_SafetyTask_PWMOFF 2 */
break;
default:
break;
}
}
Middle Frequent tasks
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-77.png)
__weak void MC_Scheduler(void)
{
/* USER CODE BEGIN MC_Scheduler 0 */
/* USER CODE END MC_Scheduler 0 */
if (bMCBootCompleted == 1)//初始化完成
{
if(hMFTaskCounterM1 > 0u)//任务計數大於0
{
hMFTaskCounterM1--;//遞减
}
else
{
TSK_MediumFrequencyTaskM1();//執行中頻任务
//速度環以及狀態機執行
/* USER CODE BEGIN MC_Scheduler 1 */
/* USER CODE END MC_Scheduler 1 */
hMFTaskCounterM1 = MF_TASK_OCCURENCE_TICKS;//任務計數,
//MF_TASK_OCCURENCE_TICKS=(SYS_TICK_FREQUENCY/SPEED_LOOP_FREQUENCY_HZ)-1u
//SYS_TICK_FREQUENCY=2000,SPEED_LOOP_FREQUENCY_HZ = 1000
}
if(hBootCapDelayCounterM1 > 0u) //驅動器啟動電容器對馬達 1 充电所需的延遲計數
{
hBootCapDelayCounterM1--;
}
if(hStopPermanencyCounterM1 > 0u)//馬達1 在 STOP 狀態下的持續時間
{
hStopPermanencyCounterM1--;
}
}
else
{
}
}
HIGH Frequent tasks
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-78.png)
__weak uint8_t TSK_HighFrequencyTask(void)
{
/* USER CODE BEGIN HighFrequencyTask 0 */
/* USER CODE END HighFrequencyTask 0 */
uint8_t bMotorNbr = 0;
uint16_t hFOCreturn;
uint16_t hState; /* only if sensorless main*/
Observer_Inputs_t STO_Inputs; /* only if sensorless main*/
STO_Inputs.Valfa_beta = FOCVars[M1].Valphabeta; /* only if sensorless*/
if ( STM[M1].bState == SWITCH_OVER )
{
if (!REMNG_RampCompleted(pREMNG[M1]))
{
FOCVars[M1].Iqdref.q = REMNG_Calc(pREMNG[M1]);//執行斜率計算並返回狀態變量的當前值
}
}
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_1 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_1 */
hFOCreturn = FOC_CurrControllerM1();//執行FOC核心算法,並返回執行完成的狀態
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_2 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_2 */
if(hFOCreturn == MC_FOC_DURATION)//FOC執行錯誤
{
STM_FaultProcessing(&STM[M1], MC_FOC_DURATION, 0);//報錯
}
else//沒有錯誤
{
//檢查對齊和第一加速階段是否已完成
bool IsAccelerationStageReached = RUC_FirstAccelerationStageReached(&RevUpControlM1);
STO_Inputs.Ialfa_beta = FOCVars[M1].Ialphabeta; /* only if sensorless*/
//测量電壓
STO_Inputs.Vbus = VBS_GetAvBusVoltage_d(&(pBusSensorM1->_Super)); /* only for sensorless*/
//獲取新的速度並更新估算的角度
STO_PLL_CalcElAngle (&STO_PLL_M1, &STO_Inputs);
//估算平均速度
STO_PLL_CalcAvrgElSpeedDpp (&STO_PLL_M1); /* Only in case of Sensor-less */
if (IsAccelerationStageReached == false)//如果檢查加速階段没有完成
{
STO_ResetPLL(&STO_PLL_M1);//覆為參數
}
//獲取馬達狀態
hState = STM_GetState(&STM[M1]);
if((hState == START) || (hState == SWITCH_OVER) || (hState == START_RUN)) /* only for sensor-less*/
{
int16_t hObsAngle = SPD_GetElAngle(&STO_PLL_M1._Super);//獲取轉子角度
VSS_CalcElAngle(&VirtualSpeedSensorM1,&hObsAngle);//更新轉子角度
}
/* USER CODE BEGIN HighFrequencyTask SINGLEDRIVE_3 */
/* USER CODE END HighFrequencyTask SINGLEDRIVE_3 */
}
/* USER CODE BEGIN HighFrequencyTask 1 */
/* USER CODE END HighFrequencyTask 1 */
return bMotorNbr;
}
API Using
After introducing the main program flow, the next step is to use the upper-level API to make the motor rotate, indicating that the API has been successfully established.
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-79.png)
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-80.png)
Mainly, the following 2 functions need to be set within the while
loop of the program to make the motor run.
MC_ProgramSpeedRampMotor1(3000/6,1000); //設定轉速為3000
MC_StartMotor1(); //馬達運轉
Sample code Reference
The reference code for implementing the following speed control is shown below.
![](http://en.stamssolution.com/wp-content/uploads/2022/03/image-81.png)
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
MC_ProgramSpeedRampMotor1(3000/6,1000); //設定轉速為3000
MC_StartMotor1(); //馬達運轉
HAL_Delay(10000); //延時10S
MC_ProgramSpeedRampMotor1(5000/6,1000); //設定轉速為5000
HAL_Delay(10000);
MC_ProgramSpeedRampMotor1(2000/6,1000); //設定轉速為2000
HAL_Delay(10000);
MC_StopMotor1(); //馬達停轉
HAL_Delay(5000); //延時5S
}
/* USER CODE END 3 */
Pingback: Motor Control Workbench 程式架構 - AMS and STM32