📄 pmsm.c
字号:
/**********************************************************************
* *
* Software License Agreement *
* *
* The software supplied herewith by Microchip Technology *
* Incorporated (the "Company") for its dsPIC controller *
* is intended and supplied to you, the Company's customer, *
* for use solely and exclusively on Microchip dsPIC *
* products. The software is owned by the Company and/or its *
* supplier, and is protected under applicable copyright laws. All *
* rights are reserved. Any use in violation of the foregoing *
* restrictions may subject the user to criminal sanctions under *
* applicable laws, as well as to civil liability for the breach of *
* the terms and conditions of this license. *
* *
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO *
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, *
* BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND *
* FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE *
* COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, *
* INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. *
* *
**********************************************************************/
/**********************************************************************
* *
* Author: John Theys/Dave Ross/Jorge Zambada *
* *
* Filename: PMSM.c *
* Date: 04/27/07 *
* File Version: 1.00 *
* *
* Tools used: MPLAB GL -> 7.52.0.0 *
* *
* Linker File: p30f6010a.gld *
* *
* *
***********************************************************************
*10/31/03 2.00 Released Motor runs fine, still some loose ends
*
*12/19/03 2.01 Cleaned up structure, created UserParms.h for all
* user defines.
*
*02/12/04 3.00 -Removed unnecessary files from project.
-Changed iRPM to int to correct floating point calc
* problems.
* -CalcVel() and velocity control loop only execute
* after number of loop periods specified by
* iIrpPerCalc.
* -Added iDispLoopCount variable to schedule
* execution of display and button routines
* -trig.s file changed to use program space for
* storage of sine data.
* -Added DiagnosticsOutput() function that uses
* output compare channels to output control variable
* information.
* -Added TORQUE_MODE definition to bypass velocity
* control loop.
* -Turned off SATDW bit in curmodel.s file. The
* automatic saturation feature prevents slip
* angle calculation from wrapping properly.
*04/27/07 4.00 -PMSM functionality added. Speed and Position Estimation
* is used to control PMSM motors. ACIM is not supported.
*
************************************************************************
* Code Description
*
* This file demonstrates Vector Control of a 3 phase PMSM using the
* dsPIC30F. SVM is used as the modulation strategy. Currents are measured
* to estimate position and speed of PMSM Motors
**********************************************************************/
/************** GLOBAL DEFINITIONS ***********/
/************* START OF MAIN FUNCTION ***************/
int main ( void )
{
SMCInit(&smc1);
SetupPorts();
InitLCD();
InitOutputCompare6(); // Configure and intialize the Output Compare Module
SetupControlParameters();
OC6CONbits.OCM = 0b110; // Set the Output Compare Module for PWM Mode
T3CONbits.TON = 1; // Start Timer-3 Module
while(1)
{
uGF.Word = 0; // clear flags
// init Mode
uGF.bit.OpenLoop = 1; // start in openloop
// init LEDs
pinLED1 = 0;
pinLED2 = !uGF.bit.OpenLoop;
pinLED3 = 0;
pinLED4 = 0;
// init board
SetupBoard();
// init user specified parms and stop on error
if( SetupParm() )
{
// Error
uGF.bit.RunMotor=0;
return;
}
// zero out i sums
PIParmD.qdSum = 0;
PIParmQ.qdSum = 0;
PIParmQref.qdSum = 0;
iMaxLoopCnt = 0;
Wrt_S_LCD("Vector Control ", 0 , 0);
Wrt_S_LCD("S4-Run/Stop ", 0, 1);
// Enable ADC interrupt and begin main loop timing
IFS0bits.ADIF = 0;
IEC0bits.ADIE = 1;
if(!uGF.bit.RunMotor)
{
// Initialize current offset compensation
while(!pinButton1) //wait here until button 1 is pressed
{
ClrWdt();
// Start offset accumulation //and accumulate current offset while waiting
MeasCompCurr();
}
while(pinButton1); //when button 1 is released
SetupParm();
uGF.bit.RunMotor = 1; //then start motor
}
// Run the motor
uGF.bit.ChangeMode = 1;
// Enable the driver IC on the motor control PCB
pinPWMOutputEnable_ = 0;
Wrt_S_LCD("RPM= ", 0, 0);
Wrt_S_LCD("S5-Cls. Lp S6-2x", 0, 1);
//Run Motor loop
while(1)
{
ClrWdt();
// Write vector control variables to output compare channels
// for observation on oscilloscope.
// The code that updates the LCD display and polls the buttons
// executes every 50 msec.
if(iDispLoopCnt >= dDispLoopCnt)
{
//Display RPM
Dis_RPM(5,0);
// Button 1 starts or stops the motor
if(pinButton1)
{
if( !uGF.bit.Btn1Pressed )
uGF.bit.Btn1Pressed = 1;
}
else
{
if( uGF.bit.Btn1Pressed )
{
// Button just released
uGF.bit.Btn1Pressed = 0;
// begin stop sequence
uGF.bit.RunMotor = 0;
pinPWMOutputEnable_ = 1;
break;
}
}
//while running button 2 will toggle open and closed loop
if(pinButton2)
{
if( !uGF.bit.Btn2Pressed )
uGF.bit.Btn2Pressed = 1;
}
else
{
if( uGF.bit.Btn2Pressed )
{
// Button just released
uGF.bit.Btn2Pressed = 0;
uGF.bit.ChangeMode = 1;
uGF.bit.OpenLoop = ! uGF.bit.OpenLoop;
pinLED2 = !uGF.bit.OpenLoop;
}
}
//while running button 3 will double/half the speed or torque demand
if(pinButton3)
{
if( !uGF.bit.Btn3Pressed )
uGF.bit.Btn3Pressed = 1;
LATGbits.LATG0 = 0;
}
else
{
if( uGF.bit.Btn3Pressed )
{
// Button just released
uGF.bit.Btn3Pressed = 0;
uGF.bit.ChangeSpeed = !uGF.bit.ChangeSpeed;
pinLED3 = uGF.bit.ChangeSpeed;
#ifdef SNAPSHOT
uGF.bit.DoSnap = 1;
SnapCount = 0;
pinLED4 = 1;
#endif
}
}
if( uGF.bit.SnapDone )
{
uGF.bit.SnapDone=0;
pinLED4 = 0;
}
} // end of display and button polling code
} // End of Run Motor loop
} // End of Main loop
// should never get here
while(1){}
}
//---------------------------------------------------------------------
// Executes one PI itteration for each of the three loops Id,Iq,Speed
void DoControl( void )
{
short i;
short TempAng;
// Assume ADC channel 0 has raw A/D value in signed fractional form from
// speed pot (AN7).
ReadSignedADC0( &ReadADCParm );
if( uGF.bit.OpenLoop )
{
// OPENLOOP: force rotating angle,Vd,Vq
if( uGF.bit.ChangeMode )
{
// just changed to openloop
uGF.bit.ChangeMode = 0;
// synchronize angles
// VqRef & VdRef not used
CtrlParm.qVqRef = 0;
CtrlParm.qVdRef = 0;
uGF.bit.DoSnap = 1;
Startup_Lock = 0;
Startup_Ramp = 0;
// Initialize SMC
smc1.Valpha = 0;
smc1.Ealpha = 0;
smc1.EalphaFinal = 0;
smc1.Zalpha = 0;
smc1.EstIalpha = 0;
smc1.Vbeta = 0;
smc1.Ebeta = 0;
smc1.EbetaFinal = 0;
smc1.Zbeta = 0;
smc1.EstIbeta = 0;
smc1.Ialpha = 0;
smc1.IalphaError = 0;
smc1.Ibeta = 0;
smc1.IbetaError = 0;
smc1.Theta = 0;
smc1.Omega = 0;
}
CtrlParm.qVelRef = ADCBUF3/2; // Initial Torque Reference
#ifdef SNAPSHOT
// Log data in the snapshot buffers
if( uGF.bit.DoSnap )
{
SnapBuf1[SnapCount] = SNAP1;
SnapBuf2[SnapCount] = SNAP2;
SnapBuf3[SnapCount] = SNAP3;
SnapCount++;
if(SnapCount == SNAPSIZE)
{
SnapCount = 0;
}
}
#endif
if(AccumThetaCnt == 0)
{
CalcVel();
PIParmQref.qInMeas = smc1.Omega;
}
CtrlParm.qVqRef = CtrlParm.qVelRef;
// PI control for Q
PIParmQ.qInMeas = ParkParm.qIq;
PIParmQ.qInRef = CtrlParm.qVqRef;
CalcPI(&PIParmQ);
ParkParm.qVq = PIParmQ.qOut;
// PI control for D
PIParmD.qInMeas = ParkParm.qId;
PIParmD.qInRef = CtrlParm.qVdRef;
CalcPI(&PIParmD);
ParkParm.qVd = PIParmD.qOut;
}
else
// Closed Loop Vector Control
{
if(uGF.bit.ChangeSpeed)
{
CtrlParm.qVelRef = ReadADCParm.qADValue/3;
}
else
{
CtrlParm.qVelRef = ReadADCParm.qADValue/6;
}
if( uGF.bit.ChangeMode )
{
// just changed from openloop
uGF.bit.ChangeMode = 0;
PIParmQref.qdSum = (long)CtrlParm.qVqRef << 13;
Startup_Lock = 0;
Startup_Ramp = 0;
}
// Check to see if new velocity information is available by comparing
// the number of interrupts per velocity calculation against the
// number of velocity count samples taken. If new velocity info
// is available, calculate the new velocity value and execute
// the speed control loop.
if(AccumThetaCnt == 0)
{
// Calculate velocity from acumulated encoder counts
CalcVel();
// Execute the velocity control loop
PIParmQref.qInMeas = smc1.Omega;
PIParmQref.qInRef = CtrlParm.qVelRef;
CalcPI(&PIParmQref);
CtrlParm.qVqRef = PIParmQref.qOut;
}
#ifdef SNAPSHOT
if(SnapShotDelayCnt++ == SnapShotDelay)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -