svpwm完整程序.docx

上传人:b****3 文档编号:3681256 上传时间:2022-11-24 格式:DOCX 页数:90 大小:45.49KB
下载 相关 举报
svpwm完整程序.docx_第1页
第1页 / 共90页
svpwm完整程序.docx_第2页
第2页 / 共90页
svpwm完整程序.docx_第3页
第3页 / 共90页
svpwm完整程序.docx_第4页
第4页 / 共90页
svpwm完整程序.docx_第5页
第5页 / 共90页
点击查看更多>>
下载资源
资源描述

svpwm完整程序.docx

《svpwm完整程序.docx》由会员分享,可在线阅读,更多相关《svpwm完整程序.docx(90页珍藏版)》请在冰豆网上搜索。

svpwm完整程序.docx

svpwm完整程序

头文件

UserParms.h

C文件

ACIM.c

Encoder.c

InitCurModel.c

UserParms.h

//#defineTORQUE_MODE

#defineDIAGNOSTICS

//****************振荡器************************************

#definedFoscExt7372800//外部晶振或时钟频率(Hz)

#definedPLL8//PLL比率

#definedLoopTimeInSec0.00005//PWM周期-100uS,10KhzPWM

#definedDeadTimeSec0.000002//以秒为单位的死区时间

//Derived

#definedFosc(dFoscExt*dPLL)//时钟频率(Hz)

#definedFcy(dFosc/4)//指令频率(Hz)

#definedTcy(1.0/dFcy)//指令周期(s)

#definedDeadTime(int)(dDeadTimeSec*dFcy)//以dTcys为单位的死区时间

#definedLoopInTcy(dLoopTimeInSec/dTcy)//以Tcy为单位的基本循环周期

#definedDispLoopTime0.100//显示和按钮状态查询循环

//****************电机参数********************************

#definediPoles1//极对数

#definediCntsPerRev2000//每转的编码器线数

#definediNomRPM3600//电机铭牌上的转速(RPM)

#definedfRotorTmConst0.078//以秒为单位的转子时间常数,来自电机制造商

//****************测量*************************************

#definediIrpPerCalc30//每次速度计算的PWM循环次数

//**************PI系数************************************

#definedDqKp0x2000//4.0(NKo=4)

#definedDqKi0x0100;//0.125

#definedDqKc0x0100;//0.125

#definedDqOutMax0x5A82;//0.707设定该值以避免饱和

#definedQqKp0x2000;//4.0(NKo=4)

#definedQqKi0x0100;//0.125

#definedQqKc0x0100;//0.125

#definedQqOutMax0x5A82;//0.707设定该值以避免饱和

#definedQrefqKp0x4000//8.0(NKo=4)

#definedQrefqKi0x0800//1.0

#definedQrefqKc0x0800//1.0

#definedQrefqOutMax0x3FFF//0.4999设定该值以避免饱和

//**************ADC换算************************************

//标定常数:

由校准或硬件设计确定。

#definedqK0x3FFF;//等于0.4999

#definedqKa0x3FFF;//等于0.4999

#definedqKb0x3FFF;//等于0.4999

//**************弱磁****************************************

//在恒转矩范围内的磁通给定值。

//根据经验确定、给出额定压/频比

#definedqK13750;//

ACIM.c

