svpwm完整程序Word格式.docx
《svpwm完整程序Word格式.docx》由会员分享,可在线阅读,更多相关《svpwm完整程序Word格式.docx(90页珍藏版)》请在冰豆网上搜索。
#definedQqKc0x0100;
#definedQqOutMax0x5A82;
#definedQrefqKp0x4000//8.0(NKo=4)
#definedQrefqKi0x0800//1.0
#definedQrefqKc0x0800//1.0
#definedQrefqOutMax0x3FFF//0.4999设定该值以避免饱和
//**************ADC换算************************************
//标定常数:
由校准或硬件设计确定。
#definedqK0x3FFF;
//等于0.4999
#definedqKa0x3FFF;
#definedqKb0x3FFF;
//**************弱磁****************************************
//在恒转矩范围内的磁通给定值。
//根据经验确定、给出额定压/频比
#definedqK13750;
//
/**********************************************************************
**
*作者:
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"
Parms.h"
Encoder.h"
SVGen.h"
ReadADC.h"
MeasCurr.h"
CurModel.h"
FdWeak.h"
Control.h"
PI.h"
Park.h"
OpenLoop.h"
LCD.h"
bin2dec.h"
UserParms.h"
/***********************全局定义结束********************/
unsignedshortuWork;
shortiCntsPerRev;
shortiDeltaPos;
union{
struct
{
unsignedDoLoop:
1;
unsignedOpenLoop:
unsignedRunMotor:
unsignedBtn1Pressed:
unsignedBtn2Pressed:
unsignedBtn3Pressed:
unsignedBtn4Pressed:
unsignedChangeMode:
unsignedChangeSpeed:
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);
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;
RPM="
0,0);
S5-Cls.LpS6-2x"
//电机运行循环
//如果使用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)
uGF.bit.Btn2Pressed)
uGF.bit.Btn2Pressed=1;
if(uGF.bit.Btn2Pressed)
//按钮刚释放
uGF.bit.Btn2Pressed=0;
uGF.bit.OpenLoop=!
uGF.bit.OpenLoop;
//在运行时按钮3将加倍/减半速度或转矩给定
if(pinButton3)
uGF.bit.Btn3Pressed)
uGF.bit.Btn3Pressed=1;
LATGbits.LATG0=0;
if(uGF.bit.Btn3Pressed)
uGF.bit.Btn3Pressed=0;
uGF.bit.ChangeSpeed=!
uGF.bit.ChangeSpeed;
pinLED3=uGF.bit.ChangeSpeed;
LATGbits.LATG0=1;
//按钮4不具备任何功能
if(pinButton4)
uGF.bit.Btn4Pressed)
uGF.bit.Btn4Pressed=1;
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;
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;
i=-OpenLoopParm.qVelMech;
uWork=i<
<
2;
if(uWork>
0x5a82)
uWork=0x5a82;
if(uWork<
0x1000)
uWork=0x1000;
ParkParm.qVd=uWork;
OpenLoop();
ParkParm.qAngle=OpenLoopParm.qAngFlux;
//闭环矢量控制
//改变为闭环模式
//同步角度以及准备qdImag
CurModelParm.qAngFlux=OpenLoopParm.qAngFlux;
CurModelParm.qdImag=ParkParm.qId;
//根据电流模型计算角度
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;
//Q的PI控制
PIParmQ.qInMeas=ParkParm.qIq;
PIParmQ.qInRef=CtrlParm.qVqRef;
PIParmQ);
ParkParm.qVq=PIParmQ.qOut;
//D的PI控制
PIParmD.qInMeas=ParkParm.qId;
PIParmD.qInRef=CtrlParm.qVdRef;
PIParmD);
ParkParm.qVd=PIParmD.qOut;
ADC中断服务程序执行速度计算以及电压矢量更新循环。
//ADC采样和转换由PWM周期触发。
//速度计算假定计算之间的间隔时间是固定的。
//--------------------------------------------------------------------
void__attribute__((__interrupt__))_ADCInterrupt(void)
//递增控制显示和按钮功能执行的计数变量。
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
SetupBoard
voidSetupBoard(void)
BYTEb;
//禁止ADC中断
IEC0bits.ADIE=0;
//复位电机控制功率模块上的所有故障。
p