整体理解

理解为启动时为开环模式加速启动,到一定阶段转为FOC闭环处理。在运行过程中会根据外部输入命令进行处理。
流程简介:

STC_SPEED_MODE和STC_TORQUE_MODE在运行过程中的转换

开始启动的时候即revup 加速过程实际上是STC_TORQUE_MODE模式,运行到RUN的状态即FOC过程的时候转换为速度模式。
在SWITCH_OVER阶段使用 MCI_ExecBufferedCommands(&Mci[M1]);调用进行转换

调用关系为

系统定时器->MC_RunMotorControlTasks-> MC_Scheduler()
或 Systick is not executed due low priority so is necessary to TIMx_BRK_M1_IRQHandler call .系统定时器没有调用的情况下TIMx_BRK_M1_IRQHandler需要调用。
TIMx_BRK_M1_IRQHandler->MC_Scheduler()

MC_Scheduler(hMFTaskCounterM1递减计数为0)->MediumFrequencyTask

/*** @brief Executes medium frequency periodic Motor Control tasks** This function performs some of the control duties on Motor 1 according to the* present state of its state machine. In particular, duties requiring a periodic* execution at a medium frequency rate (such as the speed controller for instance)* are executed here.*/
__weak void TSK_MediumFrequencyTaskM1(void)
{int16_t wAux = 0;bool IsSpeedReliable = STO_PLL_CalcAvrgMecSpeedUnit(&STO_PLL_M1, &wAux);PQD_CalcElMotorPower(pMPM[M1]);//检测速度是不是可靠,如果不可靠后续运行时需要错误处理if (MCI_GetCurrentFaults(&Mci[M1]) == MC_NO_FAULTS)//检测是电流获取是否正常{if (MCI_GetOccurredFaults(&Mci[M1]) == MC_NO_FAULTS)//检测是否有错误{switch (Mci[M1].State){case IDLE://空闲状态{if ((MCI_START == Mci[M1].DirectCommand) || (MCI_MEASURE_OFFSETS == Mci[M1].DirectCommand)){//收到运行命令RUC_Clear(&RevUpControlM1, MCI_GetImposedMotorDirection(&Mci[M1]));//初始化内部转速控制器状态if (pwmcHandle[M1]->offsetCalibStatus == false)//没有校准转入校准{PWMC_CurrentReadingCalibr(pwmcHandle[M1], CRC_START);//通过读取没有电流时的电流值电压值作为校准,每次启动都需要调用。Mci[M1].State = OFFSET_CALIB;}else//校准了就使能定时器相关通道,转入CHARGE_BOOT_CAP ,启动模式{/* calibration already done. Enables only TIM channels */pwmcHandle[M1]->OffCalibrWaitTimeCounter = 1u;PWMC_CurrentReadingCalibr(pwmcHandle[M1], CRC_EXEC);//通过读取没有电流时的电流值电压值作为校准,每次启动都需要调用。R3_2_TurnOnLowSides(pwmcHandle[M1]);//开启PWM定时器相关设置,有可能电容开始充电TSK_SetChargeBootCapDelayM1(CHARGE_BOOT_CAP_TICKS);//记录电容充电开始时间Mci[M1].State = CHARGE_BOOT_CAP;//转入BOOT 启动模式}}else{/* nothing to be done, FW stays in IDLE state */}break;}case OFFSET_CALIB:{if (MCI_STOP == Mci[M1].DirectCommand)//收到停止命令{TSK_MF_StopProcessing(&Mci[M1], M1);}else{if (PWMC_CurrentReadingCalibr(pwmcHandle[M1], CRC_EXEC))//通过读取没有电流时的电流值电压值作为校准,每次启动都需要调用。{if (MCI_MEASURE_OFFSETS == Mci[M1].DirectCommand)//根据以前的状态返回对应的应有状态。{FOC_Clear(M1);MPM_Clear((MotorPowMeas_Handle_t*) pMPM[M1]);Mci[M1].DirectCommand = MCI_NO_COMMAND;Mci[M1].State = IDLE;}else//从IDLE转启动启动跳过来的话转入启动{R3_2_TurnOnLowSides(pwmcHandle[M1]);//前有介绍TSK_SetChargeBootCapDelayM1(CHARGE_BOOT_CAP_TICKS);//前面有介绍Mci[M1].State = CHARGE_BOOT_CAP;}}else{/* nothing to be done, FW waits for offset calibration to finish */}}break;}case CHARGE_BOOT_CAP:{if (MCI_STOP == Mci[M1].DirectCommand)//收到停止命令转入停止{TSK_MF_StopProcessing(&Mci[M1], M1);}else{if (TSK_ChargeBootCapDelayHasElapsedM1())//如果有开机电容需要判断到充电完成时间够再运行{R3_2_SwitchOffPWM(pwmcHandle[M1]);//关闭PWMFOCVars[M1].bDriveInput = EXTERNAL;//设置影响FOC_CalcCurrRef,使用INTERNAL是内部根据速度等计算获得,使用EXTERNALSTC_SetSpeedSensor( pSTC[M1], &VirtualSpeedSensorM1._Super );//设置速度传感器为虚拟传感器STO_PLL_Clear(&STO_PLL_M1);//STO滑模观测的状态清0,后续到一定速度后会启动检测FOC_Clear( M1 );//清除FOC状态Mci[M1].State = START;//转到开始状态PWMC_SwitchOnPWM(pwmcHandle[M1]);//开启PWM}else{/* nothing to be done, FW waits for bootstrap capacitor to charge */}}break;}case START:{if (MCI_STOP == Mci[M1].DirectCommand)//如果是停止命令则停止{TSK_MF_StopProcessing(&Mci[M1], M1);}else{/* Mechanical speed as imposed by the Virtual Speed Sensor during the Rev Up phase. */int16_t hForcedMecSpeedUnit;qd_t IqdRef;bool ObserverConverged = false;/* Execute the Rev Up procedure */if(! RUC_Exec(&RevUpControlM1))//进行加速过程,加速可以由多个步骤的加速设置组合而成{/* The time allowed for the startup sequence has expired 时间超过了允许的启动时间*/MCI_FaultProcessing(&Mci[M1], MC_START_UP, 0);}else{/* Execute the torque open loop current start-up ramp:进行扭矩开环启动上坡* Compute the Iq reference current as configured in the Rev Up sequence计算Iq电流参考加速的过程序列 */IqdRef.q = STC_CalcTorqueReference( pSTC[M1] );//计算Iq值IqdRef.d = FOCVars[M1].UserIdref;//Id使用用户设定值/* Iqd reference current used by the High Frequency Loop to generate the PWM output */FOCVars[M1].Iqdref = IqdRef;}//计算虚拟速度传感器的速度值(void) VSS_CalcAvrgMecSpeedUnit(&VirtualSpeedSensorM1, &hForcedMecSpeedUnit);/* check that startup stage where the observer has to be used has been reached 启动到了可以使用观测器的状态,可以使用滑膜观察器就可以使用闭环控制*/if (true == RUC_FirstAccelerationStageReached(&RevUpControlM1)){ObserverConverged = STO_PLL_IsObserverConverged(&STO_PLL_M1, &hForcedMecSpeedUnit);STO_SetDirection(&STO_PLL_M1, (int8_t)MCI_GetImposedMotorDirection(&Mci[M1]));//将命令设置为从虚拟速度传感器启动转换阶段到其他速度传感器。(void)VSS_SetStartTransition(&VirtualSpeedSensorM1, ObserverConverged);}if (ObserverConverged)//观测器是否收敛{qd_t StatorCurrent = MCM_Park(FOCVars[M1].Ialphabeta, SPD_GetElAngle(&STO_PLL_M1._Super));/* Start switch over ramp. This ramp will transition from the revup to the closed loop FOC. 结束斜坡,加速转换成闭环的FOC*/REMNG_Init(pREMNG[M1]);(void)REMNG_ExecRamp(pREMNG[M1], FOCVars[M1].Iqdref.q, 0);(void)REMNG_ExecRamp(pREMNG[M1], StatorCurrent.q, TRANSITION_DURATION);Mci[M1].State = SWITCH_OVER;}}break;}case SWITCH_OVER:{if (MCI_STOP == Mci[M1].DirectCommand)//是否停止{TSK_MF_StopProcessing(&Mci[M1], M1);}else{bool LoopClosed;int16_t hForcedMecSpeedUnit;if(! RUC_Exec(&RevUpControlM1))//进行加速过程{/* The time allowed for the startup sequence has expired */MCI_FaultProcessing(&Mci[M1], MC_START_UP, 0);}else{/* Compute the virtual speed and positions of the rotor.The function returns true if the virtual speed is in the reliability range 计算转子的虚拟速度和位置。  如果虚拟速度在可靠性范围内,则该函数返回 true*/LoopClosed = VSS_CalcAvrgMecSpeedUnit(&VirtualSpeedSensorM1, &hForcedMecSpeedUnit);/* Check if the transition ramp has completed. */bool tempBool;//从虚拟速度传感器启动转换阶段到其他速度传感器是否完成判断。tempBool = VSS_TransitionEnded(&VirtualSpeedSensorM1);LoopClosed = LoopClosed || tempBool;/* If any of the above conditions is true, the loop is considered closed.The state machine transitions to the START_RUN state. 如果上述任一条件为真,则认为循环是闭合的。状态机将转换为START_RUN状态。*/if (true ==  LoopClosed){#if ( PID_SPEED_INTEGRAL_INIT_DIV == 0 )PID_SetIntegralTerm(&PIDSpeedHandle_M1, 0);#elsePID_SetIntegralTerm(&PIDSpeedHandle_M1,(((int32_t)FOCVars[M1].Iqdref.q * (int16_t)PID_GetKIDivisor(&PIDSpeedHandle_M1))/ PID_SPEED_INTEGRAL_INIT_DIV));#endif/* USER CODE BEGIN MediumFrequencyTask M1 1 *//* USER CODE END MediumFrequencyTask M1 1 */STC_SetSpeedSensor(pSTC[M1], &STO_PLL_M1._Super); /*Observer has converged*/FOC_InitAdditionalMethods(M1);FOC_CalcCurrRef( M1 );STC_ForceSpeedReferenceToCurrentSpeed(pSTC[M1]); /* Init the reference speed to current speed */MCI_ExecBufferedCommands(&Mci[M1]); /* Exec the speed ramp after changing of the speed sensor 斜坡起步后执行相关的命令,加减速等*/Mci[M1].State = RUN;}}}break;}case RUN://正常FOC运行{if (MCI_STOP == Mci[M1].DirectCommand)//停止命令{TSK_MF_StopProcessing(&Mci[M1], M1);}else{/* USER CODE BEGIN MediumFrequencyTask M1 2 *//* USER CODE END MediumFrequencyTask M1 2 */MCI_ExecBufferedCommands(&Mci[M1]);//前面有介绍FOC_CalcCurrRef(M1);//计算Iq电流值if(!IsSpeedReliable){MCI_FaultProcessing(&Mci[M1], MC_SPEED_FDBK, 0);}}break;}case STOP:{if (TSK_StopPermanencyTimeHasElapsedM1()){STC_SetSpeedSensor(pSTC[M1], &VirtualSpeedSensorM1._Super);      /*  sensor-less */VSS_Clear(&VirtualSpeedSensorM1); /* Reset measured speed in IDLE *//* USER CODE BEGIN MediumFrequencyTask M1 5 *//* USER CODE END MediumFrequencyTask M1 5 */Mci[M1].DirectCommand = MCI_NO_COMMAND;Mci[M1].State = IDLE;}else{/* nothing to do, FW waits for to stop */}break;}case FAULT_OVER:{if (MCI_ACK_FAULTS == Mci[M1].DirectCommand){Mci[M1].DirectCommand = MCI_NO_COMMAND;Mci[M1].State = IDLE;}else{/* nothing to do, FW stays in FAULT_OVER state until acknowledgement */}}break;case FAULT_NOW:{Mci[M1].State = FAULT_OVER;}default:break;}}else{Mci[M1].State = FAULT_OVER;}}else{Mci[M1].State = FAULT_NOW;}/* USER CODE BEGIN MediumFrequencyTask M1 6 *//* USER CODE END MediumFrequencyTask M1 6 */
}