/**********************************************************************

**

*作者:

JohnTheys/DaveRoss*

**

*文件名:

ACIM.c*

*日期:

10/31/03*

*文件版本:

3.00*

**

*使用工具:

MPLAB->6.43*

*编译器->1.20.00*

**

*链接文件:

p30f6010.gld*

**

**

***********************************************************************

*10/31/032.00发布电机运行正常,但仍有些遗留的小问题

*

*12/19/032.01完成结构,为所有用户定义变量创建UserParms.h。

*

*02/12/043.00-从项目中去除了不需要的文件。

*-将iRPM改为int以纠正浮点计算问题。

*-CalcVel()和转速控制环仅在iIrpPerCalc指定的数个循环周期后执行

*

*-增加了iDispLoopCount变量以安排显示和按钮子程序的执行时间

*-trig.s文件改为使用程序空间来存储正弦数据。

*-增加了DiagnosticsOutput()函数,该函数使用输出比较通道来输出控

*制变量信息。

*-增加了TORQUE_MODE定义以忽略转速控制环。

*-关闭curmodel.s文件中的SATDW位。

自动饱和功能阻止转差角计算正确

*翻转返回。

************************************************************************

*代码说明

*

*该文件给出了使用dsPIC30F实现的三相交流感应电机矢量控制实例。

*采用空间矢量调制作为控制策略。

***********************************************************************/

/***************************全局定义***********************/

#defineINITIALIZE

#include"Motor.h"

#include"Parms.h"

#include"Encoder.h"

#include"SVGen.h"

#include"ReadADC.h"

#include"MeasCurr.h"

#include"CurModel.h"

#include"FdWeak.h"

#include"Control.h"

#include"PI.h"

#include"Park.h"

#include"OpenLoop.h"

#include"LCD.h"

#include"bin2dec.h"

#include"UserParms.h"

/***********************全局定义结束********************/

unsignedshortuWork;

shortiCntsPerRev;

shortiDeltaPos;

union{

struct

{

unsignedDoLoop:

1;

unsignedOpenLoop:

1;

unsignedRunMotor:

1;

unsignedBtn1Pressed:

1;

unsignedBtn2Pressed:

1;

unsignedBtn3Pressed:

1;

unsignedBtn4Pressed:

1;

unsignedChangeMode:

1;

unsignedChangeSpeed:

1;

unsigned:

7;

}bit;

WORDWord;

}uGF;//通用标志

tPIParmPIParmQ;

tPIParmPIParmQref;

tPIParmPIParmD;

tReadADCParmReadADCParm;

intiRPM;

WORDiMaxLoopCnt;

WORDiLoopCnt;

WORDiDispLoopCnt;

/**********************************************************************/

void__attribute__((__interrupt__))_ADCInterrupt(void);

voidSetupBoard(void);

boolSetupParm(void);

voidDoControl(void);

voidDis_RPM(BYTEbChrPosC,BYTEbChrPosR);

voidDiagnosticsOutput(void);

/********************主函数开头*************************/

intmain(void)

