Download Print this page

Advertisement

Quick Links

Using the dsPIC30F for Vector Control of an ACIM
Author:
Dave Ross, John Theys
Diversified Engineering Inc.
Co-Author: Steve Bowling
Microchip Technology Inc.
INTRODUCTION
This application note describes a vector control
application that is written for the dsPIC30F family of
devices. Except for a brief discussion on control theory,
the information presented assumes you have a basic
understanding of AC induction motor characteristics.
References are included in some instances to provide
background information.
SOFTWARE FEATURES
The Vector Control software has the following features:
• The software implements vector control of an AC
induction motor using the indirect flux control
method.
• With a 50 µsec control loop period, the software
requires approximately 9 MIPS of CPU overhead
(less than 1/3 of the total available CPU).
• The application requires 258 bytes of data
memory storage and 256 bytes of constant
storage. With the user interface, approximately 8
Kbytes of program memory are required.
• The memory requirements of the application allow
it to be run on the dsPIC30F2010, which is the
smallest and least expensive dsPIC30F device at
the time of this writing.
• An optional diagnostics mode can be enabled to
allow real-time observation of internal program
variables on an oscilloscope. This feature
facilitates control loop adjustment.
VECTOR CONTROL THEORY
Background
The AC induction motor (ACIM) is the workhorse of
industrial and residential motor applications due to its
simple construction and durability. These motors have
no brushes to wear out or magnets to add to the cost.
The rotor assembly is a simple steel cage.
 2004 Microchip Technology Inc.
AN908
ACIM's are designed to operate at a constant input volt-
age and frequency, but you can effectively control an
ACIM in an open loop variable speed application if the
frequency of the motor input voltage is varied. If the
motor is not mechanically overloaded, the motor will
operate at a speed that is roughly proportional to the
input frequency. As you decrease the frequency of the
drive voltage, you also need to decrease the amplitude
by a proportional amount. Otherwise, the motor will
consume excessive current at low input frequencies.
This control method is called Volts-Hertz control.
In practice, a custom Volts-Hertz profile is developed
that ensures the motor operates correctly at any speed
setting. This profile can take the form of a look-up table
or can be calculated during run time. Often, a slope
variable is used in the application that defines a linear
relationship between drive frequency and voltage at
any operating point. The Volts-Hertz control method
can be used in conjunction with speed and current sen-
sors to operate the motor in a closed-loop fashion.
The Volts-Hertz method works very well for slowly
changing loads such as fans or pumps. But, it is less
effective when fast dynamic response is required. In
particular, high current transients can occur during
rapid speed or torque changes. The high currents are a
result of the high slip factor that occurs during the
change. Fast dynamic response can be realized with-
out these high currents if both the torque and flux of the
motor are controlled in a closed loop manner. This is
accomplished using Vector Control techniques. Vector
control is also commonly referred to as Field Oriented
Control (FOC).
The benefits of vector control can be directly realized
as lower energy consumption. This provides higher
efficiency, lower operating costs and reduces the cost
of drive components.
Vector Control
Traditional control methods, such as the Volts-Hertz
control method described above, control the frequency
and amplitude of the motor drive voltage. In contrast,
vector control methods control the frequency, ampli-
tude and phase of the motor drive voltage. The key to
vector control is to generate a 3-phase voltage as a
phasor to control the 3-phase stator current as a
phasor that controls the rotor flux vector and finally the
rotor current phasor.
DS00908A-page 1

Advertisement

loading
Need help?

Need help?

Do you have a question about the AN908 and is the answer not in the manual?

Questions and answers