RUC 爬坡控制

根据设置控制速度和电流值,其中STC_ExecRamp是获取曲线的参数,

VSS_SetMecAcceleration将曲线对应参设置给电机控制。

/*** @brief  Main revup controller procedure executing overall programmed phases.* @param  pHandle: Pointer on Handle structure of RevUp controller.*  @retval Boolean set to false when entire revup phases have been completed.*/
__weak bool RUC_Exec(RevUpCtrl_Handle_t *pHandle)
{bool retVal = true;
#ifdef NULL_PTR_REV_UP_CTLif (MC_NULL == pHandle){retVal = false;}else{#endifif (pHandle->hPhaseRemainingTicks > 0U)//加速时间没到0 减1{/* Decrease the hPhaseRemainingTicks.*/pHandle->hPhaseRemainingTicks--;} /* hPhaseRemainingTicks > 0 */if (0U == pHandle->hPhaseRemainingTicks)//一个加速过程是否结束{if (pHandle->pCurrentPhaseParams != MC_NULL)//后续没有加速过程,是否还有有的话使用新的加速过程{/* If it becomes zero the current phase has been completed.*//* Gives the next command to STC and VSS.*/(void)STC_ExecRamp(pHandle->pSTC, pHandle->pCurrentPhaseParams->hFinalTorque * pHandle->hDirection,(uint32_t)(pHandle->pCurrentPhaseParams->hDurationms));VSS_SetMecAcceleration(pHandle->pVSS,pHandle->pCurrentPhaseParams->hFinalMecSpeedUnit * pHandle->hDirection,pHandle->pCurrentPhaseParams->hDurationms);//设置加速曲线参数/* Compute hPhaseRemainingTicks.*/pHandle->hPhaseRemainingTicks = (uint16_t)((((uint32_t)pHandle->pCurrentPhaseParams->hDurationms) * ((uint32_t)pHandle->hRUCFrequencyHz)) / 1000U );//设置对应曲线的运行时间pHandle->hPhaseRemainingTicks++;//这个我认为可以可无,估计是想保证不为0/*Set the next phases parameter pointer.*/pHandle->pCurrentPhaseParams = pHandle->pCurrentPhaseParams->pNext; //指向下个电流设置曲线阶段//cstat !MISRAC2012-Rule-11.5/*Increases the rev up stages counter.*/pHandle->bStageCnt++;//过程计数,用于知道第几步了。}else//所有加速过程结束,后续没有新的加速设置{retVal = false;}}
#ifdef NULL_PTR_REV_UP_CTL}
#endifreturn (retVal);
}

