• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

祝国内电动汽车发力发展,分享电动汽车代码给大家

祝国内电动汽车发力发展,分享电动汽车代码给大家

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.
 *
 * 11/03/05   4.00   -Added support to software for MPLAB tuning
 *                   interface.  This includes the snapshot code.
 *                   Also modified code so that user parameters
 *                   only get initialized at user startup.
 * 15/06/07   5.00  -Added PID tuning support from LABVIEW application
 *      over CAN bus.  Added support for regenerative braking.
 *      PID parameters are now stored in EEPROM memory.
 ************************************************************************
 *      Code Description
 * 
 *  This file demonstrates Vector Control of a 3 phase ACIM using the
 *  dsPIC30F.  SVM is used as the modulation strategy.
 **********************************************************************/

/************** GLOBAL DEFINITIONS ***********/

#define INITIALIZE
#include
#include
#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"

//inlcudes for the CAN1 module
#include
#include "delay.h"
#include "can.h"
#include "uart.h"
#include "stdlib.h"
#include "CAN1IsTXReady.c"
#include "CAN1SendMessage.c"
#include "CAN1Initialize.c"
#include "CAN1SetOperationMode.c"

/*****************Config bit settings****************/
//_FOSC(CSW_FSCM_OFF & XT_PLL8);
//_FWDT(WDT_OFF);
//_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN & PWMxH_ACT_LO & PWMxL_ACT_LO);
///************** END OF GLOBAL DEFINITIONS ***********/


#define TORQUE_MODE  //Motor primarily works on torque mode
//#define DIAGNOSTICS
//#define SNAPSHOT

#ifdef SNAPSHOT
 #define SNAPSIZE  900
 #define SNAP_DELAY  SNAPSIZE/4
 #define SNAP1  ParkParm.qIq
 #define SNAP2  ParkParm.qId
 #define SNAP3  EncoderParm.qVelMech
 int SnapBuf1[SNAPSIZE];
 int SnapBuf2[SNAPSIZE];
 int SnapBuf3[SNAPSIZE];
 int SnapCount;
#endif


unsigned short uWork;
short iCntsPerRev;
short iDeltaPos;
short accelvalue = 0;
short accelvaluelast = 0;
short brakevalue = 0;
short brakevaluelast = 0;
short fluxLast = 0;

union   {
        struct
            {
            unsigned DoLoop:1;
            unsigned BeginStop:1;
            unsigned DoSnap:1;
            unsigned SnapDone:1;
            unsigned OpenLoop:1;
            unsigned RunMotor:1;
            unsigned RunningUpload:1;
            unsigned Btn1Pressed:1;
            unsigned Btn2Pressed:1;
            unsigned Btn3Pressed:1;
            unsigned Btn4Pressed:1;
            unsigned UploadToMonitor:1;
            unsigned ChangeMode:1;
            unsigned ChangeSpeed:1;
            unsigned    :2;
            }bit;
        WORD Word;
        } uGF;        // general flags


 union   {
            long  Long;
            WORD  Word[2];
            short Short[2];
            BYTE  Byte[4];
            } DataUnion;       

tPIParm     PIParmQ;
tPIParm     PIParmQref;
tPIParm     PIParmD;

tReadADCParm ReadADCParm;
tReadADCParm ReadADC3Parm;

char ResetAngle;//RG
char brake,Flaggy, RecFlag = 0;
int temp;

int iRPM,iRPM_old,RPMbuf,RPMave[100], count = 0, i = 0, Torqbuf = 0, Fluxbuf = 0;
short qPID[9] = {1,2,3,4,5,6,7,8,9};
WORD iMaxLoopCnt;
WORD iLoopCnt;
WORD iDispLoopCnt;

/*Declare constants/coefficients/calibration data to be stored in DataEEPROM*/
int _EEDATA(32) fooArrayInDataEE[] = {0,1,2,3,4,5,6,7,8,9,0xA,0xB,0xC,0xD,0xE,0xF};

/*Declare variables to be stored in RAM*/
int fooArray1inRAM[] = {0xAAAA, 0xBBBB, 0xCCCC, 0xDDDD, 0xEEEE, 0xFFFF, 0xABCD, 0xBCDE,
                       0xCDEF, 0xDEFA, 0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555};

short fooArray2inRAM[9];

