在前面的博客已经讲到电机本体的Simulink模型搭建,其中可以自定义电机的库模型,或者直接通过仿真器件进行搭建都可以。这部分内容可以参考前面的内容:电机的数学模型永磁同步电机的矢量控制策略(二)一一一数学模型
按照SVPWM的实现流程进行仿真模型搭建,如图1所示。
图1 SVPWM的仿真模型
对应于专门讲解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的输出进行功能函数的编程如下:
#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的输出图形当时在做实验的时候没有记录保存,后续如果允许我更新补充哈,详细结合实验步骤来分析波形特点。
没有含有PWM生成的模块,仅含有电流环和转速环的控制,针对数学模型的推导与建立。输出波形如图3所示。
图2 转速环和电流环的电机控制模型
从图3可看出,依据坐标变换的矢量解耦控制,d轴电流最终趋向于0,q轴最终趋于一个稳定值,这个与坐标变换里面所讲到的结论是一致的。大家可以参考下这个:坐标变换
下面给出DSP上专门这块的SVPWM控制C++代码:
#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);
}
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
#include
#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
#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扩张状态观测器 */
/*****
扩张状态观测器,得到反馈信号的扩张状态:
1、状态信号z1;
2、状态速度信号z2;
3、状态加速度信号z3。
其中z1、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.
//===========================================================================
当你在忙起来的时候,你就觉得在实现与自我实现中寻找到那个平衡点——进步。希望可以每天进步一点点,之前的博客(包括这篇)都是在总结与回顾之前所学习的内容与所得,后续将持续更新,感谢您的关注与点赞!!!