{

SetupPorts();

InitLCD();

while

(1)

{

uGF.Word=0;//清除标志

//初始化模式

uGF.bit.OpenLoop=1;//以开环模式起动

//初始化LED

pinLED1=0;

pinLED2=!

uGF.bit.OpenLoop;

pinLED3=0;

pinLED4=0;

//初始化控制板

SetupBoard();

//对用户指定参数进行初始化并在出错时停止

if(SetupParm())

{

//错误

uGF.bit.RunMotor=0;

return;

}

//清零i和

PIParmD.qdSum=0;

PIParmQ.qdSum=0;

PIParmQref.qdSum=0;

iMaxLoopCnt=0;

Wrt_S_LCD("VectorControl",0,0);

Wrt_S_LCD("S4-Run/Stop",0,1);

//使能ADC中断并开始主循环定时

IFS0bits.ADIF=0;

IEC0bits.ADIE=1;

if(!

uGF.bit.RunMotor)

{

//初始化电流偏移量补偿

while(!

pinButton1)//在此处等待直至按钮1按下

{

ClrWdt();

//开始偏移量累加//并在等待时对电流偏移量进行累加

MeasCompCurr();

}

while(pinButton1);//当按钮1释放时

uGF.bit.RunMotor=1;//随后起动电机

}

//电机运行

uGF.bit.ChangeMode=1;

//使能电机控制PCB上的驱动器IC

pinPWMOutputEnable_=0;

Wrt_S_LCD("RPM=",0,0);

Wrt_S_LCD("S5-Cls.LpS6-2x",0,1);

//电机运行循环

while

(1)

{

ClrWdt();

//如果使用OC7和OC8显示矢量控制变量,

//调用更新代码。

#ifdefDIAGNOSTICS

DiagnosticsOutput();

#endif

//每隔50毫秒执行更新LCD显示和查询按钮状态的代码。

//

if(iDispLoopCnt>=dDispLoopCnt)

{

//DisplayRPM

Dis_RPM(5,0);

//按钮1控制电机的起停

if(pinButton1)

{

if(!

uGF.bit.Btn1Pressed)

uGF.bit.Btn1Pressed=1;

}

else

{

if(uGF.bit.Btn1Pressed)

{

//按钮刚被释放

uGF.bit.Btn1Pressed=0;

//开始停止过程

uGF.bit.RunMotor=0;

pinPWMOutputEnable_=1;

break;

}

}

//在运行时按钮2将控制开/闭环模式之间的切换

if(pinButton2)

{

if(!

uGF.bit.Btn2Pressed)

uGF.bit.Btn2Pressed=1;

}

else

{

if(uGF.bit.Btn2Pressed)

{

//按钮刚释放

uGF.bit.Btn2Pressed=0;

uGF.bit.ChangeMode=1;

uGF.bit.OpenLoop=!

uGF.bit.OpenLoop;

pinLED2=!

uGF.bit.OpenLoop;

}

}

//在运行时按钮3将加倍/减半速度或转矩给定

if(pinButton3)

{

if(!

uGF.bit.Btn3Pressed)

uGF.bit.Btn3Pressed=1;

LATGbits.LATG0=0;

}

else

{

if(uGF.bit.Btn3Pressed)

{

//按钮刚释放

uGF.bit.Btn3Pressed=0;

uGF.bit.ChangeSpeed=!

uGF.bit.ChangeSpeed;

pinLED3=uGF.bit.ChangeSpeed;

LATGbits.LATG0=1;

}

}

//按钮4不具备任何功能

if(pinButton4)

{

if(!

uGF.bit.Btn4Pressed)

uGF.bit.Btn4Pressed=1;

}

else

{

if(uGF.bit.Btn4Pressed)

{

//按钮刚被释放

uGF.bit.Btn4Pressed=0;

//***此处加入按钮4功能的代码

}

}

}//显示和按钮查询代码结束

}//电机运行循环结束

}//主循环结束

//不应执行到此处

while

(1){}

}

//--------------------------------------------------------------------//

对Id控制环、Iq控制环和速度控制环中的每个控制环执行一次PI迭代

voidDoControl(void)

