This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

InstaSPIN-FOC 关于SVGENCURRENT_compPwmData()、SVGEN_run()、HAL_setTrigger()函数的实现原理



static inline void SVGENCURRENT_compPwmData(SVGENCURRENT_Handle svgencurrentHandle, MATH_vec3 *pPwmData, MATH_vec3 *pPwmData_prev)
{
SVGENCURRENT_Obj *svgencurrent = (SVGENCURRENT_Obj *)svgencurrentHandle;

_iq Va_avg = (pPwmData->value[0]+pPwmData_prev->value[0])>>1;
_iq Vb_avg = (pPwmData->value[1]+pPwmData_prev->value[1])>>1;
_iq Vc_avg = (pPwmData->value[2]+pPwmData_prev->value[2])>>1;
_iq Vlimit;
_iq Vmid, Vmid_prev;
_iq Voffset;

Vlimit = svgencurrent->Vlimit;//最大占空比

//define compensation mode

if(Va_avg > Vlimit)
{
if(Vb_avg > Vlimit)//
{
svgencurrent->compMode = one_phase_measurable;//
if(Va_avg > Vb_avg)//
Vmid = pPwmData->value[1];//
Vmid_prev = pPwmData_prev->value[1];
svgencurrent->Vmid = Vmid_b;//
}
else
{
Vmid = pPwmData->value[0];
Vmid_prev = pPwmData_prev->value[0];
svgencurrent->Vmid = Vmid_a;
}
}
else if(Vc_avg > Vlimit)
{
svgencurrent->compMode = one_phase_measurable;
if(Va_avg > Vc_avg)
{
Vmid = pPwmData->value[2];
Vmid_prev = pPwmData_prev->value[2];
svgencurrent->Vmid = Vmid_c;
}
else
{
Vmid = pPwmData->value[0];
Vmid_prev = pPwmData_prev->value[0];
svgencurrent->Vmid = Vmid_a;
}
}
else
{
svgencurrent->compMode = two_phase_measurable;
if(Vb_avg > Vc_avg) svgencurrent->Vmid = Vmid_b;
else svgencurrent->Vmid = Vmid_c;
}

}
else
{
if(Vb_avg > Vlimit)
{
if(Vc_avg > Vlimit)
{
svgencurrent->compMode = one_phase_measurable;
if(Vb_avg > Vc_avg)
{
Vmid = pPwmData->value[2];
Vmid_prev = pPwmData_prev->value[2];
svgencurrent->Vmid = Vmid_c;
}
else
{
Vmid = pPwmData->value[1];
Vmid_prev = pPwmData_prev->value[1];
svgencurrent->Vmid = Vmid_b;
}
}
else
{
svgencurrent->compMode = two_phase_measurable;
if(Va_avg > Vc_avg) svgencurrent->Vmid = Vmid_a;
else svgencurrent->Vmid = Vmid_c;
}
}
else
{
if(Vc_avg > Vlimit)
{
svgencurrent->compMode = two_phase_measurable;
if(Va_avg > Vb_avg) svgencurrent->Vmid = Vmid_a;
else svgencurrent->Vmid = Vmid_b;
}
else
{
svgencurrent->compMode = all_phase_measurable;
}
}
}

//phase voltage compensator
if(svgencurrent->compMode == one_phase_measurable)//得出只有一相可以采集到电流
{
//???不理解为什么??
Voffset = (Vmid + Vmid_prev) - (Vlimit <<1);//

pPwmData->value[0] -= Voffset;//减去偏置 使下管时间采样更充分
pPwmData->value[1] -= Voffset;
pPwmData->value[2] -= Voffset;
}

// get ignore current
//判断偏置修正后占空比是否大于占空比限制值
if(((pPwmData->value[0] + pPwmData_prev->value[0])>>1) > Vlimit)
{
svgencurrent->IgnoreShunt = ignore_a;
}
else if(((pPwmData->value[1] + pPwmData_prev->value[1])>>1) > Vlimit)
{
svgencurrent->IgnoreShunt = ignore_b;
}
else if(((pPwmData->value[2] + pPwmData_prev->value[2])>>1) > Vlimit)
{
svgencurrent->IgnoreShunt = ignore_c;
}
else
{
svgencurrent->IgnoreShunt = use_all;
}

pPwmData_prev->value[0] = pPwmData->value[0];
pPwmData_prev->value[1] = pPwmData->value[1];
pPwmData_prev->value[2] = pPwmData->value[2];

return;
} // end of SVGENCURRENT_compPwmData() function

