VF/IF斜坡强拖(浮点、定点)代码
VF强拖就是电压开环强拖,给定一个固定的Ud和Uq,然后执行反Park变换和SVPWM(此时不需要执行完整的FOC环路,最易实现),IF强拖则是给定一个固定的id_ref和iq_ref,然后执行FOC电流环让id和iq逐渐接近给定的id_ref和iq_ref(此时需要保证电流环的PID参数是合理的,稍微复杂,但比VF强拖更稳定);/************* 斜坡强拖具体代码实现(浮点和定点)**
·
VF强拖和IF强拖介绍:
强拖就是人工给定电角度,斜坡强拖就是电角度增加的速度不是固定的而是缓慢增加的,直到最后电角度的速度增加到给定速度为止;VF强拖就是电压开环强拖,给定一个固定的Ud和Uq,然后执行反Park变换和SVPWM(此时不需要执行完整的FOC环路,最易实现),IF强拖则是给定一个固定的id_ref和iq_ref,然后执行FOC电流环让id和iq逐渐接近给定的id_ref和iq_ref(此时需要保证电流环的PID参数是合理的,稍微复杂,但比VF强拖更稳定);
不管是VF强拖还是IF强拖,本质都是不去获取真实电角度,而是人为给定一个电角度,在无法获取准确电角度又想让电机转动的情况下可以使用;
/************* 斜坡强拖具体代码实现 (浮点和定点)*****************/
/*RPM_ref
*/
#define PWM_Time 100 //FOC中断执行间隔时间,单位us
uint32_t IF_VF_RUN(uint16_t RPM_ref, uint16_t Time_ms)
{
static float Angular_Speed;
static float Angular_Angle = 0;
uint64_t Angular_Speed_ref = (uint64_t)(RPM_ref)*65536ULL/60ULL*(uint64_t)Hall_Three.Poles; //计算目标电角速度 Q16格式的 rad/s
uint32_t IF_FOC_num = (uint32_t)Time_ms*1000 / PWM_Time; //爬坡过程FOC中断次数
uint32_t Angular_Speed_step = Angular_Speed_ref / IF_FOC_num; //每次FOC中断的爬坡电角速度步进值
Angular_Speed += Angular_Speed_step; //计算本次电角速度
if( Angular_Speed >= Angular_Speed_ref)
Angular_Speed = Angular_Speed_ref;
Angular_Angle = Angular_Angle + Angular_Speed * (float)Hall_Three.Speed_PWM_Time / 1000000; //计算本次电角度
if(Angular_Angle >= 65536)
Angular_Angle -= 65536;
uint32_t Angular_Angle_Q16 = (uint32_t)(Angular_Angle); //将电角度转换为Q15格式
return Angular_Angle_Q16; //返回Q16格式的电角度
}
#define Two_PI 6.28318530718f
float IF_VF_RUN_Float(float RPM_ref, float Time_ms)
{
Angular_Speed_ref = RPM_ref*6.28f/60.0f*Pole; //计算目标电角速度
IF_FOC_num = Time_ms * 1000 / (float)PWM_Time; //爬坡过程FOC中断次数
Angular_Speed_step = Angular_Speed_ref / IF_FOC_num; //每次FOC中断的爬坡电角速度步进值
Angular_Speed += Angular_Speed_step; //计算本次电角速度
if( Angular_Speed >= Angular_Speed_ref)
Angular_Speed = Angular_Speed_ref;
Angular_Angle = Angular_Angle + Angular_Speed * 50.0f / 1000000.0f; //计算本次电角度
if(Angular_Angle >= Two_PI)
Angular_Angle -= Two_PI;
return Angular_Angle; //返回电角度
}
实际使用案例:
VF强拖就是直接在电流环PID控制后面给一个固定的Ud和Uq,IF强拖则是在电流环PID控制前面给定一个固定的iq_ref和id_ref
/*FOC中断*/
void HAL_ADCEx_InjectedConvCpltCallback( ADC_HandleTypeDef *hadc)
{
/*********************** 1、Processing Eleangle ***************************/
Predict_eleangle = VF_IF_RUN_Float(600.0f, 6000.0f); //强拖提供电角度
/*********************** 2、Processing ADC ***************************/
adc1_in1 = ADC1->JDR1;
adc2_in2 = ADC2->JDR1;
foc_abc_current_i.ia = ((float)adc1_in1 - ADCSampPare.OffsetPhaseU_Curr) * 0.0201416f;
foc_abc_current_i.ib = ((float)adc2_in2 - ADCSampPare.OffsetPhaseV_Curr) * 0.0201416f; //3.3/4096 /(40V/V) / (0.001Ω)
foc_abc_current_i.ic = - foc_abc_current_i.ia - foc_abc_current_i.ib;
/*********************** FOC Algorithm ***************************/
Angle_Sin_Cos(Predict_eleangle, &foc_sin_cos); //
Clark(foc_abc_current_i, &foc_alpha_beta_i);
Park(foc_alpha_beta_i, foc_sin_cos, &foc_dq_i);
foc_dq_i.iq = Lpf(foc_dq_i.iq, foc_dq_i.iq_last,0.8f);
foc_dq_i.iq_last = foc_dq_i.iq;
foc_dq_i.id = Lpf(foc_dq_i.id, foc_dq_i.id_last,0.8f);
foc_dq_i.id_last = foc_dq_i.id;
current_q_pid.fbk = foc_dq_i.iq;
current_d_pid.fbk = foc_dq_i.id;
// current_q_pid.ref = 0.1f; //电流强拖
// current_d_pid.ref = 0.0f;
current_pid_Control(¤t_q_pid);
current_pid_Control(¤t_d_pid);
// foc_dq_v.vq = 1.0f; //电压强拖
// foc_dq_v.vd = 0.0f;
Reverse_Park(foc_sin_cos, foc_dq_v, &foc_alpha_beta_v);
/*Overmodulation prevention*/
RevPark_Circle_Limitation_cmsis(&foc_alpha_beta_v.v_alpha, &foc_alpha_beta_v.v_beta,
Udc, 0.95f);
Foc_Svpwm(foc_alpha_beta_v, &foc_pwm, Udc, PWM_PERIOD);
TIM1->CCR1 = foc_pwm.pwm_u;
TIM1->CCR2 = foc_pwm.pwm_v;
TIM1->CCR3 = foc_pwm.pwm_w;
}
}
更多推荐



所有评论(0)