永磁同步电机的矢量控制策略(八)一一一仿真模型搭建与源代码

8.永磁同步电机的矢量控制策略(八)

在前面的博客已经讲到电机本体的Simulink模型搭建,其中能够自定义电机的库模型,或者直接经过仿真器件进行搭建均可以。这部份内容能够参考前面的内容:电机的数学模型永磁同步电机的矢量控制策略(二)一一一数学模型html

8.1SVPWM的仿真模型搭建

按照SVPWM的实现流程进行仿真模型搭建,如图1所示。
在这里插入图片描述
图1 SVPWM的仿真模型web

对应于专门讲解SVPWM控制波形产生的:SVPWM控制算法

如下附上DSP上专门这块的SVPWM控制C++代码:
先定义函数名称及功能编程

#ifndef  Svpwm_dq_H
#define  Svpwm_dq_H
#include "DSP2833x_Project.h"
#include "IQmathLib.h"

typedef struct 	{ _iq  Ualpha; 	//  二相静止坐标系alpha-轴
				  _iq  Ubeta;	//  二相静止坐标系beta-轴
				  _iq  Ta;		//  三相矢量占空比Ta
				  _iq  Tb;		//  三相矢量占空比Tb
				  _iq  Tc;		//  三相矢量占空比Tc
				  _iq  tmp1;	//  三相静止坐标系的电压temp1
				  _iq  tmp2;	//  三相静止坐标系的电压temp2
				  _iq  tmp3;	//  三相静止坐标系的电压temp3
				  Uint16 VecSector;	 //矢量空间扇区号
				} SVPWM , *p_SVPWM ;

#define SVPWM_DEFAULTS  { 0,0,0,0,0,0,0,0,0}  // 初始化参数

extern SVPWM     Svpwmdq;

void  SVPWM_Cale(p_SVPWM pV); // svpwm调制算法函数

#endif /* Svpwm_dq*/

再而后接着按SVPWM的输出进行功能函数的编程以下:svg

#include "Main_PMSM_QEncoder.h"

SVPWM        Svpwmdq=SVPWM_DEFAULTS;

// SVPWM是7段式矢量调试,扇区与输出电压占空比通过简化后为对称输出,1和4,2和5,3和6对称
// 文档给出是按照7段式SVPWM一点点按照矢量调制原理推到,中间推到有Uabc的三相电压
// T1和T1做用时间,Txyz时间最终等效Tabc三相输入占空比,
// Udc/√3=1=IQ(1.0), 是调制最大电1 是等效为IQ24是16777216  电压利用率是100%,算死区计算2*1.8=3.6/80us=4.5%
// 调制利用率等于(1-0.045)=0.955=95.5%   约等于31000
// Ualpha和Ubeta是和uq ud等幅值变换因此都是-32767到32768

void  SVPWM_Cale(p_SVPWM  pV)
{
    pV->tmp1= pV->Ubeta;   // 至关于二相静止坐标--到三相静止变换出Uabc
	pV->tmp2= _IQdiv2(pV->Ubeta) + (_IQmpy(_IQ(0.866),pV->Ualpha));
    pV->tmp3= pV->tmp2 - pV->tmp1;

	pV->VecSector=3;   // 根据三相电压符号计算矢量扇区
	pV->VecSector=(pV->tmp2> 0)?( pV->VecSector-1):pV->VecSector;
	pV->VecSector=(pV->tmp3> 0)?( pV->VecSector-1):pV->VecSector;
	pV->VecSector=(pV->tmp1< 0)?(7-pV->VecSector) :pV->VecSector;

	if     (pV->VecSector==1 || pV->VecSector==4)   // 根据矢量扇区计算矢量占空比Tabc
      {     pV->Ta= pV->tmp2;
      		pV->Tb= pV->tmp1-pV->tmp3;
      		pV->Tc=-pV->tmp2;
      }

    else if(pV->VecSector==2 || pV->VecSector==5)
      {     pV->Ta= pV->tmp3+pV->tmp2;
      		pV->Tb= pV->tmp1;
      		pV->Tc=-pV->tmp1;
      }

    else
      {     pV->Ta= pV->tmp3;
      		pV->Tb=-pV->tmp3;
      		pV->Tc=-(pV->tmp1+pV->tmp2);
      }
}

SVPWM的输出图形当时在作实验的时候没有记录保存,后续若是容许我更新补充哈,详细结合实验步骤来分析波形特色。函数

8.2电流环的仿真模型搭建

没有含有PWM生成的模块,仅含有电流环和转速环的控制,针对数学模型的推导与创建。输出波形如图3所示。
在这里插入图片描述
图2 转速环和电流环的电机控制模型oop