static inline void HAL_setTrigger(HAL_Handle handle,const SVGENCURRENT_IgnoreShunt_e ignoreShunt,
const SVGENCURRENT_VmidShunt_e midVolShunt)
{
HAL_Obj *obj = (HAL_Obj *)handle;

PWM_Obj *pwm1 = (PWM_Obj *)obj->pwmHandle[PWM_Number_1];
PWM_Obj *pwm2 = (PWM_Obj *)obj->pwmHandle[PWM_Number_2];
PWM_Obj *pwm3 = (PWM_Obj *)obj->pwmHandle[PWM_Number_3];
PWM_Obj *pwm;

uint16_t nextPulse1 = (pwm1->CMPA + pwm1->CMPAM) / 2;
uint16_t nextPulse2 = (pwm2->CMPA + pwm2->CMPAM) / 2;
uint16_t nextPulse3 = (pwm3->CMPA + pwm3->CMPAM) / 2;
uint16_t pwmCMPA1 = pwm1->CMPA;
uint16_t pwmCMPA2 = pwm2->CMPA;
uint16_t pwmCMPA3 = pwm3->CMPA;

if(ignoreShunt == use_all)//计算出占空比最小的一相
{
if((nextPulse1 <= nextPulse2) && (nextPulse1 <= nextPulse3))
{
pwm = pwm1;
}
else if((nextPulse2 <= nextPulse1) && (nextPulse2 <= nextPulse3))
{
pwm = pwm2;
}
else
{
pwm = pwm3;
}
}
else
{
if(midVolShunt == Vmid_a)
{
pwm = pwm1;
}
else if(midVolShunt == Vmid_b)
{
pwm = pwm2;
}
else
{
pwm = pwm3;
}
}

pwmCMPA1 = pwm->CMPA;
pwmCMPA2 = pwm->CMPAM;

if(pwmCMPA2 >= (pwmCMPA1 + pwm->DBFED))
{
pwmCMPA3 = (pwmCMPA2 - (pwmCMPA1 + pwm->DBFED)) / 2 + 1;
if(pwmCMPA3 < (pwm1->TBPRD>>1))
{
pwm1->CMPB = pwmCMPA3;
}
else
{
pwm1->CMPB = (pwm1->TBPRD>>1);
}
PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBDecr);
}
else
{
pwmCMPA3 = ((pwmCMPA1 + pwm->DBFED) - pwmCMPA2 ) / 2 + 1;
if(pwmCMPA3 < (pwm1->TBPRD>>1))
{
pwm1->CMPB = pwmCMPA3;
}
else
{
pwm1->CMPB = (pwm1->TBPRD>>1);
}
PWM_setSocAPulseSrc(obj->pwmHandle[PWM_Number_1],PWM_SocPulseSrc_CounterEqualCmpBIncr);
}

return;
} // end of HAL_setTrigger() function

非常感谢牛x的TI工程师,向您们学习,敬礼~

问题1:

iq Va_avg = (pPwmData->value[0]+pPwmData_prev->value[0])>>1;
_iq Vb_avg = (pPwmData->value[1]+pPwmData_prev->value[1])>>1;
_iq Vc_avg = (pPwmData->value[2]+pPwmData_prev->value[2])>>1;

为什么要求两次的平均?是单纯的滤波吗?

问题2:Voffset = (Vmid + Vmid_prev) - (Vlimit <<1);//

为什么要减去两次的值才是需要等到的偏置?

问题3:HAL_setTrigger函数中 