VSS_CalcAvrgMecSpeedUnit

/*** @brief  This method must be called with the same periodicity*         on which speed control is executed.*         This method computes and stores rotor instantaneous el speed (express*         in dpp considering the measurement frequency) in order to provide it*         to SPD_CalcElAngle function and SPD_GetElAngle.*         Then compute store and return - through parameter*         hMecSpeedUnit - the rotor average mech speed, expressed in the unit*         defined by #SPEED_UNIT. Then return the reliability state of the*         sensor (always true).* @param  pHandle: handler of the current instance of the VirtualSpeedSensor component* @param  hMecSpeedUnit pointer to int16_t, used to return the rotor average*         mechanical speed (SPED_UNIT)* @retval true = sensor information is reliable*         false = sensor information is not reliable*/
__weak bool VSS_CalcAvrgMecSpeedUnit(VirtualSpeedSensor_Handle_t *pHandle, int16_t *hMecSpeedUnit)
{bool SpeedSensorReliability;
#ifdef NULL_PTR_VIR_SPD_SENif ((MC_NULL == pHandle) || (MC_NULL == hMecSpeedUnit)){SpeedSensorReliability = false;}else{#endifif (pHandle->hRemainingStep > 1u)//一个步数的计数判断,等于加速被切换成了多个阶段加速{pHandle->wElSpeedDpp32 += pHandle->wElAccDppP32;//一个32位的计数累加器一次加一个小的速度 32位精度较高,可以实现缓慢加速//实际用的是是速度的高16位
#ifndef FULL_MISRA_C_COMPLIANCY_VIRT_SPD_SENS//cstat !MISRAC2012-Rule-1.3_n !ATH-shift-neg !MISRAC2012-Rule-10.1_R6pHandle->_Super.hElSpeedDpp = (int16_t)(pHandle->wElSpeedDpp32 >> 16);
#elsepHandle->_Super.hElSpeedDpp = (int16_t)(pHandle->wElSpeedDpp32 / 65536);
#endif/* Convert dpp into MecUnit *///从每步的步速加的值计算电机的速度*hMecSpeedUnit = (int16_t)((((int32_t)pHandle->_Super.hElSpeedDpp)* ((int32_t )pHandle->_Super.hMeasurementFrequency) * SPEED_UNIT)/ (((int32_t)pHandle->_Super.DPPConvFactor) * ((int32_t)pHandle->_Super.bElToMecRatio)));//保存电机的速度值pHandle->_Super.hAvrMecSpeedUnit = *hMecSpeedUnit;pHandle->hRemainingStep--;//步数减少}else if (1U == pHandle->hRemainingStep)//到最后一部前{*hMecSpeedUnit = pHandle->hFinalMecSpeedUnit;//电机速度应该等于设定速度了pHandle->_Super.hAvrMecSpeedUnit = *hMecSpeedUnit;//保存设定速度pHandle->_Super.hElSpeedDpp = (int16_t)((((int32_t)*hMecSpeedUnit) * ((int32_t)pHandle->_Super.DPPConvFactor)) / (((int32_t)SPEED_UNIT) * ((int32_t)pHandle->_Super.hMeasurementFrequency)));//从电机的设定速度计算每部的速度pHandle->_Super.hElSpeedDpp *= ((int16_t)pHandle->_Super.bElToMecRatio);//这个可以和上面合并pHandle->hRemainingStep = 0U;//加速步骤完成}else{*hMecSpeedUnit = pHandle->_Super.hAvrMecSpeedUnit;}/* If the transition is not done yet, we already know that speed is not reliable *///在TSK_HighFrequencyTask->VSS_CalcElAngle中会调用一无状态观测器到有状态观测转换的过程。转换步数完成后会设置转换结束pHandle->bTransitionEnded = true;if (false == pHandle->bTransitionEnded){pHandle->_Super.bSpeedErrorNumber = pHandle->_Super.bMaximumSpeedErrorsNumber;SpeedSensorReliability = false;}else{SpeedSensorReliability = SPD_IsMecSpeedReliable(&pHandle->_Super, hMecSpeedUnit);}
#ifdef NULL_PTR_VIR_SPD_SEN}
#endifreturn (SpeedSensorReliability);
}