在这里插入图片描述
图3 电机控制相应量的输出波形:q-d轴电流、转速学习

从图3可看出,依据坐标变换的矢量解耦控制,d轴电流最终趋向于0,q轴最终趋于一个稳定值,这个与坐标变换里面所讲到的结论是一致的。你们能够参考下这个:坐标变换ui

下面给出DSP上专门这块的SVPWM控制C++代码:.net

#ifndef  PI_Cale_H
#define  PI_Cale_H
#include "IQmathLib.h"

typedef struct {
        _iq  Ref;   // PI控制的给定参数
        _iq  Fbk;   // PI控制的反馈参数
        _iq  Out;   // PI控制的输出参数
        _iq  OutF;  // PI控制的滤波后输出参数
        _iq  Kp;        // PI控制的比例参数
        _iq  Ki;        // PI控制的积分参数
        _iq  Umax;  // PI控制的输出限制最大幅值参数
        _iq  Umin;  // PI控制的输出限制最小幅值参数
        _iq  up;        // PI控制的比例项输出参数
        _iq  ui;        // PI控制的积分项输出参数
        _iq  v1;        // PI控制的历史输出项参数
        _iq  i1;        // PI控制的历史积分项输出参数
       } PI_Control, *p_PI_Control ;

#define PI_Control_DEFAULTS {0,0,0,0,0,0,_IQ(1.0),0,0,0,0,0} // 初始化参数

extern  PI_Control     pi_spd  ;
extern  PI_Control     pi_id   ;
extern  PI_Control     pi_iq   ;

void  PI_Controller(p_PI_Control  pV);  //PI控制算法函数
void  PI_Pare_init(void );    //PI控制参数初始化

#endif /* PI_Cale*/

具体的功能函数给出以下:

#include "Main_PMSM_QEncoder.h"

PI_Control   pi_spd = PI_Control_DEFAULTS;
PI_Control   pi_id  = PI_Control_DEFAULTS;
PI_Control   pi_iq  = PI_Control_DEFAULTS;

// 此程序PID是软件文档介绍有区别,文档写出基本PID公式算法
// 此PID省略D,同时加入抗积分保护算法,
// 判断PI输出结果是否被限制,达到限制后,这积分保持历史状态,不在累加
// 参考网上抗积分饱和原理 https://blog.csdn.net/qq_22520215/article/details/72896637
// 能够采用抗积分饱和算法,其思路就是:若是上一次的输出控制量超过了饱和值,饱和值为正,
// 则这一次只积分负的误差,饱和值为负,则这一次只积分正的误差,从而避免系统长期留在饱和区!

void  PI_Controller(p_PI_Control  pV)
{
    /* proportional term */
	pV->up = pV->Ref - pV->Fbk;

	/* integral term */
	pV->ui = (pV->Out == pV->v1)?(_IQmpy(pV->Ki, pV->up)+ pV->i1) : pV->i1;
	pV->i1 = pV->ui;  // 输出值达到保护输出值就锁定积分值不在累加

	/* control output*/
	pV->v1 = _IQmpy(pV->Kp, (pV->up )) + pV->ui; //  _IQmpy 是移位2…^24次方 因此Kp/16777216
	pV->Out= _IQsat(pV->v1, pV->Umax, pV->Umin); // 限制输出
}

void  PI_Pare_init(void )
{
 //_IQmpy 是移位2…^24次方 因此Kp/16777216   Ki/16777216
  pi_spd.Kp=_IQ(0.22);
  pi_spd.Ki=_IQ(0.00097);  // 0.0001*10 / 0.2   T*SpeedLoopPrescaler/0.2
  pi_spd.Umax =_IQ(0.85);
  pi_spd.Umin =_IQ(0.0);

  // 二闭环 speed和id闭环,采用速度闭环  id电流闭环 则速度环输出uq电压

  //三个闭环,id闭环输出为电压Vd,speed速度闭环输出给定电流iq,iq闭环输出等于给定Vq
  //速度环输出的是参考电流,本开发板的电流设计±8A左右,100mr电路,电路放大2倍,电流中点电压1.65V

  pi_id.Kp=_IQ(0.025);  //
  pi_id.Ki=_IQ(0.00048);  //
  pi_id.Umax =_IQ(0.1);
  pi_id.Umin =_IQ(-0.1);

  pi_iq.Kp=_IQ(0.028);
  pi_iq.Ki=_IQ(0.00056);
  pi_iq.Umax =_IQ(0.85);
  pi_iq.Umin =_IQ(0.0);
 }

8.3双闭环的仿真模型搭建

