双三相永磁同步电机双闭环FOC控制,转速环、电流环的PI限幅及参数整定

记录DSP做主控,双三相电机双闭环FOC控制,实验过程中有关PI控制器相关知识。

电机参数:Ld,Lq,极对数pn,永磁体磁链faif。直流母线电压vbus。DSP采样时间Ts。

一、PI控制器类型:并联型PI控制

/*并联型PI控制器的误差及积分误差*/
speed_error=speed_ref-PMSM.speed_m;
speed_integral+=speed_error*0.0001;

/*积分误差限幅设定*/
if(speed_integral > speed_integral_max)
{
    speed_integral = speed_integral_max;
}
else if(speed_integral < -speed_integral_max)
{
    speed_integral = -speed_integral_max;
}

/*转速环PI控制器输出*/
speed_PI = speed_kp*speed_error + speed_ki*speed_integral;

/*PI控制器输出限幅设定*/
if(speed_PI > speed_PI_max)
{
    iq_ref1 = speed_PI_max;
}
else if(speed_PI < -speed_PI_max)
{
    iq_ref1 = -speed_PI_max;
}
else
{
    iq_ref1 = speed_PI;
}

并联型PI控制器的代码如上所示。可以看出,除了误差和积分误差,以及控制器输出公式以外,有两个限幅值需要设定,分别为:积分误差限幅,PI控制器输出限幅。

二、转速环限幅值设定原理

1、转速环PI控制器输出限幅(固定值):转速环输出为内环电流环的参考值,即iq_ref。有以下两种建议:

①根据电机额定电流12A,设定输出限幅为10A,防止电流过大烧电机;

②根据电机额定功率如:9.5N·m,设定iq = Te/3/pn/faif = 6.81A(这个值可以稍微放开点儿)。

speed_PI_max = 10;        //转速环输出限幅,固定值

2、转速环PI控制器积分误差限幅(动态限幅):在电机运行进入稳态过程中,error为零,比例几乎不发挥作用,主要是积分发生作用。为了让积分具有有效的调节效果,动态限幅设定为:

speed_integral_max = 10/speed_ki;	

根据PI控制器的输出公式可知,当前项比例值为0时,后项积分环输出的最大值与PI控制器输出限幅值相等。这意味着,积分误差最大值不会超过PI控制器限幅,保证积分环在不饱和时,可以有效发挥消除静差的作用(饱和也没事)。

三、电流环限幅值设定原理

1、电流环PI控制器输出限幅(动态限幅):电流环输出为dq坐标系下的电压,即vq_ref,vd_ref。在三相电机内,我们已知以下关系:

\sqrt{v_{d}^{2}+v_{q}^{2}}\leq \frac{\sqrt{3}}{3}*v_{bus}                                                              (1)

这表明在三相电机内,理论上来说,电流环的输出不能超过六边形的内切圆半径,从而保证线性调制。在双三相电机中,理论计算也可以得出这样一个值,但是实际过程中,嗯。。我们不限制这么多了,给出一个近似量即可:

iq_PI_max1=vbus*0.9;		
id_PI_max1=vbus*0.9;		
ix_PI_max1=vbus*0.09;		
iy_PI_max1=vbus*0.09;

2、电流环PI控制器积分误差限幅(动态限幅):与转速环原理一样,为了让积分环有效发挥作用,积分误差最大值应为PI控制器能够输出的最大值:

iq_integral_max1 = vbus*0.9/iq_ki1;	
id_integral_max1 = vbus*0.9/id_ki1;	
ix_integral_max1 = vbus*0.09/ix_ki1;	
iy_integral_max1 = vbus*0.09/iy_ki1;

到此PI控制器的两个输出限幅就记录完毕了。下面进入参数整定。

四、PI控制器参数整定

同样的,在三相电机内,理论计算Kp和Ki值为:

K_{p} = L_{d}/2T_{s}                                                                     (2)

K_{i} = R/2T_{s}                                                                      (3)

理论上,在双三相电机内,参数设定值近似就可以了。

实际过程中,经验调试会把比例值 = 0.1,积分值 = 0.01(让积分环慢点作用)。然后比例值以1量度增加,增加到近似理论计算5左右,同时慢慢放开积分值,0.02、0.05......可以获得比较好的PI控制器跟踪效果。