/******************CAN Variables*********************/
unsigned char send_buffer1[] = {0x00,0x00,0x0}, send_buffer2[] = {0x00,0x00,0x00}, send_buffer3[] = {0x00,0x00,0x00}, receive_buffer[8] = {0,0,0,0,0,0,0,0}, ack_buf[1] = {0x41}, nack_buf[1] = {0x4E};
unsigned char buffer_ready, rx_ready, test; 
float rec = 0, dataf[9] = {0,0,0,0,0,0,0,0,0};
short data[9] = {0,0,0,0,0,0,0,0,0};
unsigned char chk1 = 0, chk2 = 0;
int timeout1 = 0, timeout2 = 0, time_flag = 0;
/******************************************************/
void __attribute__((__interrupt__)) _ADCInterrupt(void);
void SetupBoard( void );
bool SetupPeripherals(void);
void InitUserParms(void);
void DoControl( void );
void Dis_RPM( BYTE bChrPosC, BYTE bChrPosR );
void DiagnosticsOutput(void);
void init(void); //can init
void GetRPM(void);
void GetTorq(void);
void GetFlux(void);
void GetqPIDParms(void);

/************* START OF MAIN FUNCTION ***************/

int main ( void )
{
 ResetAngle = 0;  //flux angle control reset

 int temp = 0;
 
 for( i = 0; i == 100; i++) //clear average RPM buffer
  {
   RPMave[i] = 0;
  }
  i = 0;
  
 init(); //CAN bus initialization
 
  /* Initialize Serial RS 232 (Port B on dev board, 115.2kBaud at 12.29MIPS) */   //RG: this block
 U1BRG = 10;    //Set baud rate. At 12.29 MIPS, should result in 115.2kbps - 4.8 %. Seems to work regardless.
 U1MODEbits.PDSEL = 0b00; //8 bits, no parity
 U1MODEbits.STSEL = 0;  //1 stop bit
 U1MODEbits.UARTEN = 1;  //enable UART, also enables receive
 U1STAbits.UTXEN = 1;  //enable transmit

 U1TXREG = (unsigned char)fooArray2inRAM[7]; //show startup successful on UART
 Wait(0xFFFF);

    SetupPorts();

 while(1)
 {
  
  GetqPIDParms();//Receive PID parameters over CAN bus and store into array

  if((chk1 == 9)&&(chk2 == 9))//if all parameters have been received
  {
   chk1 = 0; //clear reception check variables
   chk2 = 0;
   
   Wait(0xFFFF);
   
   //set normal mode
   CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_NOR);
   Wait(0x000F);
   //send ack to LABVIEW application
   CAN1SendMessage(1, 1, ack_buf, 0x01,0x00);
   while(!CAN1IsTXReady(0));
   
   /*Erase 16 words (1 row in dsPIC30F DataEEPROM) in Data EEPROM from array named "fooArrayinDataEE" */
   temp = EraseEE(__builtin_tblpage(&fooArrayInDataEE[0]), __builtin_tbloffset(&fooArrayInDataEE[0]), 16);

   /*Write 16 words (1 row in dsPIC30F DataEEPROM) to Data EEPROM from array named "fooArray1inRAM" */
   /*to array named "fooArrayinDataEE" */
   temp = WriteEE(&qPID[0],__builtin_tblpage(&fooArrayInDataEE[0]),__builtin_tbloffset(&fooArrayInDataEE[0]), 16);
   
   //break;
   RecFlag = 1;
  }
  
  if((chk1 != chk2)||(time_flag == 1))//if all parameters have not been received
  {
   //set normal mode
   CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_NOR);
   
   //send nack
   CAN1SendMessage(1, 1, nack_buf, 0x01,0x00);
   while(!CAN1IsTXReady(0));

   chk1 = 0; //clear reception check variables
   chk2 = 0;
   
   time_flag = 0; //clear timeout flag
   
   //set listen mode
   CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_LISTENALL);
   //break;
   RecFlag = 0;
  }  
  
  if(pinButton1)//if button pressed then break and start motor normal operation mode
  {
   //set CAN bus to normal operation
   CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_NOR);
   Wait(0x000F);
    break;
  }   
 }
 //Initialized user parameters
 InitUserParms();
   
    while(1)
        {
        uGF.Word = 0;                   // clear flags
       
        // init Mode
        uGF.bit.OpenLoop = 0;           // start in closed loop
  
  // init LEDs
        pinLED1 = 0;
        pinLED2 = !uGF.bit.OpenLoop;
        pinLED3 = 0;
        pinLED4 = 0;

        // init board
        SetupBoard();
       
        // init user specified parms and stop on error
        if( SetupPeripherals() )
            {
            // Error
            uGF.bit.RunMotor=0;
            return;
            }
       
        // zero out i sums
        PIParmD.qdSum = 0;
        PIParmQ.qdSum = 0;
        PIParmQref.qdSum = 0;
    
        iMaxLoopCnt = 0;
       
        // 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
            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;

  //Run Motor loop
        while(1)
            {
            ClrWdt();
                         
            // The code that updates the LCD display and polls the buttons
            // executes every 50 msec.
           
            if(iDispLoopCnt >= dDispLoopCnt)
             {
         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;
                        }
                    }
                  
                }  // end of display and button polling code             
                //********************************************************************************************************
    //CAN STUFF FOLLOWS

    //Calculate RPM and send it to LABVIEW application
    GetRPM();
    while(!CAN1IsTXReady(0));
    IEC0bits.ADIE = 0;
    CAN1SendMessage(1, 1, send_buffer1, 0x03,0x00);
    IEC0bits.ADIE = 1;
    while(!CAN1IsTXReady(0));
   // Wait(0x00FF);
       
    
    //Calculate torque and send it to LABVIEW application
    GetTorq();
    while(!CAN1IsTXReady(1));
    IEC0bits.ADIE = 0;
    CAN1SendMessage(1, 1, send_buffer2, 0x03,0x01);
    IEC0bits.ADIE = 1;
    while(!CAN1IsTXReady(1));
   // Wait(0x00FF);
   
    //Calculate flux and send it to LABVIEW application
    GetFlux();
    while(!CAN1IsTXReady(2));
    IEC0bits.ADIE = 0;
    CAN1SendMessage(1, 1, send_buffer3, 0x03,0x02);
    IEC0bits.ADIE = 1;
    while(!CAN1IsTXReady(2));
    //Wait(0xFFF);
    //*************************************************************************************************************
            }   // 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).
    ReadADC0( &ReadADCParm );
   if(((unsigned int)ReadADCParm.qADValue < 100 )) //small deadband at lowest range to pot
 {
  pinPWMOutputEnable_ = 1; //disable PWM outputs
  ReadADCParm.qADValue = 0;
  brake = 0;
 }
 else
 {

  pinPWMOutputEnable_ = 0; //enable PWM outputs

  //use deadbands for gas and brake
//  if((unsigned int)ReadADCParm1.qADValue < 100 )
//  {
//   ReadADCParm1.qADValue = 0;
//   brake = 0;
//  }
//  if((unsigned int)ReadADCParm.qADValue < 100 )
//  {
//   ReadADCParm.qADValue = 0;
//  }  
  
 }
 
  //Regenerative Braking support not used but can be added
  //accelvalue = ReadADCParm.qADValue.
     //accelvalue = ((0x7FFF & (0x7FFF - (unsigned short)ReadADCParm.qADValue))-9251)*2; //scaling
  //accelvalue += accelvalue/5; //scaling
  
  //the addition and multiplication was resulting in a roll overso that sometimes when the pedal was fully pressed it
  //equaled -32000 the following code says that if the value goes negative and the last value measured was over 30000 then
  //the negative value is a result of rollover so set the value to maximum
 // if(accelvalue < 0 && accelvaluelast > 30000)
 //  accelvalue = 32767;
   
  //due to scaling there was a negative value when the pedal is released. since negative values are not wanted set value to
  //zero
 // if(accelvalue < 0)
 //  accelvalue = 0;
 // accelvaluelast = accelvalue; //last value measured
 // ReadADCParm.qADValue = accelvalue; //put the scaled value into the variable used for speed control
  
  //Set speed/torque reference
  CtrlParm.qVelRef = ReadADCParm.qADValue >> 1;


        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
          PIParmQref.qInMeas = EncoderParm.qVelMech;
          PIParmQref.qInRef  = CtrlParm.qVelRef;
          CalcPI(&PIParmQref);
          CtrlParm.qVqRef    = PIParmQref.qOut;
            }
      
      
        // 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;
        #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__)) _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 )
 {
  // Set LED1 for diagnostics
  pinLED1 = 1;
  
  
  // use TMR1 to measure interrupt time for diagnostics
  TMR1 = 0;          
  iLoopCnt = TMR1;
  
  // Calculate qIa,qIb
  MeasCompCurr();
  
  // Calculate qId,qIq from qSin,qCos,qIa,qIb
  ClarkePark();
  
  // Calculate control values
  DoControl();
  
  // Calculate qSin,qCos from qAngle
  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();
  
  // Measure loop time
  iLoopCnt = TMR1 - iLoopCnt;
  if( iLoopCnt > iMaxLoopCnt )
  iMaxLoopCnt = iLoopCnt;
  
  // Clear LED1 for diagnostics
  pinLED1 = 0;  
 }   
}