1.双闭环矢量控制策略:转速环PI控制器+电流环PI控制器+SVPWM

在这里插入图片描述

2.双闭环矢量控制策略: 转速环PI控制器+电流环PI控制器+SVPWM+电流环的前馈补偿控制
在这里插入图片描述

3.双闭环矢量控制策略: 转速环SMC控制器+电流环PI控制器+SVPWM
在这里插入图片描述

4.双闭环矢量控制策略: 转速环SMC控制器+电流环PI控制器+SVPWM+电流环的前馈补偿控制
在这里插入图片描述
5.双闭环矢量控制策略: 转速环ADRC控制器+电流环PI控制器+SVPWM

在这里插入图片描述

6.双闭环矢量控制策略:转速环复合控制策略(PI+SMC)+电流环PI控制器+SVPWM
在这里插入图片描述

**微电机核心期刊论文已录用,而且正式刊出《基于滑模观测器估计偏差反馈的永磁同步电机转速控制策略》**有须要参考学习的朋友能够私我。

如下是学习LADRC的源代码,后续的LADRC学习资料和具体讲解敬请期待后续博客更新。

LADRC的DSP源代码以下:

#ifndef  LADRC_H
#define  LADRC_H

#include <stdint.h>
#include <stdio.h>
#include "IQmathLib.h"
#include "math.h"

typedef struct {
//两个输入一个输出共32个
	    /*****安排过分过程TD*******///8
	        float  ref;   //自抗扰控制的给定转速
			float  x1;    //跟踪微分期状态量
			float  x2;    //跟踪微分期状态量微分项
			float  r;     //时间尺度
			float  h;     //ADRC系统积分时间
			uint16_t N0;  //跟踪微分器解决速度超调h0=N*h

			float h0;
			float fh;     //最速微分加速度跟踪量

		/*****扩张状态观测器ESO*******///10

		/******已系统输出y和输入u来跟踪估计系统状态和扰动*****/

			float z1;
			float z2;
			float z3;   //根据控制对象输入与输出,提取的扰动信息
			float e;    //系统状态偏差
			float y;    //y系统输出量
			float fe;
			float fe1;
			float  w0;   //调试参数
			float  beta_01;
			float  beta_02;
			float  beta_03;

		/**********系统状态偏差反馈率*********///5

			float e0;//状态偏差积分项
			float e1;//状态误差
			float e2;//状态量微分项
			float u0;//非线性组合系统输出
			float u;//带扰动补偿后的输出
			float d;//SMDO滑模干扰观测器的干扰量输出

			/*********第一种组合形式PD*********///10

				float beta_0;//线性
				float wc;    //调试参数
				float beta_1;//非线性组合参数
				float beta_2;//u0=beta_1*e1+beta_2*e2+(beta_0*e0);

			/*********第二种组合形式*********/

				float alpha1;//u0=beta_1*fal(e1,alpha1,zeta)+beta_2*fal(e2,alpha2,zeta)
				float alpha2;//0<alpha1<1<alpha2
				float zeta;//线性段的区间长度

			/*********第三种组合形式*********/

				float h1;//u0=-fhan(e1,e2,r,h1);
				uint16_t N1;//跟踪微分器解决速度超调h0=N*h

			/*********第四种组合形式*********/

				float c;//u0=-fhan(e1,c*e2*e2,r,h1);

				float b0;//扰动补偿

		    /*********强制类型转换*********/
//				float Out;  //转速输出,iq给定

       } LADRC_Control, *p_LADRC_Control ; //初始化各个参数

#define LADRC_Control_DEFAULTS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // 初始化参数

extern  LADRC_Control     LADRC_spd  ;

//int16_t Sign_ADRC(float Input)   //符号函数
//int16_t Fsg_ADRC(float x,float d)   // 开关函数/比较函数
//float Fal_ADRC(float e,float alpha,float zeta) // 原点附近有连线性段的连续幂次函数
//float Constrain_Float(float amt, float low, float high) //归一化区间函数

void  LADRC_Controller(p_LADRC_Control  pV);  //LADRC控制算法函数
void  LADRC_Pare_init(void );                 //LADRC控制参数初始化

#endif /* LADRC */

//===========================================================================
// No more.
//===========================================================================
#include "Main_PMSM_QEncoder.h"
LADRC_Control    LADRC_spd = LADRC_Control_DEFAULTS;

   //符号函数
int16_t Sign_ADRC(float Input)
 {
     int16_t output=0;

     if(Input>1E-6) output=1;

     else if(Input<-1E-6) output=-1;

     else output=0;

     return output;
 }