操作顺序是:先调节内环电流环闭环,然后调节外环转速换闭环,最后达到的效果是:更改iq_ref,iq能够实现很好的跟踪;更改参考转速,转速能够实现稳定跟踪。


如果此篇文章对您有帮助,记得评论告诉我(●'◡'●)
您的点赞和收藏是对写作者最大的鼓励!
  • 22
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的永磁同步电机FOC控制转速电流环的C代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define PI 3.14159265358979 // 定义结构体存储电机参数 typedef struct { double Rs; // 马达定子电阻 double Ld; // 马达定子d轴电感 double Lq; // 马达定子q轴电感 double J; // 马达转动惯量 double P; // 马达极数 double Ke; // 电动势常数 double Kt; // 转矩常数 double Tm; // 额定负载转矩 double rated_speed; // 额定转速 } MotorParam; // 定义结构体存储FOC控制器参数 typedef struct { double Ts; // 采样时间 double Kp; // 比例系数 double Ki; // 积分系数 double Kc; // 当前PID控制器比例系数 double Kd; // 当前PID控制器微分系数 double speed_ref; // 目标转速 double current_ref; // 目标电流 double Id; // 直轴电流 double Iq; // 交轴电流 double Ia; // A相电流 double Ib; // B相电流 double Ic; // C相电流 double Va; // A相电压 double Vb; // B相电压 double Vc; // C相电压 double speed; // 实际转速 double theta_e; // 电角度 double theta_m; // 机械角度 double theta_m_old; // 上一次的机械角度 double error_speed; // 转速误差 double error_current;// 电流误差 double integral_speed;// 转速积分 double integral_current;// 电流积分 double u_d; // 直轴电压 double u_q; // 交轴电压 double u_alpha; // α轴电压 double u_beta; // β轴电压 } FOCParam; // 计算矢量旋转 void SVPWM(double u_alpha, double u_beta, double theta_e, double* t1, double* t2, double* t0) { double ta, tb, tc; double ua, ub, uc; double cos_theta = cos(theta_e); double sin_theta = sin(theta_e); ua = u_alpha * cos_theta + u_beta * sin_theta; ub = -u_alpha * sin_theta + u_beta * cos_theta; uc = -ua - ub; ta = (1.0 / sqrt(3)) * (ua - 0.5 * ub - 0.5 * uc); tb = (1.0 / sqrt(3)) * (ub - 0.5 * ua - 0.5 * uc); tc = (1.0 / sqrt(3)) * (uc - 0.5 * ua - 0.5 * ub); *t1 = 0.5 * (1.0 - ta - tb); *t2 = 0.5 * (1.0 - tb - tc); *t0 = 0.5 * (1.0 - tc - ta); } // FOC控制器 void FOCControl(MotorParam* motor, FOCParam* foc) { double omega_r; // 转子电角速度 double T_r; // 电磁转矩 double T_e; // 机械转矩 double theta_r; // 转子电角度 double theta_m; // 机械角度 double dIq; // 交轴电流变化量 double dId; // 直轴电流变化量 double u_alpha, u_beta; double t1, t2, t0; double u_d_old, u_q_old; double Ta, Tb, Tc; // 计算转矩 omega_r = foc->speed / motor->P; T_r = motor->Ke * (foc->Iq * sin(foc->theta_e) - foc->Id * cos(foc->theta_e)); T_e = T_r - motor->Tm; dIq = foc->Ki * foc->Ts * (foc->current_ref - foc->Iq); dId = foc->Ki * foc->Ts * (0.0 - foc->Id); foc->Iq += dIq; foc->Id += dId; // 计算电角度和机械角度 theta_r = foc->theta_e + motor->P * omega_r * foc->Ts; theta_m = theta_r / motor->P; foc->theta_m = fmod(theta_m, 2.0 * PI); if (foc->theta_m < 0.0) { foc->theta_m += 2.0 * PI; } // 转速控制 foc->error_speed = foc->speed_ref - foc->speed; foc->integral_speed += foc->error_speed * foc->Ts; foc->u_q = foc->Kp * foc->error_speed + foc->Ki * foc->integral_speed; foc->u_q = fmax(fmin(foc->u_q, 10.0), -10.0); // 电流控制 foc->error_current = foc->current_ref - foc->Iq; foc->integral_current += foc->error_current * foc->Ts; foc->u_d = foc->Kp * foc->error_current + foc->Ki * foc->integral_current; foc->u_d = fmax(fmin(foc->u_d, 10.0), -10.0); // 转换到直交坐标系 u_alpha = foc->u_d * cos(foc->theta_e) - foc->u_q * sin(foc->theta_e); u_beta = foc->u_d * sin(foc->theta_e) + foc->u_q * cos(foc->theta_e); // 计算SVPWM波形 SVPWM(u_alpha, u_beta, foc->theta_e, &t1, &t2, &t0); // 更新电压 foc->u_alpha = u_alpha; foc->u_beta = u_beta; // 计算电流 Ta = motor->Kt * (t1 - 0.5 * t2 - 0.5 * t0); Tb = motor->Kt * (t2 - 0.5 * t0 - 0.5 * t1); Tc = motor->Kt * (t0 - 0.5 * t1 - 0.5 * t2); foc->Ia = Ta / motor->Ke; foc->Ib = Tb / motor->Ke; foc->Ic = Tc / motor->Ke; // 计算电角度 foc->theta_e += omega_r * foc->Ts; // 保存直轴电压 u_d_old = foc->u_d; u_q_old = foc->u_q; // 计算直轴电压 foc->u_d = foc->Kp * (foc->Id - (motor->Ld / motor->Rs) * foc->Ia) - foc->Kc * (foc->u_d - u_d_old) / foc->Ts; foc->u_d = fmax(fmin(foc->u_d, 10.0), -10.0); // 计算交轴电压 foc->u_q = foc->Kp * (foc->Iq - (motor->Lq / motor->Rs) * foc->Ib) - foc->Kc * (foc->u_q - u_q_old) / foc->Ts; foc->u_q = fmax(fmin(foc->u_q, 10.0), -10.0); // 更新电流 dIq = foc->Ki * foc->Ts * (foc->current_ref - foc->Iq); dId = foc->Ki * foc->Ts * (foc->u_d - foc->Id); foc->Iq += dIq; foc->Id += dId; } // 主函数 int main() { MotorParam motor; FOCParam foc; // 初始化电机参数 motor.Rs = 1.0; motor.Ld = 0.01; motor.Lq = 0.02; motor.J = 0.1; motor.P = 4; motor.Ke = 0.1; motor.Kt = 0.1; motor.Tm = 0.0; motor.rated_speed = 2000.0; // 初始化FOC控制器参数 foc.Ts = 0.0001; foc.Kp = 0.1; foc.Ki = 50.0; foc.Kc = 0.1; foc.Kd = 0.0; foc.speed_ref = 1000.0; foc.current_ref = 1.0; foc.Id = 0.0; foc.Iq = 0.0; foc.Ia = 0.0; foc.Ib = 0.0; foc.Ic = 0.0; foc.Va = 0.0; foc.Vb = 0.0; foc.Vc = 0.0; foc.speed = 0.0; foc.theta_e = 0.0; foc.theta_m = 0.0; foc.theta_m_old = 0.0; foc.error_speed = 0.0; foc.error_current = 0.0; foc.integral_speed = 0.0; foc.integral_current = 0.0; foc.u_d = 0.0; foc.u_q = 0.0; foc.u_alpha = 0.0; foc.u_beta = 0.0; // 模拟FOC控制 for (int i = 0; i < 10000; i++) { FOCControl(&motor, &foc); foc.speed = motor.rated_speed * motor.P * (foc.theta_m - foc.theta_m_old) / (2.0 * PI * foc.Ts); foc.theta_m_old = foc.theta_m; printf("%lf,%lf,%lf,%lf\n", foc.speed, foc.current_ref, foc.Iq, foc.u_q); } return 0; } ``` 这段代码实现了一个简单的FOC控制器,包括转速电流环控制。在`FOCControl`函数,我们首先计算电机转矩和角度,然后进行转速和电流控制,最后计算SVPWM波形,更新电压和电流。在主函数,我们模拟了10000个采样周期,每个周期的时长为0.0001秒,输出了转速、目标电流、实际电流和交轴电压。 需要注意的是,这段代码仅供参考,实际应用需要根据具体电机和控制器参数进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值