前面
这个问题来自于一个私信(ID:学到老&活到老)
总结来说:就是占空比非满,使用PWM策略进行调制时,检测到另一相的反电动势是非连续的,如果这个时候过零点正好出现在MOS管关断的时候,岂不是检测不到这个时候的反电动势了?
解决办法原理
这个办法来自于NXP电控开发笔记
用一句话来讲的话,嗯,其实就是线性插值。
通过测量两个点的反电动势,通过插值的办法,近似找到过零点。
如上图,Tzc就是过零点,但刚好在MOS关断的时候,没办法测量到这时候的反电动势。
假设这个时候电机匀速转动,没有出现加速或者减速的情况。
我们就可以通过测量在Tadc时刻的反电动势值et,以及上一次测量的反电动势值e(t-1)
按照以下公式计算:
用的三角形近似,求得Tzc。
算法实现
if(bemfVoltage >= 0)
{
/* Rising interpolation */
delta = bemfVoltage - bemfVoltageOld;
if((driveStatus.B.AdcSaved == 1) && (delta > bemfVoltage))
{
timeBackEmf -= MLIB_Mul(MLIB_Div(bemfVoltage, delta), MLIB_Sub(timeBackEmf, timeOldBackEmf));
}
else
{
timeBackEmf -= (MLIB_Div(MLIB_Sub(timeBackEmf, timeOldBackEmf), 2));
}
lastTimeZC = timeZC;
timeZC = (uint16_t)timeBackEmf;
// periodZC = (timeZC - lasTimeZC) + ftm_mod_old(no timer reset)
periodZC[ActualCmtSector] = (ftm_mod_old - lastTimeZC) + timeZC;
// Average of the previous and current ZC period
actualPeriodZC = (actualPeriodZC + periodZC[ActualCmtSector]) >> 1;
// advancedAngle(0.3815) = 0.5 * Advanced Angle(0.763)
NextCmtPeriod = MLIB_Mul_F16(actualPeriodZC, advanceAngle);
// Update commutation period -> FTM0_MOD = timeZC + nextCmtPeriod
FTM_DRV_CounterStop(INST_FLEXTIMER_MC0);
FTM_DRV_SetModuloCounterValue(INST_FLEXTIMER_MC0, timeZC + NextCmtPeriod, true);
FTM_DRV_CounterStart(INST_FLEXTIMER_MC0);
driveStatus.B.NewZC = 1;
}
公式1就是具体的插值算法实现,使用了NXP内置的一些工具函数库。
if((driveStatus.B.AdcSaved == 1) && (delta > bemfVoltage))
{
timeBackEmf -= MLIB_Mul(MLIB_Div(bemfVoltage, delta), MLIB_Sub(timeBackEmf, timeOldBackEmf));//公式1
}
else
{
timeBackEmf -= (MLIB_Div(MLIB_Sub(timeBackEmf, timeOldBackEmf), 2));
}