// 开关函数/比较函数
int16_t Fsg_ADRC(float x,float d)
 {
    int16_t output=0;
    output=(Sign_ADRC(x+d)- Sign_ADRC(x-d))/2;
    return output;
 }

// 原点附近有连线性段的连续幂次函数
 float Fal_ADRC(float e,float alpha,float zeta)
 {
 int16 s=0;
 float fal_output=0;
 s= (Sign_ADRC(e+zeta)-Sign_ADRC(e-zeta))/2;
 fal_output = e*s/(powf(zeta,1-alpha))+powf(abs(e),alpha)*Sign_ADRC(e)*(1-s);
 return fal_output;
 }


 float Constrain_Float(float amt, float low, float high) //归一化区间函数
 {
   return ((amt)<(low)?(low):((amt)>(high)?(high):(amt)));
 }

 //constrain(amt,low,high)函数的工做过程是,若是值amt小于low,则返回low;
 //若是amt大于high,则返回high;不然,返回amt。该函数通常能够用于将值归一化到某个区间内

 //除法运算函数
 //float Division_function(float A, float B) //除法函数
// {
 //  return ((amt)<(low)?(low):((amt)>(high)?(high):(amt)));
// }

 // 此程序是线性自抗扰控制
 //宏定义的问题,和宏定义同名的参数被使用,当作变量

void LADRC_Controller(p_LADRC_Control pV)
{
        float d=0, a0=0, Y=0, a1=0, a2=0, A=0;
        float x1_delta=0;
//      float temp_e2=0;
    /* Step1:安排跟踪微分过程TD */
	 /*****
	      安排过分过程,输入为指望给定,
	      由TD跟踪微分器获得:
	      过渡指望信号x1,过渡指望微分信号x2
	 ******/
       // 输入指望转速Ref-----wr
	   x1_delta = pV->x1-pV->ref;                        //偏差量-----用x1-v(k)替代x1获得离散更新公式
	   pV->h0 = pV->N0*pV->h;                            //h0 = N0*h 用h0替代h,解决最速跟踪微分器速度超调问题
	   d  = pV->r*pV->h0*pV->h0;                         //d=rh0^2;
	   a0 = pV->h0*pV->x2;                               //a0=h0*x2
	   Y = x1_delta+a0;                                  //y=x1-z+a0
	   a1=sqrt(d*(d+8*abs(Y)));                          // a1=sqrt(d*(d+8*ABS(y))])
	   a2=a0+Sign_ADRC(Y)*(a1-d)/2;                      // a2=a0+sign(y)*(a1-d)/2/单个的符号函数,极小数近似等于0
	   A = (a0+Y)*Fsg_ADRC(Y,d)+a2*(1-Fsg_ADRC(Y,d));    // a =(a0+y-a2)*sign(y,d)+a2
	   pV->fh = -pV->r*(A/d)*Fsg_ADRC(A,d)-pV->r*Sign_ADRC(A)*(1-Fsg_ADRC(A,d)); // fh =-r*[a/d-sign(a)]*sign(a,d)-r*sign(a)

	   // h为ADRC系统积分时间
	   pV->x1 = pV->x1 + pV->h*pV->x2;     //指望信号x1
	   pV->x2 = pV->x2 + pV->h*pV->fh;     //指望微分信号x2
//LADRC_spd.fh LADRC_spd.
	   /* Step2:ESO扩张状态观测器 */
	   /*****
	         扩张状态观测器,获得反馈信号的扩张状态:
	         一、状态信号z1;
	         二、状态速度信号z2;
	         三、状态加速度信号z3。
	         其中z一、z2用于做为状态反馈与TD微分跟踪器获得的x1,x2作差后,
	         通过非线性函数映射,乘以beta系数后,
	         组合获得未加入状态加速度估计扰动补偿的原始控制量u
	         *********/
//y系统输出量,转速反馈值-----we;安排输出u;(两个输入三个输出)
	     pV->e  = pV->z1-pV->y;               //e=z1-y 状态偏差
//	     pV->fe =Fal_ADRC(pV->e,0.5,pV->h);   //避免高频颤振/*---http://www.docin.com/p-2071650216.html-----*/
//	     pV->fe1=Fal_ADRC(pV->e,0.25,pV->h);  //

	     /*************扩展状态量更新**********/
//	     pV->z1+=pV->z1+pV->h*(pV->z2-pV->beta_01*pV->e);
//	     pV->z2+=pV->h*(pV->z3-pV->beta_02*pV->fe+ pV->b0*pV->u);
	    //ESO估计状态加速度信号,进行扰动补偿,传统MEMS陀螺仪漂移较大,估计会产生漂移
//	     pV->z3+=pV->h*(-pV->beta_03*pV->fe1);

	     //ESO估计状态加速度信号,进行扰动补偿,传统MEMS陀螺仪漂移较大,估计会产生漂移
	     pV->z1=pV->z1+pV->h*(pV->z2-pV->beta_01*pV->e);                 //beta_01取值的范围能够依据经验公式
	     pV->z2=pV->z2+pV->h*(pV->z3-pV->beta_02*pV->e+ pV->b0*(pV->u+pV->d));   //扰动补偿+SMDO
	     pV->z3=pV->z3+pV->h*(-pV->beta_03*pV->e);                               //pV->z3没有用到

/* 线性扩张状态观测器*/

	     /* Step3:NLSEF */
	     /********状态偏差反馈率***/
//	     pV->e0+=pV->e1*pV->h;//状态积分项
//	     pV->e0=pV->e0+pV->e1*pV->h;//状态积分项

	     pV->e1=pV->x1-pV->z1;   //状态误差项 LADRC_spd.x2
	     pV->e2=pV->x2-pV->z2;   //状态微分项 LADRC_spd.z2
	     /* Step4:线性组合PD */
	     /*
	      fhan_Input->u0=//fhan_Input->beta_0*fhan_Input->e0
	                    +fhan_Input->beta_1*fhan_Input->e1
	                    +fhan_Input->beta_2*fhan_Input->e2;
	    */
//        temp_e2 = Constrain_Float(pV->e2,-3000,3000); //3000
//        pV->u0 = (pV->beta_1 * Fal_ADRC(pV->e1,pV->alpha1,pV->zeta)- pV->beta_2 * pV->z2-pV->z3)/(pV->b0);   //SMDO+扰动补偿
        pV->u0 = ((pV->beta_1 * pV->e1)- pV->beta_2 * pV->z2-pV->z3+pV->d)/(pV->b0);
//      pV->u0 = pV->beta_1 * Fal_ADRC(pV->e1,pV->alpha1,pV->zeta)- pV->beta_2 * Fal_ADRC(temp_e2,pV->alpha2,pV->zeta)-pV->z3;
//      pV->u0 = pV->beta_1 * Fal_ADRC(pV->e1,pV->alpha1,pV->zeta)+ pV->beta_2 * Fal_ADRC(temp_e2,pV->alpha2,pV->zeta);

		 /* Step5:控制输出 */
	/* control output*/
        pV->u=Constrain_Float(pV->u0,0,14260633.6);   ////带扰动补偿后的输出 // 限制输出-1500

// LADRC_spd.u0
}