//---------------------------------------------------------------------
// SetupBoard
//
// Initialze board
//---------------------------------------------------------------------

void SetupBoard( void )
{
    BYTE b;

    // Disable ADC interrupt
    IEC0bits.ADIE = 0;

    // Reset any active faults on the motor control power module.
    //pinFaultReset = 1;
    //for(b=0;b<10;b++)
        Nop();
    //pinFaultReset = 0;


    // Ensure PFC switch is off.
    pinPFCFire = 0;
    // Ensure brake switch is off.
    pinBrakeFire = 0;
}

//---------------------------------------------------------------------
// Dis_RPM
//
// Display RPM
//---------------------------------------------------------------------

void Dis_RPM( BYTE bChrPosC, BYTE bChrPosR )
{
 iRPM_old = iRPM;      
    iRPM = EncoderParm.iDeltaCnt*60/(MotorParm.fLoopPeriod*MotorParm.iIrpPerCalc*EncoderParm.iCntsPerRev);
    iRPM = (iRPM + iRPM_old) >> 1;
}   
//---------------------------------------------------------------------

void InitUserParms(void)
{
 int dummy =0, index = 0xF000, num = 0;

 // Turn saturation on to insure that overflows will be handled smoothly.
    CORCONbits.SATA  = 0;

    // Setup required parameters

 // Pick scaling values to be 8 times nominal for speed and current
 
 // 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;   
 
 // Rotor time constant in sec
    MotorParm.fRotorTmConst = dfRotorTmConst;

    // Basic loop period (in sec).  (PWM interrupt period)
    MotorParm.fLoopPeriod = dLoopInTcy * dTcy;  //Loop period in cycles * sec/cycle

    // Encoder velocity interrupt period (in sec).
    MotorParm.fVelIrpPeriod = MotorParm.fLoopPeriod;

    // Number of vel interrupts per velocity calculation.
    MotorParm.iIrpPerCalc = diIrpPerCalc;       // In loops

    // Scale mechanical speed of motor (in rev/sec)
    MotorParm.fScaleMechRPS = MotorParm.iScaleMechRPM/60.0;

    // Scaled flux speed of motor (in rev/sec)
    // All dimensionless flux velocities scaled by this value.
    MotorParm.fScaleFluxRPS = MotorParm.iPoles*MotorParm.fScaleMechRPS;

    // Minimum period of one revolution of flux vector (in sec)
    MotorParm.fScaleFluxPeriod = 1.0/MotorParm.fScaleFluxRPS;

    // Fraction of revolution per LoopTime at maximum flux velocity
    MotorParm.fScaleFracRevPerLoop = MotorParm.fLoopPeriod * MotorParm.fScaleFluxRPS;

    // Scaled flux speed of motor (in radians/sec)
    // All dimensionless velocities in radians/sec scaled by this value.
    MotorParm.fScaleFluxSpeed = 6.283 * MotorParm.fScaleFluxRPS;

    // Encoder count rate at iScaleMechRPM
    MotorParm.lScaleCntRate = MotorParm.iCntsPerRev * (MotorParm.iScaleMechRPM/60.0);

 

 // ============= Open Loop ======================
 
     OpenLoopParm.qKdelta = 32768.0 * 2 * MotorParm.iPoles * MotorParm.fLoopPeriod * MotorParm.fScaleMechRPS;
     OpenLoopParm.qVelMech = dqOL_VelMech;   
     CtrlParm.qVelRef = OpenLoopParm.qVelMech;
 
     InitOpenLoop();
  
 // ============= Field Weakening ===============
 // Field Weakening constant for constant torque range
     FdWeakParm.qK1 = dqK1;       // Flux reference value
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++=
//Load Coefficients from EEPROM 

 /*Read array named "fooArrayinDataEE" from DataEEPROM and place the result into*/
 /*array in RAM named, "fooArray2inRAM" */
 temp = ReadEE(__builtin_tblpage(&fooArrayInDataEE[0]),__builtin_tbloffset(&fooArrayInDataEE[0]),&fooArray2inRAM[0], 16);
 
 //Read EEPROM array and write to UART for trouble shooting
 data[0] = fooArray2inRAM[0];
 dataf[0] = (float)data[0]/10000;
 U1TXREG = (unsigned char)data[0];
 Wait(0xFFFF);
 data[1] = fooArray2inRAM[1];
 dataf[1] = (float)data[1]/10000;
 U1TXREG = (unsigned char)data[1];
 Wait(0xFFFF);
 data[2] = fooArray2inRAM[2];
 dataf[2] = (float)data[2]/10000;
 U1TXREG = (unsigned char)data[2];
 Wait(0xFFFF);
 data[3] = fooArray2inRAM[3];
 dataf[3] = (float)data[3]/10000;
 U1TXREG = (unsigned char)data[3];
 Wait(0xFFFF);
 data[4] = fooArray2inRAM[4];
 dataf[4] = (float)data[4]/10000;
 U1TXREG = (unsigned char)data[4];
 Wait(0xFFFF);
 data[5] = fooArray2inRAM[5];
 dataf[5] = (float)data[5]/10000;
 U1TXREG = (unsigned char)data[5];
 Wait(0xFFFF);
 data[6] = fooArray2inRAM[6];
 dataf[6] = (float)data[6]/10000;
 U1TXREG = (unsigned char)data[6];
 Wait(0xFFFF);
 data[7] = fooArray2inRAM[7];
 dataf[7] = (float)data[7]/10000;
 U1TXREG = (unsigned char)data[7];
 Wait(0xFFFF);
 data[8] = fooArray2inRAM[8];
 dataf[8] = (float)data[8]/10000;
 U1TXREG = (unsigned char)data[8];
 Wait(0xFFFF);
    
//  if(RecFlag == 1) //If PID params have been received over CAN bus then load them into RAM
//  {

   // ============= PI D Term ===============     
      PIParmD.qKp = data[0];      
      PIParmD.qKi = data[1];             
      PIParmD.qKc = data[2];      
      PIParmD.qOutMax = dDqOutMax;
      PIParmD.qOutMin = -PIParmD.qOutMax;
  
      InitPI(&PIParmD);
  
  // ============= PI Q Term ===============
      PIParmQ.qKp = data[3];   
      PIParmQ.qKi = data[4];
      PIParmQ.qKc = data[5];
      PIParmQ.qOutMax = dQqOutMax;
      PIParmQ.qOutMin = -PIParmQ.qOutMax;
  
      InitPI(&PIParmQ);
  
  // ============= PI Qref Term ===============
      PIParmQref.qKp = data[6];      
      PIParmQref.qKi = data[7];      
      PIParmQref.qKc = data[8];      
      PIParmQref.qOutMax = dQrefqOutMax;  
      PIParmQref.qOutMin = -PIParmQref.qOutMax;

      InitPI(&PIParmQref); 
//  }
//  else //load PID params from RAM for trouble shooting
//  { 
//       // ============= PI D Term ===============     
//       PIParmD.qKp = dDqKp;      
//       PIParmD.qKi = dDqKi;             
//       PIParmD.qKc = dDqKc;      
//       PIParmD.qOutMax = dDqOutMax;
//       PIParmD.qOutMin = -PIParmD.qOutMax;
//   
//       InitPI(&PIParmD);
//   
//   // ============= PI Q Term ===============
//       PIParmQ.qKp = dQqKp;   
//       PIParmQ.qKi = dQqKi;
//       PIParmQ.qKc = dQqKc;
//       PIParmQ.qOutMax = dQqOutMax;
//       PIParmQ.qOutMin = -PIParmQ.qOutMax;
//   
//       InitPI(&PIParmQ);
//   
//   // ============= PI Qref Term ===============
//       PIParmQref.qKp = dQrefqKp;      
//       PIParmQref.qKi = dQrefqKi;      
//       PIParmQref.qKc = dQrefqKc;      
//       PIParmQref.qOutMax = dQrefqOutMax;  
//       PIParmQref.qOutMin = -PIParmQref.qOutMax;
//  
//      InitPI(&PIParmQref);
//   
//     }
    // ============= ADC - Measure Current & Pot ======================

    // Scaling constants: Determined by calibration or hardware design.
    ReadADCParm.qK      = dqK;   
    ReadADC3Parm.qK      = dqK;   
   
    MeasCurrParm.qKa    = dqKa;   
    MeasCurrParm.qKb    = dqKb;  

    // Inital offsets
    InitMeasCompCurr( 450, 730 );
 
}


