TI中文支持网
TI专业的中文技术问题搜集分享网站

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()个函数的基本原理是什么?

zheng decai:

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

,

Cherry Zhou:

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

,

Cherry Zhou:

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

是的。

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

因为PWM 为对称模式。

zheng decai 说:问题3:HAL_setTrigger函数中 

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

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

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

,

zheng decai:

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

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个?谢谢

,

Cherry Zhou:

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

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

赞(0)
未经允许不得转载:TI中文支持网 » InstaSPIN-FOC 关于SVGENCURRENT_compPwmData()、SVGEN_run()、HAL_setTrigger()函数的实现原理
分享到: 更多 (0)