基于DSP280049C的正点原子PMSM电机驱动(二):FOC文件的建立与开环代码编写

FOC.h文件的建立

FOC头文件中,主要放入源文件中将会用到的部分参数值,以及电机相关的参数。

/*
 * FOC.h
 *
 *  Created on: 2023年7月10日
 *      Author: 24460
 */

#ifndef USER_INC_FOC_H_
#define USER_INC_FOC_H_

#include "driverlib.h"
#include "device.h"

/*常用数学值*/
#define pi      3.14159                 //pi
#define pi_2    6.28318                 //2*pi
#define pi_180  0.01745                 //2*pi/360
#define sqrt3   1.73205                 //sqrt(3)
#define sqrt3_2 0.86603                 //sqrt(3)/2
#define sqrt23  0.81649                 //sqrt(2/3)
#define sqrt24  0.70710                 //sqrt(2/4)

/*逆变器相关参数*/
#define Udc     24                      //母线电压
#define fsw     5000                    //MOSFET开关频率,也是PWM的周期频率
#define Ts      0.0002                  //MOSFET开关时间,也是PWM的周期时间,200us
#define K       (sqrt3*Ts)/Udc          //SVPWM中间参数
#define K_park  0.6667                  //clark以及park变换为等大小变换

/*PMSM参数*/
#define rpm_rated   3000    //电机额定机械转速
#define Ed          0.0043  //反电动势系数:0.0043v/rpm
#define Pn          8/2     //极对数
#define R           1.02    //定子电阻,单位为Ω
#define L           0.00059  //定子电感
#define Ld          0.00059  //直轴电感0.59mH
#define Lq          0.00059  //交轴电感0.59mH

void Open_FOC_contral(void);

#endif /* USER_INC_FOC_H_ */

FOC.c文件的建立

FOC源文件中主要是FOC控制的计算过程,并且以函数的形式能够被PWM中断周期性的调用。

/*
 * FOC.c
 *
 *  Created on: 2023年7月10日
 *      Author: 24460
 */

#include "F28x_Project.h"
#include "IQmathLib.h"
#include "FOC.h"
#include "PWM.h"