//---------------------------------------------------------------------
bool SetupPeripherals(void)
{
// ============= Encoder ===============

    if( InitEncoderScaling() )
        // Error
        return True;

// ============= Current Model ===============

    if(InitCurModelScaling())
        // Error
        return True;

// ============= SVGen ===============
    // Set PWM period to Loop Time
    SVGenParm.iPWMPeriod = dLoopInTcy;     

// ============= TIMER #1 ======================
    PR1 = 0xFFFF;
    T1CONbits.TON = 1;
    T1CONbits.TCKPS = 1;    // prescale of 8 => 1.08504 uS tick

// ============= Motor PWM ======================

    PDC1 = 0;
    PDC2 = 0;
    PDC3 = 0;
    PDC4 = 0;

    // Center aligned PWM.
    // Note: The PWM period is set to dLoopInTcy/2 but since it counts up and
    // and then down => the interrupt flag is set to 1 at zero => actual
    // interrupt period is dLoopInTcy

    PTPER = dLoopInTcy/2;   // Setup PWM period to Loop Time defined in parms.h

    PWMCON1 = 0x0077;       // Enable PWM 1,2,3 pairs for complementary mode
    DTCON1 = dDeadTime;     // Dead time
    DTCON2 = 0;
    FLTACON = 0;            // PWM fault pins not used
    FLTBCON = 0;
    PTCON = 0x8002;         // Enable PWM for center aligned operation

    // 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)      
    SEVTCMPbits.SEVTDIR = 0;

// ============= Encoder ===============

    MAXCNT = MotorParm.iCntsPerRev;   
    POSCNT = 0;
    QEICON = 0;
    QEICONbits.QEIM = 7;    // x4 reset by MAXCNT pulse
    QEICONbits.POSRES = 0;  // Don't allow Index pulse to reset counter
    QEICONbits.SWPAB = 1;   // direction
    DFLTCON = 0;            // Digital filter set to off

// ============= ADC - Measure Current & Pot ======================
// ADC setup for simultanous sampling on
//      CH0=AN7, CH1=AN0, CH2=AN1, CH3=AN2.
// Sampling triggered by PWM and stored in signed fractional form.

    ADCON1 = 0;
    // Signed fractional (DOUT = sddd dddd dd00 0000)
    ADCON1bits.FORM = 3;   
    // Motor Control PWM interval ends sampling and starts conversion
    ADCON1bits.SSRC = 3; 
    // Simultaneous Sample Select bit (only applicable when CHPS = 01 or 1x)
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    // Samples CH0 and CH1 simultaneously (when CHPS = 01)
    ADCON1bits.SIMSAM = 1; 
    // Sampling begins immediately after last conversion completes.
    // SAMP bit is auto set.
    ADCON1bits.ASAM = 1; 


    ADCON2 = 0;
    // Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
    ADCON2bits.CHPS = 2; 


    ADCON3 = 0;
    // A/D Conversion Clock Select bits = 8 * Tcy
    ADCON3bits.ADCS = 15; 


    /* ADCHS: ADC Input Channel Select Register */
    ADCHS = 0;
    // CH0 is AN7
    ADCHSbits.CH0SA = 7;
    // CH1 positive input is AN0, CH2 positive input is AN1, CH3 positive input is AN2
    ADCHSbits.CH123SA = 0;


    /* ADPCFG: ADC Port Configuration Register */
    // Set all ports digital
    ADPCFG = 0xFFFF;
    ADPCFGbits.PCFG0 = 0;   // AN0 analog
    ADPCFGbits.PCFG1 = 0;   // AN1 analog
    ADPCFGbits.PCFG2 = 0;   // AN2 analog
    ADPCFGbits.PCFG7 = 0;   // AN7 analog


    /* ADCSSL: ADC Input Scan Select Register */
    ADCSSL = 0;

    // Turn on A/D module
    ADCON1bits.ADON = 1;
   
    return False;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Function:  init

Description: This function will initialize the CAN bus module for the purpose
of communicating with the LABVIEW interface.  The default mode will be
LISTENALL after this code is executed.  The default bit rate is 125 kbps with
an oscillator frequency of 20MHz.

Input arguments: void
Output arguments: void

*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void init(void)

 
 //set up registers fCAN = fOSC
 //normal operation mode
 //no abort
 CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_CONFIG); 
 
 
 //set baud rate pre scale(BRP) to 6, phase segments to 8 TQ each and Propagation time to 8 TQ.
 CAN1Initialize(CAN_SYNC_JUMP_WIDTH1 & CAN_BAUD_PRE_SCALE(19), CAN_PHASE_SEG2_TQ(6) & CAN_PHASE_SEG1_TQ(7)& CAN_PROPAGATIONTIME_SEG_TQ(2));
     
     
 CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_NOR); 
// CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_LOOPBK); 
 
// //set up registers
// //transmit registers
 C1TX0CON = 0x0003;//buffer zero, highest priority
 C1TX1CON = 0x0002;//buffer one, high intermediate priority
 C1TX0CON = 0x0001;//buffer two, low intermediate priority
// 
// //receive register
 C1RX0CON = 0x0004;//allow buffer rollover, allow jump table offset between 0 and 1
 
 //SID
 C1RX0SID = 0X0000;
 C1RX1SID = 0X0000;
 C1RX0EID = 0X0000;
 C1RX1EID = 0X0000;
 
 
 C1CTRLbits.CANCAP = 1;
// //message acceptance filters //buffer 0//the masks are all set to zero so all filter bits are not considered (C1RXMnSID)
 C1RXF0SID = 0x0000;//EXIDE = 1//enable filter for standard identifiers, the rest of this register is used for id bits
//      //bits 12-2 ===== SID <10:0>
 C1RXF0EIDH = 0X0000;
 C1RXF0EIDL = 0X0000;
 C1RXM0SID = 0x0000;//MIDE set to one to match only standard messages as determined by EXIDE 
 C1RXM0EIDH = 0x0000;
 C1RXM0EIDL = 0x0000;
// 
// //buffer 1
 C1RXF1SID = 0x0000;//EXIDE = 1//enable filter for standard identifiers, the rest of this register is used for id bits