Summary of Contents for Microchip Technology AN908

  • Page 1 The rotor assembly is a simple steel cage. rotor current phasor.  2004 Microchip Technology Inc. DS00908A-page 1...
  • Page 2 With the coordinate transformation, the stator currents can be controlled like DC values using standard control The entire process of transforming, PI iteration, loops. transforming back and generating PWM is illustrated in Figure 1.  2004 Microchip Technology Inc. DS00908A-page 2...
  • Page 3 α axis is proportional to the rotor torque. Now that you + 2i β have these components represented as DC values you √ 3 can control them independently with classic PI control loops.  2004 Microchip Technology Inc. DS00908A-page 3...
  • Page 4 The correct angular position of the rotor flux vector flux producing component of I during transient must be estimated based on known values and motor changes. parameters. This estimation uses a motor equivalent  2004 Microchip Technology Inc. DS00908A-page 4...
  • Page 5 In this case, the D term could cause excessive changes in PWM duty cycle that could affect the operation of the algorithms and produce over current trips.  2004 Microchip Technology Inc. DS00908A-page 5...
  • Page 6 The effective switching frequency is doubled, reducing the ripple current while not increasing the switching losses in the power devices. TABLE 1: SPACE VECTOR MODULATION INVERTER STATES Vector U(000) 2/3V U(111)  2004 Microchip Technology Inc. DS00908A-page 6...
  • Page 7: Code Description

    Each W register used in an assembly module has been assigned a descriptive name that tells what value the register holds during the calculation. The re-naming of the W registers makes the code easier to follow and avoids register usage conflicts.  2004 Microchip Technology Inc. DS00908A-page 7...
  • Page 8 InitCurModel() function is used to clear variables vector calculation loop period, number of motor poles associated with the CurModel() routine. and the maximum motor velocity in revolutions per second.  2004 Microchip Technology Inc. DS00908A-page 8...
  • Page 9 SinCos(); // Calculate qValpha, qVbeta from qSin,qCos,qVd,qVq InvPark(); // Calculate Vr1,Vr2,Vr3 from qValpha, qVbeta CalcRefVec(); // Calculate and set PWM duty cycles from Vr1,Vr2,Vr3 CalcSVGen(); // Clear LED1 for diagnostics pinLED1 = 0;  2004 Microchip Technology Inc. DS00908A-page 9...
  • Page 10 If speed is obtained from another source, these functions are not required for the application. SVGen.s This file has the CalcSVGen() function, which calcu- lates the final PWM values as a function of the 3-phase voltage vector.  2004 Microchip Technology Inc. DS00908A-page 10...
  • Page 11 The encoder can be mounted directly on the front face of the motor, as shown in Figure 12. Any other similar encoder with 500 lines of resolution may be used instead of the U.S. Digital device, if desired.  2004 Microchip Technology Inc. DS00908A-page 11...
  • Page 12 • The isolated hall-effect current sensors are used to measure the motor phase currents. Ensure LK1 and LK2 (next to the 5V regulator) are placed on pins 1 and 2.  2004 Microchip Technology Inc. DS00908A-page 12...
  • Page 13 RD10 not used in application RD11 Demo board PWM output buffer enable (Active low) RD12 not used in application RD13 IC6/CN19 LCD E RD14 IC7/CN20 not used in application  2004 Microchip Technology Inc. DS00908A-page 13...
  • Page 14 SCK2/CN8 Button 1 (S4) (Active low) SDI2/CN9 Button 2 (S5) (Active low) SDO2/CN10 Button 3 (S6) (Active low) SS2/CN11 Button 4 (S7) (Active low)  2004 Microchip Technology Inc. DS00908A-page 14...
  • Page 15: Software Operation

    On when system is in closed loop mode. option is to be used. LED 3 (D8) On when speed is at full value, off when speed is at half value. LED 4 (D9) Not used in the application.  2004 Microchip Technology Inc. DS00908A-page 15...
  • Page 16 A and B signals on the encoder wiring connections. The encoder wiring will also depend on whether the encoder is mounted on the front or rear of the motor.  2004 Microchip Technology Inc. DS00908A-page 16...
  • Page 17 #define TORQUE_MODE statement in the UserParms.h file. This will bypass the outer velocity control loop and feed the potentiometer demand value directly to the I control loop setpoint.  2004 Microchip Technology Inc. DS00908A-page 17...
  • Page 18: Appendix A. References

    Figure 15 and Figure 16 clearly shows the benefits of vector control. The speed change takes less current to execute in closed loop mode. FIGURE 16: PHASE CURRENT VS. VELOCITY, 1000 TO 2000 RPM STEP, OPEN LOOP  2004 Microchip Technology Inc. DS00908A-page 18...
  • Page 19: Appendix B. Source Code

    InitCurModel.c Software License Agreement The software supplied herewith by Microchip Technology Incorporated (the “Company”) is intended and supplied to you, the Company’s customer, for use solely and exclusively with products manufactured by the Company. The software is owned by the Company and/or its supplier, and is protected under applicable copyright laws. All rights are reserved.
  • Page 20 // equivalent to 0.4999 #define dqKb 0x3FFF; // equivalent to 0.4999 //************** Field Weakening ************************************** // Flux reference value in constant torque range. // Determined empirically to give rated volts/hertz #define dqK1 3750;  2004 Microchip Technology Inc. DS00908A-page 20...
  • Page 21 #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" /*********************** END OF GLOBAL DEFINITIONS ********************/ unsigned short uWork; short iCntsPerRev; short iDeltaPos;  2004 Microchip Technology Inc. DS00908A-page 21...
  • Page 22 // 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;  2004 Microchip Technology Inc. DS00908A-page 22...
  • Page 23 // 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  2004 Microchip Technology Inc. DS00908A-page 23...
  • Page 24 // Button 4 does not do anything if(pinButton4) if( !uGF.bit.Btn4Pressed ) uGF.bit.Btn4Pressed = 1; else if( uGF.bit.Btn4Pressed ) // Button just released uGF.bit.Btn4Pressed = 0; //*** ADD CODE HERE FOR BUTTON 4 FUNCTION  2004 Microchip Technology Inc. DS00908A-page 24...
  • Page 25 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;  2004 Microchip Technology Inc. DS00908A-page 25...
  • Page 26 // Execute the velocity control loop PIParmQref.qInMeas = EncoderParm.qVelMech; PIParmQref.qInRef = CtrlParm.qVelRef; CalcPI(&PIParmQref); CtrlParm.qVqRef = PIParmQref.qOut; #endif // PI control for Q PIParmQ.qInMeas = ParkParm.qIq; PIParmQ.qInRef = CtrlParm.qVqRef; CalcPI(&PIParmQ); ParkParm.qVq = PIParmQ.qOut; // PI control for D  2004 Microchip Technology Inc. DS00908A-page 26...
  • Page 27 // Calculate and set PWM duty cycles from Vr1,Vr2,Vr3 CalcSVGen(); // Measure loop time iLoopCnt = TMR1 - iLoopCnt; if( iLoopCnt > iMaxLoopCnt ) iMaxLoopCnt = iLoopCnt; // Clear LED1 for diagnostics pinLED1 = 0;  2004 Microchip Technology Inc. DS00908A-page 27...
  • Page 28 // Use 8 times nominal mechanical speed of motor (in RPM) for scaling MotorParm.iScaleMechRPM = diNomRPM*8; // Number of pole pairs MotorParm.iPoles = diPoles ; // Encoder counts per revolution as detected by the dsPIC quadrature configuration. MotorParm.iCntsPerRev = diCntsPerRev;  2004 Microchip Technology Inc. DS00908A-page 28...
  • Page 29 // Scaling constants: Determined by calibration or hardware design. ReadADCParm.qK = dqK; MeasCurrParm.qKa = dqKa; MeasCurrParm.qKb = dqKb; // Inital offsets InitMeasCompCurr( 450, 730 ); // ============= Current Model =============== if(InitCurModelScaling()) // Error return True;  2004 Microchip Technology Inc. DS00908A-page 29...
  • Page 30 // SEVTCMP: Special Event Compare Count Register // Phase of ADC capture set relative to PWM cycle: 0 offset and counting up SEVTCMP = 2; // Cannot be 0 -> turns off trigger (Missing from doc)  2004 Microchip Technology Inc. DS00908A-page 30...
  • Page 31 // AN7 analog /* ADCSSL: ADC Input Scan Select Register */ ADCSSL = 0; // Turn on A/D module ADCON1bits.ADON = 1; #ifdefDIAGNOSTICS // Initialize Output Compare 7 and 8 for use in diagnostics.  2004 Microchip Technology Inc. DS00908A-page 31...
  • Page 32 > 0x1ff0) Data = 0x1ff0; if(Data < 0x000f) Data = 0x000f; OC7RS = Data; Data = (EncoderParm.qVelMech) + 0x0fff; if(Data > 0x1ff0) Data = 0x1ff0; if(Data < 0x000f) Data = 0x000f; OC8RS = Data; #endif  2004 Microchip Technology Inc. DS00908A-page 32...
  • Page 33 K = 32768; K *= 1 << Nvel; K /= MaxDeltaCnt; if( K >= 32768 ) // Error return True; EncoderParm.qKvel = K; // Initialize private variables used by CalcVelIrp. InitCalcVel(); return False;  2004 Microchip Technology Inc. DS00908A-page 33...
  • Page 34 CurModelParm.qKdelta = 32768.0 * 2 * MotorParm.iPoles * MotorParm.fLoopPeriod * MotorParm.fScaleMechRPS; CurModelParm.qKslip = 32768.0/(6.2832 * MotorParm.iPoles * MotorParm.fScaleMechRPS*MotorParm.fRotorTmConst); // Maximum allowed slip speed CurModelParm.qMaxSlipVel = 32768.0/8; // Initialize private variables used by CurrModel InitCurModel(); return False;  2004 Microchip Technology Inc. DS00908A-page 34...
  • Page 35 _MeasCompCurr global MeasCompCurr _MeasCompCurr: MeasCompCurr: ;; CorrADC1 = ADCBUF1 - iOffsetHa/2^16 ;; qIa = 2 * qKa * CorrADC1 mov.w _MeasCurrParm+ADC_iOffsetHa,w0 sub.w _ADCBUF1,WREG w0 = ADC - Offset clr.w btsc w0,#15 setm  2004 Microchip Technology Inc. DS00908A-page 35...
  • Page 36 ;On Entry: ParkParm structure must contain qSin, qCos, qIa and qIb. ;On Exit: ParkParm will contain qId, qIq ; Parameters: Input arguments: None Return: Void SFR Settings required: CORCON.SATA If there is any chance that (Ia+2*Ib)/sqrt(3) will overflow must set  2004 Microchip Technology Inc. DS00908A-page 36...
  • Page 37 A,[ParmW++] ; store to qId, inc ptr to qIq ;; Iq = -Ialpha*sin(Angle) + Ibeta*cos(Angle) CosW*IbetaW,A ; Ibeta*qCos -> A SinW*IalphaW,A ; sub Ialpha*qSin from A A,[ParmW] ; store to qIq return .end  2004 Microchip Technology Inc. DS00908A-page 37...
  • Page 38 CurModelParm structure must contain qKcur, qKslip, iKpoles, qKdelta, qVelMech, qMaxSlipVel ; On Exit: CurModelParm will contain qAngFlux, qdImag and qVelSlip ; Parameters: Input arguments: None Return: Void SFR Settings required: CORCON.SATA CORCON.IF Support routines required: None Local Stack usage:  2004 Microchip Technology Inc. DS00908A-page 38...
  • Page 39 ;; Calculate Kslip*|IqW| in Acc A to maintain 1.31 mov.w _CurModelParm+CurMod_qKslip,KslipW IqW*KslipW,A ;; Make sure denominator is > numerator else skip term A,w0 ; temporary ImagW,w0 ; |qdImag| - |Kslip*qIq| LEU,jCurModSkip ; skip term: |qdImag| <= |Kslip*qIq|  2004 Microchip Technology Inc. DS00908A-page 39...
  • Page 40 SignW,#0 w0,w0 ;; For testing mov.w w0,_CurModelParm+CurMod_qVelSlip ;; Add mechanical velocity mov.w _CurModelParm+CurMod_qVelMech,w4 add.w w0,w4,w4 mov.w w4,_CurModelParm+CurMod_qVelFlux ;; Load AngFlux to Acc A mov.w _CurModelParm+CurMod_qAngFlux,w1 w1,A mov.w _CurModelParm+CurMod_qKdelta,w5 w4*w5,A A,w4 mov.w w4,_CurModelParm+CurMod_qAngFlux return  2004 Microchip Technology Inc. DS00908A-page 40...
  • Page 41 #_ParkParm+Park_qValpha,ParmW A,[ParmW++] ; store to qValpha, inc ptr to qVbeta ;; Vbeta Vd*sin(Angle) + Vq*cos(Angle) SinW*VdW,A ; Vd*qSin -> A CosW*VqW,A ; add Vq*qCos to A A,[ParmW] ; store to Vbeta return  2004 Microchip Technology Inc. DS00908A-page 41...
  • Page 42 ;=================== CODE ===================== .section .text .global _CalcRefVec .global CalcRefVec _CalcRefVec: CalcRefVec: ;; Get qValpha, qVbeta from ParkParm structure mov.w ParkParm+Park_qValpha,ValphaW mov.w _ParkParm+Park_qVbeta,VbetaW ;; Put Vr1 = Vbeta mov.w VbetaW,_SVGenParm+SVGen_qVr1 ;; Load Sq(3)/2 mov.w #Sq3OV2,ScaleW  2004 Microchip Technology Inc. DS00908A-page 42...
  • Page 43 ValphaW*ScaleW,A ; add Valpha*sqrt(3)/2 to A A,WorkW mov.w WorkW,_SVGenParm+SVGen_qVr2 ;; AccA = -Vbeta/2 VbetaW,#1,A ;; Vr3 = (-Vbeta/2 - sqrt(3)2 * Valpha) ValphaW*ScaleW,A ; sub Valpha*sqrt(3)2 to A A,WorkW mov.w WorkW,_SVGenParm+SVGen_qVr3 return .end  2004 Microchip Technology Inc. DS00908A-page 43...
  • Page 44 ; The accumulation is set back to zero and a new accumulation starts. ;Functional prototype: void CalcVelIrp( void ); ;On Entry: EncoderParm must contain iPrevCnt, iAccumCnt, iVelCntDwn ;On Exit: EncoderParm will contain iPrevCnt, iAccumCnt and iDeltaCnt (if countdown reached zero).  2004 Microchip Technology Inc. DS00908A-page 44...
  • Page 45 Delta < -EncoderParm.iCntsPerRev/2 ) // Delta < -EncoderParm.iCntsPerRev/2 => Pos vel, wrapped around Delta += EncoderParm.iCntsPerRev; EncoderParm.iAccumCnt += Delta; EncoderParm.iVelCntDwn--; if(EncoderParm.iVelCntDwn) return; iVelCntDwn = iIrpPerCalc; qVelMech = qKvel * iAccumCnt * 2^Nvel; EncoderParm.iAccumCnt = 0;  2004 Microchip Technology Inc. DS00908A-page 45...
  • Page 46 2) Vel > 0 and wrapped around lsr.w _EncoderParm+Encod_iCntsPerRev,WREG ; WREG = CntsPerRev/2 ;; Is Delta + CntsPerRev/2 < 0 add.w DeltaW,w0,WorkW ; Delta+CntsPerRev/2 NN,jEncoder20 ; -CntsPerRev/2 <= Delta < 0, Vel > 0  2004 Microchip Technology Inc. DS00908A-page 46...
  • Page 47 ;On Exit: EncoderParm will contain qVelMech ;Parameters: ; Input arguments: None ; Return: Void ; SFR Settings required: None ; Support routines required: None ; Local Stack usage: None ; Registers modified: None  2004 Microchip Technology Inc. DS00908A-page 47...
  • Page 48 ;; iDeltaCnt is an integer but as Q15 it = (iDeltaCnt/2^15) mov.w _EncoderParm+Encod_iDeltaCnt,DeltaW mov.w _EncoderParm+Encod_qKvel,WorkW WorkW*DeltaW,A ; dKvel * (Delta/2^15) A,#(Nvel-15),WorkW ; left shift by 15-Nvel ;; qVelMech = qKvel * Q15( Delta / 2^Nvel ) mov.w WorkW,_EncoderParm+Encod_qVelMech return .end  2004 Microchip Technology Inc. DS00908A-page 48...
  • Page 49 .equ Sq3W, ; OneBySq3 .equ SinW, ; replaces Work0W .equ CosW, .equ IaW, ; copy of qIa .equ IalphaW, ; replaces Ia .equ IbW, ; copy of qIb .equ IbetaW, ; Ibeta replaces Ib  2004 Microchip Technology Inc. DS00908A-page 49...
  • Page 50 A,[ParmW++] ; store to qId, inc ptr to qIq ;; Iq = -Ialpha*sin(Angle) + Ibeta*cos(Angle) CosW*IbetaW,A ; Ibeta*qCos -> A SinW*IalphaW,A ; sub Ialpha*qSin from A A,[ParmW] ; store to qIq return .end  2004 Microchip Technology Inc. DS00908A-page 50...
  • Page 51 = (2^15)/(2 * pi * fRotorTmConst * iPoles * fScaleMechRPS) ;Functional prototype: ; void CurModel( void ) ;On Entry: CurModelParm structure must contain qKcur, qKslip, iKpoles, qKdelta, qVelMech, qMaxSlipVel ;On Exit: CurModelParm will contain qAngFlux, qdImag and qVelSlip  2004 Microchip Technology Inc. DS00908A-page 51...
  • Page 52 ;; First make qIqW and qdImagW positive and save sign in SignW SignW ; set flag sign to positive ;; if( IqW < 0 ) => toggle SignW and set IqW = -IqW mov.w _ParkParm+Park_qIq,IqW Z,jCurModSkip NN,jCurMod1 IqW,IqW SignW,SignW ; toggle sign  2004 Microchip Technology Inc. DS00908A-page 52...
  • Page 53 ;; Limit maximum slip speed mov.w _CurModelParm+CurMod_qMaxSlipVel,w1 w1,w0 ; qMaxSlipSpeed - | Kslip*qIq/qdImag | NN,jCurMod4 ;; result too large: replace it with qMaxSlipSpeed mov.w w1,w0 jCurMod4 jCurModSkip: ;; term skipped entirely - set it = 0 clr.w  2004 Microchip Technology Inc. DS00908A-page 53...
  • Page 54 CORCON,#SATDW mov.w w4,_CurModelParm+CurMod_qAngFlux return ;******************************************************************* ; void InitCurModel(void) Initialize private CurModel variables. ;******************************************************************* ; Register usage for InitCurModel ;******************************************************************* .global _InitCurModel .global InitCurModel _InitCurModel: InitCurModel: clr.w _CurModelParm+CurMod_qAngFlux clr.w _CurModelParm+CurMod_qdImag clr.w _CurModelParm+CurMod_qdImag+2 return .end  2004 Microchip Technology Inc. DS00908A-page 54...
  • Page 55 ; Local Stack usage: ; Registers modified: ??w4,w5,AccA ; Timing: ??8 instruction cycles ;******************************************************************* ;=================== CODE ===================== .section .text ; Register usage for FdWeak .global _FdWeakening .global FdWeakening _FdWeakening: FdWeakening: mov.w _FdWeakParm+FdWeak_qK1,w0 mov.w w0,_CtrlParm+Ctrl_qVdRef return .end  2004 Microchip Technology Inc. DS00908A-page 55...
  • Page 56 ; Register usage .equ ParmW, ; Ptr to ParkParm structure .equ SinW, .equ CosW, .equ VdW, ; copy of qVd .equ VqW, ; copy of qVq ;=================== CODE ===================== .section .text .global _InvPark .global InvPark  2004 Microchip Technology Inc. DS00908A-page 56...
  • Page 57 #_ParkParm+Park_qValpha,ParmW A,[ParmW++] ; store to qValpha, inc ptr to qVbeta ;; Vbeta Vd*sin(Angle) + Vq*cos(Angle) SinW*VdW,A ; Vd*qSin -> A CosW*VqW,A ; add Vq*qCos to A A,[ParmW] ; store to Vbeta return .end  2004 Microchip Technology Inc. DS00908A-page 57...
  • Page 58 If there is any chance that Accumulator will overflow must set CORCON.SATDW = 1 ; Support routines required: None ; Local Stack usage: None ; Registers modified: w0,w1,w4,w5 ; Timing: 29 cycles ;******************************************************************* .include "general.inc" ; External references .include "MeasCurr.inc" .include "Park.inc"  2004 Microchip Technology Inc. DS00908A-page 58...
  • Page 59 _MeasCurrParm+ADC_qKb,w4 w4*w5,A A,#-1,w4 mov.w w4,_ParkParm+Park_qIb ;; iOffset += (ADC-Offset) _MeasCurrParm+ADC_iOffsetLb mov.w w1,w0 addc _MeasCurrParm+ADC_iOffsetHb return .global _InitMeasCompCurr .global InitMeasCompCurr _InitMeasCompCurr: InitMeasCompCurr: clr.w _MeasCurrParm+ADC_iOffsetLa mov.w w0,_MeasCurrParm+ADC_iOffsetHa clr.w _MeasCurrParm+ADC_iOffsetLb mov.w w1,_MeasCurrParm+ADC_iOffsetHb return .end  2004 Microchip Technology Inc. DS00908A-page 59...
  • Page 60 ; Registers modified: ??w4,w5,AccA ; Timing: ??8 instruction cycles ;******************************************************************* ;=================== CODE ===================== .section .text ; Register usage for OpenLoop .equ Work0W, ; Working register .equ Work1W, ; Working register .global _OpenLoop .global OpenLoop  2004 Microchip Technology Inc. DS00908A-page 60...
  • Page 61 OpenLoopParm+OpLoop_qAngFlux,Work1W add.w Work0W,Work1W,Work0W mov.w Work0W,_OpenLoopParm+OpLoop_qAngFlux return ;******************************************************************* ; void InitOpenLoop(void) Initialize private OpenLoop variables. ;******************************************************************* ; Register usage for InitOpenLoop ;******************************************************************* .global _InitOpenLoop .global InitOpenLoop _InitOpenLoop: InitOpenLoop: clr.w _OpenLoopParm+OpLoop_qAngFlux clr.w _OpenLoopParm+OpLoop_qDeltaFlux return .end  2004 Microchip Technology Inc. DS00908A-page 61...
  • Page 62 ; Return: Void ; SFR Settings required: CORCON.SATA= 0 CORCON.IF ; Support routines required: None ; Local Stack usage: ; Registers modified: w0-w6,AccA ; Timing: 31 instruction cycles max, 28 cycles min ;*******************************************************************  2004 Microchip Technology Inc. DS00908A-page 62...
  • Page 63 ;; if( U > Outmax ) Out = Outmax ;; else if( U < Outmin ) Out = Outmin ;; else Out = U mov.w [BaseW0+PI_qOutMax],OutW1 UnlimitW6,OutW1 GT,jPI5 ; U > Outmax; OutW1 = Outmax  2004 Microchip Technology Inc. DS00908A-page 63...
  • Page 64 ;; Ki * Err - Kc * Exc mov.w [BaseW0+PI_qKc],WorkW5 WorkW5*UnlimitW6,A ;; Sum = Sum + Ki * Err - Kc * Exc A,[++BaseW0] ; store Sum mov.w ACCALL,WorkW5 mov.w WorkW5,[--BaseW0] return .end  2004 Microchip Technology Inc. DS00908A-page 64...
  • Page 65 ; Timing: 13 cycles ;******************************************************************* .include "general.inc" ; External references .include "ReadADC.inc" ; Register usage .equ ParmBaseW,w0 ; Base of parm structure .equ Work0W, .equ Work1W, ;=================== CODE ===================== .section .text .global _ReadADC0 .global ReadADC0  2004 Microchip Technology Inc. DS00908A-page 65...
  • Page 66 ;; from -1->.9999 to 0 -> 0.9999 Work1W,#15 lsr.w Work1W,Work1W Work0W*Work1W,A A,#-1,Work0W mov.w Work0W,[ParmBaseW+ADC_qADValue] return .global _ReadSignedADC0 .global ReadSignedADC0 _ReadSignedADC0: ReadSignedADC0: ;; iResult = 2 * qK * ADCBUF0 mov.w [ParmBaseW+ADC_qK],Work0W mov.w _ADCBUF0,Work1W Work0W*Work1W,A A,#-1,Work0W mov.w Work0W,[ParmBaseW+ADC_qADValue] return .end  2004 Microchip Technology Inc. DS00908A-page 66...
  • Page 67 = Tc else // (x01) if( Vr3 >= 0 ) // Sector 5: (1,0,1) 120-180 degrees T1 = Vr1 T2 = Vr3 CalcTimes(); dPWM1 = Tc dPWM2 = Ta dPWM3 = Tb  2004 Microchip Technology Inc. DS00908A-page 67...
  • Page 68 CalcTimes(); dPWM1 = Tc dPWM2 = Tb dPWM3 = Ta ; void CalcTimes(void) T1 = PWM*T1 T2 = PWM*T2 Tc = (PWM-T1-T2)/2 Tb = Ta + T1 Ta = Tb + T2 ;*******************************************************************  2004 Microchip Technology Inc. DS00908A-page 68...
  • Page 69 ;; T1 = Vr2 ;; T2 = Vr1 mov.w Vr2W,T2W mov.w Vr1W,T1W rcall CalcTimes ;; dPWM1 = Ta ;; dPWM2 = Tb ;; dPWM3 = Tc mov.w TaW,dPWM1 mov.w TbW,dPWM2 mov.w TcW,dPWM3 return  2004 Microchip Technology Inc. DS00908A-page 69...
  • Page 70 ;; Sector 2: (0,1,0) 300-360 degrees ;; T1 = -Vr3 ;; T2 = -Vr1 neg.w Vr3W,T2W neg.w Vr1W,T1W rcall CalcTimes ;; dPWM1 = Ta ;; dPWM2 = Tc ;; dPWM3 = Tb mov.w TaW,dPWM1  2004 Microchip Technology Inc. DS00908A-page 70...
  • Page 71 WorkW,T2W,WorkW ; -T2 asr.w WorkW,WorkW ; /2 mov.w WorkW,TcW ; store Tc ;; Tb = Tc + T1 add.w WorkW,T1W,WorkW mov.w WorkW,TbW ;; Ta = Tb + T2 add.w WorkW,T2W,WorkW mov.w WorkW,TaW return  2004 Microchip Technology Inc. DS00908A-page 71...
  • Page 72 ; Pointer into table base .equ Y0W, ; Y0 = SinTable[Index] .equ ParkParmW, ; Base of ParkParm structure ;; Note: RemainderW and Work0W must be even registers ;=================== LOCAL DATA ===================== .section .ndata, "d" SinTable:  2004 Microchip Technology Inc. DS00908A-page 72...
  • Page 73 ;; table but if we use only BYTE operations the wrap is automatic. add.b #0x40,IndexW add.w IndexW,pTabBaseW,pTabPtrW mov.w [pTabPtrW],[ParkParmW] ; write qCos return jInterpolate: ;; Get Y1-Y0 = SinTable[Index+1] - SinTable[Index] add.w IndexW,pTabBaseW,pTabPtrW mov.w [pTabPtrW],Y0W ; Y0 inc2.b IndexW,IndexW ; (Index += 2)&0xFF  2004 Microchip Technology Inc. DS00908A-page 73...
  • Page 74 Y0W,[pTabPtrW],Work0W ; Y1 - Y0 ;; Calcuate Delta = (Remainder*(Y1-Y0)) >> 16 mul.us RemainderW,Work0W,Work0W ;; Work1W contains upper word of (Remainder*(Y1-Y0)) ;; *pCos = Y0 + Delta add.w Work1W,Y0W,[ParkParmW] ; write qCos return .end  2004 Microchip Technology Inc. DS00908A-page 74...
  • Page 75 MPSIM, PICkit, PICDEM, PICDEM.net, PICtail, PowerCal, PowerInfo, PowerMate, PowerTool, rfLAB, Select Mode, SmartSensor, SmartTel and Total Endurance are trademarks of Microchip Technology Incorporated in the U.S.A. and other countries. SQTP is a service mark of Microchip Technology Incorporated in the U.S.A.
  • Page 76: Sales And Service

    Tel: 81-45-471- 6166 Fax: 81-45-471-6122 Suite 22, 41 Rawson Street 505 Eskdale Road Epping 2121, NSW Winnersh Triangle Australia Wokingham Tel: 61-2-9868-6733 Berkshire, England RG41 5TU Fax: 61-2-9868-6755 Tel: 44-118-921-5869 Fax: 44-118-921-5820 02/17/04  2004 Microchip Technology Inc. DS00908A-page 76...