void Open_FOC_contral(void)
{
    //电流参数
    static _iq ia;static _iq ib;static _iq ic;
    static _iq ialpha;static _iq ibeta;
    static _iq id;static _iq iq;
    //电压参数
    static _iq ua;static _iq ub;static _iq uc;
    static _iq ualpha;static _iq ubeta;
    static _iq ud;static _iq uq;
    //磁通参数定义
    static _iq phi_a;static _iq phi_b;static _iq phi_c;
    static _iq phi_alpha;static _iq phi_beta;
    static _iq phi_d;static _iq phi_q;

    //运行状态参数
    static _iq now_Etheta = _IQ(0);              //当前的电角度值
    static _iq now_Mtheta = _IQ(0);              //当前的机械角度值

    //SVPWM相关参数
    static _iq cos_Etheta;              //当前电角度的cos值,用以坐标变换
    static _iq sin_Etheta;              //当前电角度的sin值,用以坐标变换
    _iq u1;_iq u2;_iq u3;               //中间计算变量
    float U1;  float U2;  float U3;                             //SVPWM电压计算的中间变量
    int A;int B;int C;int N;                                    //扇区判断的中间变量
    float T[8];                                                 //各方向向量作业时间
    float Fu;float Fv;float Fw;                                 //uvw上桥臂置高时间
    float Tu;float Tv;float Tw;                                 //Fu,Fv,Fw与Ts的比值
    /*SVPWM相关参数end*/


    /*************************函数程序开始位置*********************************/
    now_Etheta = now_Etheta + _IQmpy( _IQ(5) , _IQ(pi_180) );  //开环控制,角度自增,每周期增加n°
    cos_Etheta = _IQcos(now_Etheta);
    sin_Etheta = _IQsin(now_Etheta);
    ud = _IQ(0);
    uq = _IQ(5);

    ualpha = _IQmpy( ud , cos_Etheta ) - _IQmpy( uq , sin_Etheta ) ;
    ubeta = _IQmpy( uq , cos_Etheta ) + _IQmpy( ud , sin_Etheta ) ;
    u1 = ubeta;
    u2 = _IQmpy( _IQ(sqrt3_2) , ualpha ) - _IQmpy(_IQ(0.5) , ubeta);
    u3 = _IQmpy( _IQ(-sqrt3_2) , ualpha ) - _IQmpy(_IQ(0.5) , ubeta);
    U1 = _IQtoF(u1);U2 = _IQtoF(u2);U3 = _IQtoF(u3);

    if (U1 > 0)  {A=1;} else {A=0;}
    if (U2 > 0)  {B=1;} else {B=0;}
    if (U3 > 0)  {C=1;} else {C=0;}
    N=4*C+2*B+A;

    switch (N){
            case 1://第二扇区
                T[2]=-K*U3;
                T[6]=-K*U2 ;
                if ( T[2]+T[6]>Ts)
                {
                    T[2]=T[2]*Ts/(T[2]+T[6]);
                    T[6]=T[6]*Ts/(T[2]+T[6]);
                }
                T[0]=(Ts-T[2]-T[6])/2;
                T[7]=T[0];
                T[1]=0.0;
                T[3]=0.0;
                T[4]=0.0;
                T[5]=0.0;
                Fu=T[6]+T[7];
                Fv=T[2]+T[6]+T[7];
                Fw=T[7];
                break;
            case 2://第六扇区
                T[4]=-K*U2;
                T[5]=-K*U1 ;
                if ( T[4]+T[5]>Ts)
                {
                    T[4]=T[4]*Ts/(T[4]+T[5]);
                    T[5]=T[5]*Ts/(T[4]+T[5]);
                }
                T[0]=(Ts-T[4]-T[5])/2;
                T[7]=T[0];
                T[2]=0.0   ;
                T[6]=0.0    ;
                T[1]=0.0               ;
                T[3]=0.0;
                Fu=T[4]+T[5]+T[7];
                Fv=T[7];
                Fw=T[5]+T[7];
                break;
            case 3://第一扇区
                T[4]=K*U3;
                T[6]=K*U1 ;
                if ( T[4]+T[6]>Ts)
                {
                    T[4]=T[4]*Ts/(T[4]+T[6]);
                    T[6]=T[6]*Ts/(T[4]+T[6]);
                }
                T[0]=(Ts-T[4]-T[6])/2;
                T[7]=T[0];
                T[1]=0.0;
                T[2]=0.0;
                T[3]=0.0;
                T[5]=0.0;
                Fu=T[4]+T[6]+T[7];
                Fv=T[6]+T[7];
                Fw=T[7];
                break;
            case 4://第四扇区
                T[1]=-K*U1;
                T[3]=-K*U3 ;
                if ( T[1]+T[3]>Ts)
                {
                    T[1]=T[1]*Ts/(T[1]+T[3]);
                    T[3]=T[3]*Ts/(T[1]+T[3]);
                }
                T[0]=(Ts-T[1]-T[3])/2;
                T[7]=T[0];
                T[2]=0.0   ;
                T[6]=0.0    ;
                T[4]=0.0               ;
                T[5]=0.0;
                Fu=T[7];
                Fv=T[3]+T[7];
                Fw=T[1]+T[3]+T[7];
                break;
            case 5://第三扇区
                T[2]=K*U1;
                T[3]=K*U2;
                if ( T[2]+T[3]>Ts)
                {
                    T[2]=T[2]*Ts/(T[2]+T[3]);
                    T[3]=T[3]*Ts/(T[2]+T[3]);
                }
                T[0]=(Ts-T[2]-T[3])/2;
                T[7]=T[0];
                T[1]=0.0;
                T[6]=0.0;
                T[4]=0.0;
                T[5]=0.0;
                Fu=T[7];
                Fv=T[2]+T[3]+T[7];
                Fw=T[3]+T[7];
                break;
            case 6://第五扇区
                T[1]=K*U2;
                T[5]=K*U3 ;
                if ( T[1]+T[5]>Ts)
                {
                    T[1]=T[1]*Ts/(T[1]+T[5]);
                    T[5]=T[5]*Ts/(T[1]+T[5]);
                }
                T[0]=(Ts-T[1]-T[5])/2;
                T[7]=T[0];
                T[2]=0.0   ;
                T[6]=0.0    ;
                T[4]=0.0               ;
                T[3]=0.0;
                Fu=T[5]+T[7];
                Fv=T[7];
                Fw=T[1]+T[5]+T[7];
                break;
            default :
                break;
        }
        /*以上为电压矢量及其作用时间计算过程*/
        Tu=Fu/Ts;Tv=Fv/Ts;Tw=Fw/Ts;

}