void  LADRC_Pare_init(void )
{
	// 自抗扰控制器参数设置15个
    /*Float----最大的数是2^(-32)到2^32-1------4294967295 */
	LADRC_spd.r= 6000000;  //TD跟踪微分器300000
	LADRC_spd.h= 0.005;    //h0=h*N0=0.01
	LADRC_spd.N0= 2;

	// 带宽调参法/*https://blog.csdn.net/handsome_for_kill/article/details/88398467*/
	LADRC_spd.w0 = 50;
	LADRC_spd.beta_01= 3*LADRC_spd.w0;                           //200   //150; //3*wo//100扩张状态观测器ESO,wo=50000
	LADRC_spd.beta_02= 3*LADRC_spd.w0*LADRC_spd.w0;              //133.3 //7500;//3*wo^2//1000
	LADRC_spd.beta_03= LADRC_spd.w0*LADRC_spd.w0*LADRC_spd.w0;   //125   //125000;//wo^3//
    // 系统特性,与被控对象有关
	LADRC_spd.b0= 0.003727458;     //0.003727458扰动补偿b0 0.001

	LADRC_spd.beta_0= 0.002;  //非线性组合

    //线性控制器PD
	LADRC_spd.wc = 16;
	LADRC_spd.beta_1= LADRC_spd.wc*LADRC_spd.wc;    //400 //wc^2   0.0005
	LADRC_spd.beta_2= 2*LADRC_spd.wc;     //40 // 2*wc 1.0

	LADRC_spd.N1= 5;
	LADRC_spd.c= 5;

	// 原点附近有连线性段的连续幂次函数
	LADRC_spd.alpha1= 0.8;//0.8
	LADRC_spd.alpha2= 1.5;//1.5
	LADRC_spd.zeta= 50;

 }

//===========================================================================
// No more.
//===========================================================================

当你在忙起来的时候,你就以为在实现与自我实现中寻找到那个平衡点——进步。但愿能够天天进步一点点,以前的博客(包括这篇)都是在总结与回顾以前所学习的内容与所得,后续将持续更新,感谢您的关注与点赞!!!