if(pwmCMPA2 >= (pwmCMPA1 + pwm->DBFED))
{
pwmCMPA3 = (pwmCMPA2 - (pwmCMPA1 + pwm->DBFED)) / 2 + 1;
if(pwmCMPA3 < (pwm1->TBPRD>>1))
{
pwm1->CMPB = pwmCMPA3;
}

的原理?

问题4:SVGEN_run()个函数的基本原理是什么?

  • static inline void SVGEN_run(SVGEN_Handle handle,const MATH_vec2 *pVab,MATH_vec3 *pT)
    {

    _iq Vmax,Vmin,Vcom;
    _iq Va,Vb,Vc;
    _iq Va_tmp = -(pVab->value[0]>>1);//-Ua/2
    _iq Vb_tmp = _IQmpy(SVGEN_SQRT3_OVER_2,pVab->value[1]);//√3/2*Ub

    Va = pVab->value[0]; //alpha
    Vb = Va_tmp + Vb_tmp; //-0.5*alpha + sqrt(3)/2 * beta;
    Vc = Va_tmp - Vb_tmp; //-0.5*alpha - sqrt(3)/2 * beta;

    Vmax=0;
    Vmin=0;
    //这样计算占空比的原因是为了和过调制进行衔接,如果换成传统的写法需要去自己写过调制的代码
    //具体参考公式 这本是 Advanced Electric Drives, Analysis, Control and Modeling using Simulink,
    //by Ned Mohan, MNPERE Press, Minneapolis, MN 55414, 2001, ISBN# 0-9715292-0-5
    // find order Vmin,Vmid,Vmax
    if (Va > Vb)
    {
    Vmax = Va;
    Vmin = Vb;
    }
    else
    {
    Vmax = Vb;
    Vmin = Va;
    }

    if (Vc > Vmax)
    {
    Vmax = Vc;
    }
    else if (Vc < Vmin)
    {
    Vmin = Vc;
    }

    Vcom = _IQmpy(Vmax+Vmin, _IQ(0.5));

    // Subtract common-mode term to achieve SV modulation
    pT->value[0] = (Va - Vcom);
    pT->value[1] = (Vb - Vcom);
    pT->value[2] = (Vc - Vcom);

    return;
    } // end of SVGEN_run() function

  • 您好我们已收到您的问题并升级到英文论坛,如有答复将尽快回复您。谢谢!

  • 为什么要求两次的平均?是单纯的滤波吗?

    是的。

    为什么要减去两次的值才是需要等到的偏置?

    因为PWM 为对称模式。

    问题3:HAL_setTrigger函数中 

    问题4:SVGEN_run()个函数的基本原理是什么?

    问题3和4:调整 PWM 占空比和 ADC 触发点来实现正确的电流值。 您可以参阅有关过调制的lab guide,该指南对此进行了详细说明。

    希望以上回答对您有所帮助,如有其他问题请随时联系我们。

  • 首先万分感谢您的回答,谢谢!

    inline _iq CTRL_angleDelayComp(CTRL_Handle handle, const _iq angle_pu)
    {
    CTRL_Obj *obj = (CTRL_Obj *)handle;
    //! _iq pu_to_khz_sf = _IQ(USER_IQ_FULL_SCALE_FREQ_Hz/1000.0);
    //! _iq khz_to_krpm_sf = _IQ(60.0/USER_MOTOR_NUM_POLE_PAIRS);
    //! _iq Mechanical_Freq_kHz = _IQmpy(EST_getFm_pu(handle),pu_to_khz_sf);
    //! _iq Speed_kRPM = _IQmpy(Mechanical_Freq_kHz,khz_to_krpm_sf);

    //_iq Mechanical_Freq_kHz = _IQmpy(EST_getFm_pu(handle),_IQ(USER_IQ_FULL_SCALE_FREQ_Hz/1000.0));

    _iq angleDelta_pu = _IQmpy(EST_getFm_pu(obj->estHandle),_IQ(USER_IQ_FULL_SCALE_FREQ_Hz/(USER_PWM_FREQ_kHz*1000.0)));


    _iq angleCompFactor = _IQ(1.0 + (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK * (float_t)USER_NUM_ISR_TICKS_PER_CTRL_TICK * ((float_t)USER_NUM_CTRL_TICKS_PER_EST_TICK - 0.5));
    _iq angleDeltaComp_pu = _IQmpy(angleDelta_pu, angleCompFactor);
    uint32_t angleMask = ((uint32_t)0xFFFFFFFF >> (32 - GLOBAL_Q));
    _iq angleTmp_pu;
    _iq angleComp_pu;

    // increment the angle
    angleTmp_pu = angleUncomp_pu + angleDeltaComp_pu;

    // mask the angle for wrap around
    // note: must account for the sign of the angle

    angleComp_pu = _IQabs(angleTmp_pu) & angleMask;

    // account for sign
    if(angleTmp_pu < 0)
    {
    angleComp_pu = -angleComp_pu;
    }

    return(angleComp_pu);
    }

    问题:_iq angleCompFactor = _IQ(1.0 + (float_t)USER_NUM_PWM_TICKS_PER_ISR_TICK * (float_t)USER_NUM_ISR_TICKS_PER_CTRL_TICK * ((float_t)USER_NUM_CTRL_TICKS_PER_EST_TICK - 0.5));

    假设所有的宏定义都为1,计算下一周期占空比应该最多延时1个pwm周期,为什么为1.5个?谢谢

  • 假设所有的宏定义都为1,计算下一周期占空比应该最多延时1个pwm周期,为什么为1.5个?谢谢

    您好,没有特殊的原因,您只要确保compensation delay大于控制频率且低于 PWM 频率就行。