📄 acim.c
字号:
uGF.bit.Btn3Pressed = 1;
LATGbits.LATG0 = 0;
}
else
{
if( uGF.bit.Btn3Pressed )
{
// Button just released
uGF.bit.Btn3Pressed = 0;
if(uGF.bit.OpenLoop)
{
uGF.bit.ChangeSpeed = !uGF.bit.ChangeSpeed;
pinLED3 = uGF.bit.ChangeSpeed;
}
else
{
#ifdef SNAPSHOT
uGF.bit.DoSnap = 1;
SnapCount = 0;
pinLED4 = 1;
#else
uGF.bit.ChangeSpeed = !uGF.bit.ChangeSpeed;
pinLED3 = uGF.bit.ChangeSpeed;
#endif
}
#ifdef DIAGNOSTICS
LATGbits.LATG0 = 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;
// Assume ADC channel 0 has raw A/D value in signed fractional form from
// speed pot (AN7).
ReadSignedADC0( &ReadADCParm );
// Set reference speed
if(uGF.bit.ChangeSpeed)
{
CtrlParm.qVelRef = ReadADCParm.qADValue/8;
}
else
{
CtrlParm.qVelRef = ReadADCParm.qADValue/16;
}
if( uGF.bit.OpenLoop )
{
// OPENLOOP: force rotating angle,Vd,Vq
if( uGF.bit.ChangeMode )
{
// just changed to openloop
uGF.bit.ChangeMode = 0;
// synchronize angles
OpenLoopParm.qAngFlux = CurModelParm.qAngFlux;
// VqRef & VdRef not used
CtrlParm.qVqRef = 0;
CtrlParm.qVdRef = 0;
}
OpenLoopParm.qVelMech = CtrlParm.qVelRef;
// calc rotational angle of rotor flux in 1.15 format
// just for reference & sign needed by CorrectPhase
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
// Closed Loop Vector Control
{
if( uGF.bit.ChangeMode )
{
// just changed from openloop
uGF.bit.ChangeMode = 0;
// synchronize angles and prep qdImag
CurModelParm.qAngFlux = OpenLoopParm.qAngFlux;
CurModelParm.qdImag = ParkParm.qId;
}
// Current model calculates angle
CurModelParm.qVelMech = EncoderParm.qVelMech;
CurModel();
ParkParm.qAngle = CurModelParm.qAngFlux;
// Calculate qVdRef from field weakening
FdWeakening();
// 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(EncoderParm.iVelCntDwn == EncoderParm.iIrpPerCalc)
{
// Calculate velocity from acumulated encoder counts
CalcVel();
// Execute the velocity control loop
// Changes 15 dec 2006
//****************************
if ((uGF.bit.Sensorless)&&(!uGF.bit.OpenLoop))
{
if(CtrlParm.qVelRef==0)
{
if (abs(EstimParm.qVelEstim)<(StartupParm.qVelMinContrOff))
{
PIParmQref.qInMeas=0;
PIParmQref.qdSum=0;
} else
{
PIParmQref.qInMeas = EstimParm.qVelEstim;
}
} else
{
PIParmQref.qInMeas = EstimParm.qVelEstim;
// Changes 02 feb 2007
//****************************
// Hysteresis by speed reference value
// minimum speed ref. is StartupParm.qVelMinContrOff
// change speed ref. from 0 to StartupParm.qVelMinContrOff by positiv edge of CtrlParm.qVelRef through StartupParm.qVelMinContrOff
// change speed ref. from StartupParm.qVelMinContrOff to 0 by negative edge of CtrlParm.qVelRef through StartupParm.qVelMinContrOff/2
if(abs(CtrlParm.qVelRef)<StartupParm.qVelMinContrOff)
{
if(abs(CtrlParm.qVelRef)<(StartupParm.qVelMinContrOff>>1))
{
CtrlParm.qVelRef=0;
} else
{
if(abs(PIParmQref.qInRef)>=(StartupParm.qVelMinContrOff))
{
if (CtrlParm.qVelRef>0)
{
CtrlParm.qVelRef=StartupParm.qVelMinContrOff;
} else
{
CtrlParm.qVelRef=-StartupParm.qVelMinContrOff;
}
} else
{
CtrlParm.qVelRef=0;
}
}
}
}
} else
{
PIParmQref.qInMeas = EncoderParm.qVelMech;
}
//****************************
#ifndef TORQUE_MODE
PIParmQref.qInRef = CtrlParm.qVelRef;
CalcPI(&PIParmQref);
CtrlParm.qVqRef = PIParmQref.qOut;
#endif
}
#ifdef SNAPSHOT
if(EncoderParm.iVelCntDwn == EncoderParm.iIrpPerCalc)
{
// Log data in the snapshot buffers
if( uGF.bit.DoSnap )
{
SnapBuf1[SnapCount] = SNAP1;
SnapBuf2[SnapCount] = SNAP2;
SnapBuf3[SnapCount] = SNAP3;
SnapCount++;
if(SnapCount == SNAP_DELAY)
{
uGF.bit.ChangeSpeed = !uGF.bit.ChangeSpeed;
pinLED3 = uGF.bit.ChangeSpeed;
}
if(SnapCount == SNAPSIZE)
{
uGF.bit.SnapDone=1;
uGF.bit.DoSnap = 0;
}
}
}
#endif
// If the application is running in torque mode, the velocity
// control loop is bypassed. The velocity reference value, read
// from the potentiometer, is used directly as the torque
// reference, VqRef.
#ifdef TORQUE_MODE
CtrlParm.qVqRef = CtrlParm.qVelRef * 4;
#endif
// 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;
}
}
//---------------------------------------------------------------------
// The ADC ISR does speed calculation and executes the vector update loop.
// The ADC sample and conversion is triggered by the PWM period.
// The speed calculation assumes a fixed time interval between calculations.
//---------------------------------------------------------------------
void __attribute__((__interrupt__,auto_psv)) _ADCInterrupt(void)
{
IFS0bits.ADIF = 0;
// Increment count variable that controls execution
// of display and button functions.
iDispLoopCnt++;
// acumulate encoder counts since last interrupt
CalcVelIrp();
if( uGF.bit.RunMotor )
{
pinLED1=1;
// use TMR1 to measure interrupt time for diagnostics
TMR1 = 0;
iLoopCnt = TMR1;
// Appcon/Changes 25 Jan 2007
// current is measured,
// Offset is dynamicly compensated when
// 1. Sensored control is selected
// 2. Velocity > CurrCompMinSpeed
//****************************
// Hysteresis for activation desactivation of offset compensation:
// MeasCurrParm.iOffsetCompAktiv is set to 1 when abs(EncoderParm.qVelMech)>MeasCurrParm.iOffsetCompVelLimit+MeasCurrParm.iOffsetCompHyst
// MeasCurrParm.iOffsetCompAktiv is set to 0 when abs(EncoderParm.qVelMech)<MeasCurrParm.iOffsetCompVelLimit
// Calculate qIa,qIb
if ((abs(EncoderParm.qVelMech)>MeasCurrParm.iOffsetCompVelLimit)&&(uGF.bit.Sensorless==0))
{
if(abs(EncoderParm.qVelMech)>(MeasCurrParm.iOffsetCompVelLimit+MeasCurrParm.iOffsetCompHyst))
{
MeasCurrParm.iOffsetCompAktiv=1;
}
} else
{
MeasCurrParm.iOffsetCompAktiv=0;
}
if( MeasCurrParm.iOffsetCompAktiv)
{
// Calculate qIa,qIb with offset correction
MeasCompCurr();
} else
{
// Calculate qIa,qIb without offset correction
MeasCompCurr2();
}
//****************************
// Calculate qId,qIq from qSin,qCos,qIa,qIb
ClarkePark();
// Appcon/Changes 15 dec 2006
// New module: Speed estimation
//****************************
// elapsed time: 16 micro second by 15MIPs
Estim();
//****************************
// Calculate control values
DoControl();
// Changes 15 dec 2006
//****************************
if ((uGF.bit.Sensorless)&&(!uGF.bit.OpenLoop))
{
SincosParm.qAngle=EstimParm.qRho;
} else
{
SincosParm.qAngle=ParkParm.qAngle;
}
//****************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -