前面

这个问题来自于一个私信(ID:学到老&活到老)
image.png
image.png
image.png
image.png
总结来说:就是占空比非满,使用PWM策略进行调制时,检测到另一相的反电动势是非连续的,如果这个时候过零点正好出现在MOS管关断的时候,岂不是检测不到这个时候的反电动势了?
image.png

解决办法原理

这个办法来自于NXP电控开发笔记
用一句话来讲的话,嗯,其实就是线性插值
通过测量两个点的反电动势,通过插值的办法,近似找到过零点。
image.png
如上图,Tzc就是过零点,但刚好在MOS关断的时候,没办法测量到这时候的反电动势。
假设这个时候电机匀速转动,没有出现加速或者减速的情况。
我们就可以通过测量在Tadc时刻的反电动势值et,以及上一次测量的反电动势值e(t-1)
按照以下公式计算:
image.png
用的三角形近似,求得Tzc。

算法实现

  1. if(bemfVoltage >= 0)
  2. {
  3. /* Rising interpolation */
  4. delta = bemfVoltage - bemfVoltageOld;
  5. if((driveStatus.B.AdcSaved == 1) && (delta > bemfVoltage))
  6. {
  7. timeBackEmf -= MLIB_Mul(MLIB_Div(bemfVoltage, delta), MLIB_Sub(timeBackEmf, timeOldBackEmf));
  8. }
  9. else
  10. {
  11. timeBackEmf -= (MLIB_Div(MLIB_Sub(timeBackEmf, timeOldBackEmf), 2));
  12. }
  13. lastTimeZC = timeZC;
  14. timeZC = (uint16_t)timeBackEmf;
  15. // periodZC = (timeZC - lasTimeZC) + ftm_mod_old(no timer reset)
  16. periodZC[ActualCmtSector] = (ftm_mod_old - lastTimeZC) + timeZC;
  17. // Average of the previous and current ZC period
  18. actualPeriodZC = (actualPeriodZC + periodZC[ActualCmtSector]) >> 1;
  19. // advancedAngle(0.3815) = 0.5 * Advanced Angle(0.763)
  20. NextCmtPeriod = MLIB_Mul_F16(actualPeriodZC, advanceAngle);
  21. // Update commutation period -> FTM0_MOD = timeZC + nextCmtPeriod
  22. FTM_DRV_CounterStop(INST_FLEXTIMER_MC0);
  23. FTM_DRV_SetModuloCounterValue(INST_FLEXTIMER_MC0, timeZC + NextCmtPeriod, true);
  24. FTM_DRV_CounterStart(INST_FLEXTIMER_MC0);
  25. driveStatus.B.NewZC = 1;
  26. }

公式1就是具体的插值算法实现,使用了NXP内置的一些工具函数库。

  1. if((driveStatus.B.AdcSaved == 1) && (delta > bemfVoltage))
  2. {
  3. timeBackEmf -= MLIB_Mul(MLIB_Div(bemfVoltage, delta), MLIB_Sub(timeBackEmf, timeOldBackEmf));//公式1
  4. }
  5. else
  6. {
  7. timeBackEmf -= (MLIB_Div(MLIB_Sub(timeBackEmf, timeOldBackEmf), 2));
  8. }