到此,FOC开环控制的程序逻辑基本上明了了,但是此时仅仅是得到了三相桥上桥臂的占空比,下一步就是要配置PWM,并在每个周期中将占空比代入。

基于DSP280049C的电机驱动系列回顾:

(一):CCS文件夹的建立与IQmath导入
(二):FOC文件的建立与开环代码编写

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
svpwm是一种常见的PWM控制方法,用于三相交流电机驱动。在Matlab中,我们可以使用Simulink的sfunction编写svpwm模型。以下是一个示例模型: 1. 首先,在Simulink中创建一个新的模型。 2. 添加一个S-Function块。这个块将用于编写svpwm代码。 3. 在S-Function块的参数设置中,选择“S-Function Builder”。 4. 在S-Function Builder中,选择“C MEX S-Function”。 5. 在“Source file(s)”中添加svpwm.c文件。 6. 在“Header file(s)”中添加svpwm.h文件。 7. 在“Simulation parameters”中添加所需的模型参数。 8. 在“Ports and data types”中定义输入和输出端口。 9. 编写svpwm.c文件代码,包括svpwm函数和其他必要函数。 10. 将svpwm.c和svpwm.h文件保存到同一个文件夹中。 11. 在模型中添加其他必要的块和连接。 12. 运行模型进行仿真。 下面是一个svpwm的示例函数: ```c #include "svpwm.h" void svpwm(double Ualpha, double Ubeta, double theta, double *Ua, double *Ub, double *Uc) { double Ud, Uq, Us, Ta, Tb, Tc; double sin_theta, cos_theta; // Clarke transform Ud = Ualpha; Uq = -0.5*Ualpha + 0.866*Ubeta; // Park transform sin_theta = sin(theta); cos_theta = cos(theta); Us = Ud*cos_theta - Uq*sin_theta; Ua = Us; Us = Ud*sin_theta + Uq*cos_theta; Ub = -0.5*Us - 0.866*Uq; Uc = -0.5*Us + 0.866*Uq; // SVM Ta = (2/3)*Ua; Tb = (2/3)*Ub; Tc = (2/3)*Uc; if (Ta > 1) Ta = 1; if (Ta < -1) Ta = -1; if (Tb > 1) Tb = 1; if (Tb < -1) Tb = -1; if (Tc > 1) Tc = 1; if (Tc < -1) Tc = -1; *Ua = Ta; *Ub = Tb; *Uc = Tc; } ``` 在svpwm.c中,我们首先进行Clarke变换和Park变换,然后使用SVM方法计算输出。最后,我们将输出值存储在Ua,Ub和Uc中。 在svpwm.h文件中,我们定义了函数的输入和输出参数: ```c void svpwm(double Ualpha, double Ubeta, double theta, double *Ua, double *Ub, double *Uc); ``` 在Simulink中,我们可以使用S-Function块调用svpwm函数,并将其连接到其他块和模型中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tony0925

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值