//      //bits 12-2 ===== SID <10:0>
 C1RXF1EIDH = 0X0000;
 C1RXF1EIDL = 0X0000;
 C1RXM1SID = 0x0000;//MIDE set to one to match only standard messages as determined by EXIDE 
 C1RXM1EIDH = 0x0000;
 C1RXM1EIDL = 0x0000; 
/* Load mask and filter registers */ 
CAN1SetFilter(0, CAN_FILTER_SID(0) & CAN_RX_EID_DIS, CAN_FILTER_EID(0));
CAN1SetMask(0, CAN_MASK_SID(0) & CAN_IGNORE_FILTER_TYPE, CAN_MASK_EID(0));

/* Set transmitter and receiver modes */
CAN1SetTXMode(0,CAN_TX_REQ & CAN_TX_PRIORITY_HIGH );
CAN1SetTXMode(1,CAN_TX_REQ & CAN_TX_PRIORITY_HIGH );
CAN1SetTXMode(2,CAN_TX_REQ & CAN_TX_PRIORITY_HIGH );
CAN1SetRXMode(0,CAN_RXFUL_CLEAR &CAN_BUF0_DBLBUFFER_EN);

CAN1SetOperationMode(CAN_CAPTURE_EN & CAN_IDLE_CON & CAN_MASTERCLOCK_1 & CAN_REQ_OPERMODE_LISTENALL);       
}  

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Function:  GetRPM