{

shorti;

//假定ADC通道0具有来自速度电位器(AN7)的有符号小数格式原始A/D值

ReadSignedADC0(&ReadADCParm);

//设定给定速度

if(uGF.bit.ChangeSpeed)

CtrlParm.qVelRef=ReadADCParm.qADValue/8;

else

CtrlParm.qVelRef=ReadADCParm.qADValue/16;

if(uGF.bit.OpenLoop)

{

//开环:

强制旋转角、Vd和Vq

if(uGF.bit.ChangeMode)

{

//改变为开环模式

uGF.bit.ChangeMode=0;

//同步角度

OpenLoopParm.qAngFlux=CurModelParm.qAngFlux;

//未使用VqRef和VdRef

CtrlParm.qVqRef=0;

CtrlParm.qVdRef=0;

}

OpenLoopParm.qVelMech=CtrlParm.qVelRef;

//为CorrectPhase所需的给定值和符号

//计算1.15格式的转子磁通旋转角。

CurModelParm.qVelMech=EncoderParm.qVelMech;

CurModel();

ParkParm.qVq=0;

if(OpenLoopParm.qVelMech>=0)

i=OpenLoopParm.qVelMech;

else

i=-OpenLoopParm.qVelMech;

uWork=i<<2;

if(uWork>0x5a82)

uWork=0x5a82;

if(uWork<0x1000)

uWork=0x1000;

ParkParm.qVd=uWork;

OpenLoop();

ParkParm.qAngle=OpenLoopParm.qAngFlux;

}

else

//闭环矢量控制

{

if(uGF.bit.ChangeMode)

{

//改变为闭环模式

uGF.bit.ChangeMode=0;

//同步角度以及准备qdImag

CurModelParm.qAngFlux=OpenLoopParm.qAngFlux;

CurModelParm.qdImag=ParkParm.qId;

}

//根据电流模型计算角度

CurModelParm.qVelMech=EncoderParm.qVelMech;

CurModel();

ParkParm.qAngle=CurModelParm.qAngFlux;

//计算弱磁控制模式的qVdRef

FdWeakening();

//设定给定速度

//如果应用运行在转矩模式,转速控制环将被忽略。

//从电位器读取的转速给定值将直接用作转矩给定VqRef。

#ifdefTORQUE_MODE

CtrlParm.qVqRef=CtrlParm.qVelRef;

#else

//通过对比每一次转速计算中的中断数和速度计数采样数来确定是否可以获得新的转速信息。

//

//如果可以获得新的转速信息,则计算新的转速值并执行

//转速控制环。

if(EncoderParm.iVelCntDwn==EncoderParm.iIrpPerCalc)

{

//根据编码器累计计数值来计算转速

CalcVel();

//执行转速控制环

PIParmQref.qInMeas=EncoderParm.qVelMech;

PIParmQref.qInRef=CtrlParm.qVelRef;

CalcPI(&PIParmQref);

CtrlParm.qVqRef=PIParmQref.qOut;

}

#endif

//Q的PI控制

PIParmQ.qInMeas=ParkParm.qIq;

PIParmQ.qInRef=CtrlParm.qVqRef;

CalcPI(&PIParmQ);

ParkParm.qVq=PIParmQ.qOut;

//D的PI控制

PIParmD.qInMeas=ParkParm.qId;

PIParmD.qInRef=CtrlParm.qVdRef;

CalcPI(&PIParmD);

ParkParm.qVd=PIParmD.qOut;

}

}

//--------------------------------------------------------------------//

ADC中断服务程序执行速度计算以及电压矢量更新循环。

//ADC采样和转换由PWM周期触发。

//速度计算假定计算之间的间隔时间是固定的。

//--------------------------------------------------------------------

void__attribute__((__interrupt__))_ADCInterrupt(void)

{

IFS0bits.ADIF=0;

//递增控制显示和按钮功能执行的计数变量。

//

iDispLoopCnt++;

//累计自上一次中断后的编码器计数

CalcVelIrp();

if(uGF.bit.RunMotor)

{

//置位用于诊断的LED1

pinLED1=1;

//使用TMR1来测量用于诊断的中断时间

TMR1=0;

iLoopCnt=TMR1;

MeasCompCurr();

//根据qSin、qCos、qIa、qIb计算qId、qIq

ClarkePark();

//计算控制值

DoControl();

//根据qAngle计算qSin、qCos

SinCos();

//根据qSin、qCos、qVd、qVq计算qValpha、qVbeta

InvPark();

//根据qValpha、qVbeta计算Vr1、Vr2、Vr3。

CalcRefVec();

//根据Vr1、Vr2、Vr3计算和设定PWM占空比

CalcSVGen();

//测量循环时间

iLoopCnt=TMR1-iLoopCnt;

if(iLoopCnt>iMaxLoopCnt)

iMaxLoopCnt=iLoopCnt;

//清零用于诊断的LED1

pinLED1=0;

}

}

//--------------------------------------------------------------------//

SetupBoard

//

//初始化控制板

//--------------------------------------------------------------------

voidSetupBoard(void)

{

BYTEb;

//禁止ADC中断

IEC0bits.ADIE=0;

//复位电机控制功率模块上的所有故障。

p

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 销售营销

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1