FOC ST MediumFrequencyTask 分析(代码注释)相关推荐

  1. 使用 Roslyn 分析代码注释,给 TODO 类型的注释添加负责人、截止日期和 issue 链接跟踪

    如果某天改了一点代码但是没有完成,我们可能会在注释里面加上 // TODO.如果某个版本为了控制影响范围临时使用不太合适的方法解了 Bug,我们可能也会在注释里面加上 // TODO.但是,对于团队项 ...

  2. linux源码acl,Linux自主访问控制机制模块详细分析之posix_acl.c核心代码注释与acl.c文件介绍...

    原标题:Linux自主访问控制机制模块详细分析之posix_acl.c核心代码注释与acl.c文件介绍 2.4.4.6 核心代码注释 1 posix_acl_permission() int(stru ...

  3. tensorflow笔记:流程,概念和简单代码注释

    tensorflow是google在2015年开源的深度学习框架,可以很方便的检验算法效果.这两天看了看官方的tutorial,极客学院的文档,以及综合tensorflow的源码,把自己的心得整理了一 ...

  4. 竟有如此沙雕的代码注释!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 某站后端代码被"开源",同时刷遍全网 ...

  5. Redis是如何写代码注释的?

    许多人认为,如果代码写得足够扎实,注释就没什么用了.在他们看来,当一切都设计妥当时,代码本身会记录其作用,因此代码注释是多余的.我对此持不同意见,主要出于两个原因: 1. 许多注释并未起到解释代码的作 ...

  6. java 注释 超链接_java_Java代码注释规范详解,代码附有注释对程序开发者来 - phpStudy...

    Java代码注释规范详解 代码附有注释对程序开发者来说非常重要,随着技术的发展,在项目开发过程中,必须要求程序员写好代码注释,这样有利于代码后续的编写和使用. 基本的要求: 1.注释形式统一 在整个应 ...

  7. 代码注释掉还能执行_日志消息是可执行代码和注释

    代码注释掉还能执行 尽管在一个人的代码中应添加多少注释之间存在意见分歧,但我认为可以肯定地说,大多数开发人员都同意以下代码段中的注释是多余的: // increment the total total ...

  8. linux统计代码注释率,统计代码注释率

    #!/bin/bash #program: #       分析.c,.cpp文件,计算文件行总数,代码行总数,注释行总数,空白行总数,代码注释率 #       注释类型: #       (1)行 ...

  9. xml分析错误:注释未终止_错误:C中的未终止注释(无效的注释块) 常见的C程序错误...

    xml分析错误:注释未终止 Comments are used to write logic explain or anything that you do not want to compile. ...

最新文章

  1. 关于浏览器和浏览器内核的解释
  2. 二叉树中是否存在节点和为指定值的路径
  3. 超快速的端到端实例分割模型,手把手教你用opencv部署Yolact
  4. 软件工程期末复习汇总
  5. 零基础想考华为认证,该怎么学?
  6. 2001年广西壮族自治区植被类型分布数据
  7. DataFrame案例--双均线策略
  8. MySQL —— 查询升序和降序
  9. Excel中对合并单元格后不同行数对应数据处理的三种特技
  10. 建立数据库模型:从业务模型、概念模型到逻辑模型
  11. java取字符串首字母_java 获取中文字符的首字母
  12. Subpalindromes
  13. DRAG DROP
  14. 关于whl,你想知道的
  15. Qt中sender()函数的用法
  16. 解决Field ‘id‘ doesn‘t have a default value 问题
  17. 跟我一起玩Win32开发(1):关于C++的几个要点
  18. 北大软件工程与计算机,北京大学软件工程考研经验分享
  19. 2022 年红队工具和模拟工具包
  20. 一文看懂:零代码平台是什么?怎么选?

热门文章

  1. html 随机画圈 不重叠,html实现随机图片
  2. 去美国出差需要注意什么
  3. SplashScreen
  4. Office软件学习
  5. mail.163.com登录界面
  6. laravel config文件配置全局变量
  7. win7安装ettercap_使用ettercap进行dns欺骗和获取目标浏览的图片
  8. 自定义歌词View的优化(一)
  9. Android开发学习中的问题2016-5-03手动创建活动
  10. Game - datastructure