Description: This function will add up 100 RPM readings and vaverage them.
The value of RPM is global and is not modified by this function. 
The send_buffer1 will be modified once the average has been calculated and
will have and identifying byte appended to it.

Input arguments: void
Output arguments: void

*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
void GetRPM(void)
{
 
//if(count < 100)
// {
//  RPMbuf = 0;
//  RPMave[count] = iRPM;
//  count++;
// }
// if(count >= 100)
// {
//  for( i = 0; i == 100; i++)
//  {
//   RPMbuf = RPMbuf + RPMave[i];
//  }
//  RPMbuf = RPMbuf/100;
  RPMbuf = iRPM;
  //RPMbuf = 700;
  
  if(RPMbuf > 2000)
  {
   RPMbuf = 2000;
  }  
  if(RPMbuf < 0)
  {
   RPMbuf = 0;
  }
  send_buffer1[0] = 0x01;
  send_buffer1[1] = (unsigned char)RPMbuf;
  RPMbuf = RPMbuf >> 8;
  send_buffer1[2] = (unsigned char)RPMbuf;
  if(send_buffer1[2] == 0x00)
  {
    send_buffer1[2] = 0xFF;//bit stuffing for LABVIEW application
  }
  if((send_buffer1[2] == 0x00)&&(send_buffer1[1] == 0x00))
  {
    send_buffer1[1] = 0xFE;//bit stuffing for LABVIEW application
    send_buffer1[2] = 0xFE;//bit stuffing for LABVIEW application
  }  

  count = 0;
// }

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Function:  GetTorq

Description: This function will get the current torque. The value of torque is
global and is not modified by this function.  The send_buffer2 will be modified
once the average has been calculated and will have and identifying byte appended
to it.

Input arguments: void
Output arguments: void

*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void GetTorq(void)
{  
 unsigned int maskpos = 0x8000, maskneg = 0x7FFF, maskbit = 0x8000;
 unsigned int value = 0, masknum = 0;
 
  value = ParkParm.qIq; //get current torque value
  masknum = value & maskbit;
  if(masknum == 0)
  {
   value = value | maskpos;
  } 
  else
  {
   value = value & maskneg;
  } 
  Torqbuf = value;
  //load CAN bus buffer
  send_buffer2[0] = 0x02;
  send_buffer2[1] = (unsigned char)Torqbuf;
  Torqbuf = Torqbuf >> 8;
  send_buffer2[2] = (unsigned char)Torqbuf;
  if(send_buffer1[2] == 0x00)
  {
    send_buffer1[2] = 0xFF; //bit stuffing for LABVIEW application
  }

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Function:  GetFlux

Description: This function will get the current flux. The value of flux is
global and is not modified by this function.  The send_buffer3 will be modified
once the average has been calculated and will have and identifying byte appended
to it.

Input arguments: void
Output arguments: void

*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void GetFlux(void)

 
  unsigned int maskpos = 0x8000, maskneg = 0x7FFF, maskbit = 0x8000;
 unsigned int value = 0, masknum = 0;
 
  value = ParkParm.qId; //get current torque value
  masknum = value & maskbit;
  if(masknum == 0)
  {
   value = value | maskpos;
  } 
  else
  {
   value = value & maskneg;
  } 
  Fluxbuf = value;  //get current torque value
  //load CAN bus buffer
  send_buffer3[0] = 0x03;
  send_buffer3[1] = (unsigned char)Fluxbuf;
  Fluxbuf = Fluxbuf >> 8;
  send_buffer3[2] = (unsigned char)Fluxbuf;
  if(send_buffer1[2] == 0x00)
  {
    send_buffer1[2] = 0xFF; //bit stuffing for LABVIEW application
  }

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Function:  GetPID Parms

Description: This function will recieve CAN messages and parse through them
to get the PID parameters.  The parameters are being sent 9 at a time with
a short delay between them.  This function also handles a timeout and corrupted
transmissions.

Input arguments: void
Output arguments: void

*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
void GetqPIDParms(void)
{
  int buf = 0, dummy1, dummy2;
  unsigned char chksum = 0;
 
  if(timeout1 == 1) //if a timeout situation is occurring
  {
   timeout2++; //increment timer
  }
  if(timeout2 == 0xFFFF) //if a timeout has occurred
  {
   timeout1 = 0; //reset timers
   timeout2 = 0;
   time_flag = 1; //set flag to indicate a timeout
  }
   
  rx_ready = C1RX0CONbits.RXFUL;
  if(rx_ready  == 1)
  {
   timeout1 = 1; //if a packet was received then start timer
   CAN1ReceiveMessage(receive_buffer, 0x08, 0x00);  //receive packet
   //put packet out on UART for trouble shooting
   U1TXREG = receive_buffer[0];
   Wait(0x00FF);
   U1TXREG = receive_buffer[1];
   Wait(0x00FF);
   U1TXREG = receive_buffer[2];
   Wait(0x00FF);
   U1TXREG = receive_buffer[3];
   Wait(0x00FF);
 
   C1RX0CONbits.RXFUL = 0; //clear CAN bus receive flag

   chksum = receive_buffer[0] + receive_buffer[1] + receive_buffer[2]; //calculate checksum
   buf = buf | (int)receive_buffer[2]; //Make CAN bytes into an int
   buf = buf << 8; 
   buf = buf | (int)receive_buffer[1]; 
   //Load qPID coefficients buffer for EEPROM storage later
   if(chksum == receive_buffer[3])
   {
    switch (receive_buffer[0]) //check ID byte
    {

     case 0x0B:
     {
      qPID[0] = buf;
      chk1 = 1;
      chk2++;   
      break; 
     }
     case 0x0C:
     {
      qPID[1] = buf;
      chk1 = 2;
      chk2++;
      break; 
     }
     case 0x0D:
     {
      qPID[2] = buf;
      chk1 = 3;
      chk2++;
      break; 
     }
     case 0x0E:
     {
      qPID[3] = buf;
      chk1 = 4;
      chk2++;
      break; 
     }
     case 0x0F:
     {
      qPID[4] = buf;
      chk1 = 5;
      chk2++;
      break; 
     }
     case 0x10:
     {
      qPID[5] = buf;
      chk1 = 6;
      chk2++;
      break; 
     }
     case 0x11:
     {
      qPID[6] = buf;
      chk1 = 7;
      chk2++;
      break; 
     }
     case 0x12:
     {
      qPID[7] = buf;
      chk1 = 8;
      chk2++;
      break; 
     }
     case 0x13:
     {
      qPID[8] = buf;
      chk1 = 9;
      chk2++;
      timeout1 = 0;
      break; 
     } 
     default:
     {
     

 

 

 

 

全部回复(7)
正序查看
倒序查看
tvro
LV.13
2
2011-09-25 22:04
楼主是好人
0
回复
2011-09-27 20:23
学习学习啊
0
回复
mybike
LV.1
4
2011-10-05 22:35

楼主好人啊,不过我对这个只认识字母和数字,连起来就不认识了

0
回复
yuzixuan
LV.8
5
2011-10-15 22:31
没有注释,降低了可读性
0
回复
tissot
LV.2
6
2011-12-23 17:00

PIC网站上随便找个代码就说电动汽车!唉!

0
回复
jade1988
LV.4
7
2011-12-23 17:28
哪块用的?
0
回复
2011-12-25 12:27
@yuzixuan
没有注释,降低了可读性

是的一般都要注释,不然看的很吃力。说明俺们功力不够,还要多学习

0
回复