/* ================================================================================= System Name: HVPM_Sensorless File Name: HVPM_Sensorless.C Description: Primary system file for the Real Implementation of Sensorless Field Orientation Control for Three Phase Permanent-Magnet Synchronous Motor (PMSM) Originator: Digital control systems Group - Texas Instruments Note: In this software, the default inverter is supposed to be HVDMC board. ==================================================================================== History: ------------------------------------------------------------------------------------- 10-9-2010 Version 1.1: Supports F2803x ===================================================================================== */ // Include header files used in the main function #include "PeripheralHeaderIncludes.h" #include "IQmathLib.h" #include "HVPM_Sensorless.h" #include "HVPM_Sensorless-Settings.h" #include // F28035_RAM_HVPM_Sensorless.CMD // PAGE0 RAMM0 : origin = 0x000050, length = 0x0003B0 // ramfuncs : > RAMM0, PAGE = 0 #ifdef FLASH #pragma CODE_SECTION(PWM1_Interrupt,"ramfuncs"); //在.cmd文件中對MainISR函數段進行單獨物理地址映射 #pragma CODE_SECTION(U1RX_Interrupt,"ramfuncs"); //在.cmd文件中對U1RX_Interrupt函數段進行單獨物理地址映射 #pragma CODE_SECTION(T0_Interrupt,"ramfuncs"); //在.cmd文件中對T1_Interrupt函數段進行單獨物理地址映射 // Prototype statements for functions found within this file. interrupt void PWM1_Interrupt(void); interrupt void U1RX_Interrupt(void); interrupt void T0_Interrupt(void); interrupt void T1_Interrupt(void); interrupt void T2_Interrupt(void); void DeviceInit(); void MemCopy(); void InitFlash(); void HVDMC_Protection(void); void init_Module(void); void Pressure_calculate(void); void TransCMD_Data(void); void TransmitUART(unsigned char *data); void Reload_ReceiverData(void); // 用於在FLASH 背景運行和在RAM 中 ISR // F28035_RAM_HVPM_Sensorless.CMD // PAGE0 RAMM0 : origin = 0x000050, length = 0x0003B0 // ramfuncs : > RAMM0, PAGE = 0 extern Uint16 *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart; void main(void) { DeviceInit(); // Device Life support & GPIO // HVPM_Sensorless-DevInit_F2803x.c // ADC CALIBRATION , PERIPHERAL CLOCK ENABLES , // Only used if running from FLASH // Note that the variable FLASH is defined by the compiler #ifdef FLASH // Copy time critical code and Flash setup code to RAM // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart // symbols are created by the linker. Refer to the linker files. MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart); // HVPM_Sensorless-DevInit_F2803x.c // Call Flash Initialization to setup flash waitstates // This function must reside in RAM InitFlash(); // Call the flash wrapper init function // HVPM_Sensorless-DevInit_F2803x.c #endif //(FLASH) init_Module(); for(;;) //infinite loop { ByteCTL.disp_rpm.all= desireSpeed; Pressure_calculate(); if ((lsw ==2 && stall_check_EN == 1) && (Disp.DR_Byte_Old != Disp.DR_Byte)) { Soft_stop = 1; } if (ByteCTL.Kgf_cm2.all== 0 ){ //Stop motor entry point in here . ByteCTL.Kgf_cm2.all value is load from calculate( ); if (lsw == 2 && stall_check_EN == 1 ) { Soft_stop = 1;} if (lsw == 1 && stall_check_EN == 0) { Soft_stop = 0; TRANS_delayCount=0; SpeedRpm_Check=0; Charge_Volt = _IQ(0.0900); Pre_desireSpeed = 0; stall_check_EN = 0; smo1.Kslf = _IQ(0.0060); Pre_CMS = 0; CMS = 1; Sprint = 1; Stable_Spd_Count = 0; IER = 0; PieCtrlRegs.PIEIER3.bit.INTx1 = 0; SpeedRef = _IQ(0); EPwm4Regs.CMPA.half.CMPA =0; EPwm3Regs.CMPA.half.CMPA =0; EPwm2Regs.CMPA.half.CMPA =0; EPwm1Regs.CMPA.half.CMPA =0; EPwm4Regs.AQCTLA.all=0x0555; EPwm4Regs.AQCTLB.all=0x0555; EPwm3Regs.AQCTLA.all=0x0555; EPwm3Regs.AQCTLB.all=0x0555; EPwm2Regs.AQCTLA.all=0x0555; EPwm2Regs.AQCTLB.all=0x0555; EPwm1Regs.AQCTLA.all=0x0555; EPwm1Regs.AQCTLB.all=0x0555; Start_motor = 0; Restart_Flag = 0; init_Module(); // re call init_Modele()again to set A/D trig by Force software } } while(Start_motor == 0){ // when motor stop. keep run this while loop and check ByteCTL.Kgf_cm2.all value if (AdcRegs.ADCSOCFLG1.all == 0){ // check all SOCx are No sample pending then AdcRegs.ADCSOCFRC1.all = 0x01ff; // Use Software Force trig SOC0~SOC8 to Convert } ByteCTL.disp_rpm.all= desireSpeed; //load motor desire-speed calculate(); // calculate A/D convert value if (TRANS_delayCount == 250000){ //commucation delay counter TRANS_delayCount=0; TransCMD_Data(); // send data to son board by UART Reload_ReceiverData(); // check data received from son board by UART } else { TRANS_delayCount++; } if (ByteCTL.Kgf_cm2.all > 50){ // if A/D Channel value if grand than 50 then start motor now. Restart_Flag = 1; Disp.DR_Byte_Old = Disp.DR_Byte; // check Motor is CC or CCW set if (Disp.DR_Byte_Old != 0x00) {Rev = 1;} else {Rev = 0;} break; } } //while(Start_motor == 0) if (Restart_Flag == 1) { TransCMD_Data(); // send data to son board by UART Start_motor =1; Soft_stop = 0; TRANS_delayCount=0; SpeedRpm_Check=0; Charge_Volt = _IQ(0.0900); Pre_desireSpeed = 0; stall_check_EN = 0; smo1.Kslf = _IQ(0.0060); Pre_CMS = 0; CMS = 1; Sprint = 1; Stable_Spd_Count = 0; Reload_ReceiverData(); // check data received from son board by UART init_Module(); // re call init_Modele()again to set A/D trig is by PWM1 interrupt } if (TRANS_delayCount > 5000){ //every loop time counter to commucate with son board . TRANS_delayCount=0; TransCMD_Data(); // send data to son board by UART Reload_ReceiverData(); } else { TRANS_delayCount++; } } void init_Module(void) { // Initialize DATALOG module dlog.iptr1 = &DlogCh1; dlog.iptr2 = &DlogCh2; dlog.iptr3 = &DlogCh3; dlog.iptr4 = &DlogCh4; dlog.trig_value = 0x1; dlog.size = 0x00c8; dlog.prescalar = 5; dlog.init(&dlog); pwm1.PeriodMax = SYSTEM_FREQUENCY*1000000*T/2; PWM_INIT_MACRO(pwm1); ADC_MACRO_INIT(); // here is TI exsample macro not change it . speed3.K1 = _IQ21(1/(BASE_FREQ*T)); speed3.K2 = _IQ(1/(1+T*2*PI*6)); speed3.K3 = _IQ(1)-speed3.K2; speed3.BaseRpm = (unsigned long )120*(BASE_FREQ/POLES); rc1.TargetValue = 0; rc1.RampDelayMax = 5; rc1.RampLowLimit = _IQ(-1); rc1.RampHighLimit = _IQ(1); rc1.RampDelayCount = 0; rc1.SetpointValue = 0; rc1.EqualFlag = 0; rg1.Freq = 0; rg1.StepAngleMax = _IQ(BASE_FREQ*T); rg1.Angle = 0; rg1.Gain = _IQ(1); rg1.Out = 0; rg1.Offset = _IQ(1); smo1_const.Rs = RS; smo1_const.Ls = LS;H) smo1_const.Ib = BASE_CURRENT; smo1_const.Vb = BASE_VOLTAGE; smo1_const.Ts = T; SMO_CONST_MACRO(smo1_const); smo1.Fsmopos = _IQ(smo1_const.Fsmopos); smo1.Gsmopos = _IQ(smo1_const.Gsmopos); smo1.Kslide = _IQ(0.15); smo1.Kslf = _IQ(0.0060); pid1_id.Kp = _IQ(0.14); pid1_id.Ki = _IQ(0.007); pid1_id.Kd = _IQ(0); pid1_id.Kc = _IQ(0); pid1_id.OutMax = _IQ(0.95); pid1_id.OutMin = _IQ(-0.95); pid1_id.Ref = _IQ(0) ; pid1_id.Fdb = _IQ(0); pid1_id.Err = _IQ(0); pid1_id.Up = _IQ(0); pid1_id.Ui = _IQ(0) ; pid1_id.Ud = _IQ(0); pid1_id.OutPreSat = _IQ(0); pid1_id.Out = _IQ(0); pid1_id.SatErr = _IQ(0); pid1_id.Up1 = _IQ(0); pid1_iq.Kp = _IQ(0.8); pid1_iq.Ki = _IQ(0.03); pid1_iq.Kd = _IQ(0); pid1_iq.Kc = _IQ(0); pid1_iq.OutMax = _IQ(0.95); pid1_iq.OutMin = _IQ(-0.95); pid1_iq.Ref = _IQ(0) ; pid1_iq.Fdb = _IQ(0); pid1_iq.Err = _IQ(0); pid1_iq.Up = _IQ(0); pid1_iq.Ui = _IQ(0) ; pid1_iq.Ud = _IQ(0); pid1_iq.OutPreSat = _IQ(0); pid1_iq.Out = _IQ(0); pid1_iq.SatErr = _IQ(0); pid1_iq.Up1 = _IQ(0); pid1_spd.Kp = _IQ(0.005); pid1_spd.Ki = _IQ(0.03); pid1_spd.Kd = _IQ(0.20); pid1_spd.Kc = _IQ(0.0); pid1_spd.OutMax = _IQ(0.5); pid1_spd.OutMin = _IQ(-0.95); pid1_spd.Out = _IQ(0); pid1_spd.Ref = _IQ(0); pid1_spd.Fdb = _IQ(0); pid1_spd.Err = _IQ(0); pid1_spd.Up = _IQ(0); pid1_spd.Ui = _IQ(0); pid1_spd.Ud = _IQ(0); pid1_spd.OutPreSat = _IQ(0); pid1_spd.SatErr = _IQ(0); pid1_spd.Up1 = _IQ(0); pid1_Vbus.Kp = _IQ(0.04); pid1_Vbus.Ki = _IQ(0.008); pid1_Vbus.Kd = _IQ(0.05); pid1_Vbus.Kc = _IQ(0); pid1_Vbus.OutMax = _IQ(0.95); pid1_Vbus.OutMin = _IQ(0); pid1_Vbus.Out = _IQ(0) ; pid1_Vbus.Ref = _IQ(0) ; pid1_Vbus.Fdb = _IQ(0); pid1_Vbus.Err = _IQ(0); pid1_Vbus.Up = _IQ(0); pid1_Vbus.Ui = _IQ(0) ; pid1_Vbus.Ud = _IQ(0); pid1_Vbus.OutPreSat = _IQ(0); pid1_Vbus.Out = _IQ(0); pid1_Vbus.SatErr = _IQ(0); pid1_Vbus.Up1 = _IQ(0); speed3.EstimatedTheta = 0; //_IQ(0); speed3.OldEstimatedTheta= 0; //_IQ(0); speed3.EstimatedSpeed = 0; //_IQ(0); speed3.EstimatedSpeedRpm = 0; smo1.Valpha = _IQ(0); smo1.Ealpha = _IQ(0); smo1.Zalpha = _IQ(0); smo1.EstIalpha = _IQ(0); smo1.Vbeta = _IQ(0); smo1.Ebeta = _IQ(0); smo1.Zbeta = _IQ(0); smo1.EstIbeta = _IQ(0); smo1.Ialpha = _IQ(0); smo1.IalphaError = _IQ(0); smo1.Ibeta = _IQ(0); smo1.IbetaError = _IQ(0); smo1.Theta = _IQ(0); svgen_dq1.Ualpha = _IQ(0); svgen_dq1.Ubeta = _IQ(0); svgen_dq1.Ta = _IQ(0); svgen_dq1.Tb = _IQ(0); svgen_dq1.Tc = _IQ(0); volt1.DcBusVolt = _IQ(0); volt1.MfuncV1 = _IQ(0); // Input: Modulation voltage phase A (pu) volt1.MfuncV2 = _IQ(0); // Input: Modulation voltage phase B (pu) volt1.MfuncV3 = _IQ(0); // Input: Modulation voltage phase C (pu) volt1.VphaseA = _IQ(0); // Output: Phase voltage phase A (pu) volt1.VphaseB = _IQ(0); // Output: Phase voltage phase B (pu) volt1.VphaseC = _IQ(0); // Output: Phase voltage phase C (pu) volt1.Valpha = _IQ(0); // Output: Stationary d-axis phase voltage (pu) volt1.Vbeta = _IQ(0); // Output: Stationary q-axis phase voltage (pu) clarke1.As = _IQ(0); clarke1.Bs = _IQ(0); clarke1.Alpha = _IQ(0); clarke1.Beta = _IQ(0); park1.Alpha = _IQ(0); park1.Beta = _IQ(0); park1.Angle = _IQ(0); park1.Ds = _IQ(0); park1.Qs = _IQ(0); park1.Sine = _IQ(0); park1.Cosine = _IQ(0); ipark1.Alpha = _IQ(0); ipark1.Beta = _IQ(0); ipark1.Angle = _IQ(0); ipark1.Ds = _IQ(0); ipark1.Qs = _IQ(0); ipark1.Sine = _IQ(0); ipark1.Cosine = _IQ(0); pwm1.MfuncC1 = 0; pwm1.MfuncC2 = 0; pwm1.MfuncC3 = 0; pwm1.PWM1out = 0; pwm1.PWM2out = 0; pwm1.PWM3out = 0; HVDMC_Protection(); EALLOW; PieVectTable.EPWM1_INT = &PWM1_Interrupt; PieVectTable.SCIRXINTA = &U1RX_Interrupt; PieVectTable.TINT0 = &T0_Interrupt; PieVectTable.TINT1 = &T1_Interrupt; PieVectTable.TINT2 = &T2_Interrupt; CpuTimer0Regs.TIM.half.LSW = 50; // T=1/60*10^6=0.016us // delay 3 seconds =3/0.016us=187.5*10^6=187500000 CpuTimer0Regs.PRD.all=187500000; CpuTimer0Regs.TPR.bit.TDDR = 0; CpuTimer0Regs.TPR.bit.PSC = 0; CpuTimer0Regs.TPRH.bit.TDDRH = 0; CpuTimer0Regs.TPRH.bit.PSCH = 0; CpuTimer0Regs.TCR.bit.SOFT = 0; CpuTimer0Regs.TCR.bit.FREE = 0; CpuTimer0Regs.TCR.bit.TRB = 1; CpuTimer0Regs.TCR.bit.TIF = 1; CpuTimer0Regs.TCR.bit.TIE = 1; CpuTimer0Regs.TCR.bit.TSS = 1; // CpuTimer0Regs.TCR.bit.TSS = 0; if (Restart_Flag == 0) // first power on .the Restart_Flag is '0' will excute SCI init { // SCI-A init here SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback test mode disable // No parity,8 char bits, // async mode, idle-line protocol SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK, // Disable RX ERR, SLEEP, TXWAKE SciaRegs.SCICTL2.all =0x0002; // disable TXRDY interrupt // Enable RXRDY/BRKDT interrupt // full TXRDY flag =0, TX EMPTY flag=0 // LSPCLK = SYSCLKOUT/4 = 60M/4 = 15Mz // BRR = (LSPCLK/SCI Asynchronous BAUD)-1 = (15 500 000/153094(=19133*8))-1 = 97 =0x61 SciaRegs.SCIHBAUD = 0x0000; SciaRegs.SCILBAUD = 0x0061; // 19133 BPS -0.36%_ERROR SciaRegs.SCICCR.bit.LOOPBKENA =0; // disable loop back SciaRegs.SCIFFTX.all=0xC000; //SCIFFENA=1 SCIRST=1 TXFFIENA=0 SciaRegs.SCIFFRX.all=0x0021; //RXFFENA=1 RXFFIL(0~4)=00000 SciaRegs.SCIFFCT.all=0x0000; // SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset TXRDY,TXEMPTY =1 SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1; SciaRegs.SCIFFRX.bit.RXFIFORESET=1; SciaRegs.SCITXBUF=0x00; } PieCtrlRegs.PIEIER1.bit.INTx7 = 1; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; PieCtrlRegs.PIEIER9.bit.INTx1 = 1; EPwm1Regs.ETSEL.bit.INTEN = 1; EPwm1Regs.ETSEL.bit.INTSEL = 1; EPwm1Regs.ETPS.bit.INTPRD = 1; EPwm1Regs.ETCLR.bit.INT = 1; EDIS; if (Restart_Flag == 1) // after power on and motor need Restart excute here { for (Stall_Count=0 ; Stall_Count < 200000 ; Stall_Count++){;} Stall_Count = 0; Restart_Flag = 0; switch (Disp.GR_Byte){ case 1: My_IdRef = _IQ(-0.25); break; case 2: My_IdRef = _IQ(-0.28); break; case 3: My_IdRef = _IQ(-0.30); break; default : My_IdRef = _IQ(-0.25); break; } desireSpeed = Start_Speed; SpdRef_Data = _IQ(((float)desireSpeed / (float)speed3.BaseRpm)); // this SpdRef_Data will load to PWM1 interrupt } IER |= M_INT1; if (Start_motor == 1){ // if Motor want start that enable PWM1 interrupt function. IER |= M_INT3; } IER |= M_INT9; EINT; ERTM; if (Start_motor == 0){ // if Motor want Stop that Reset A/D module trig fucntion in Force software . EALLOW; \ AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; /* Power up band gap */ \ \ DELAY_US(ADC_usDELAY); /* Delay before powering up rest of ADC */ \ \ AdcRegs.ADCCTL1.bit.ADCREFSEL = 1; /* ADINAN0 for VREFHI */ \ AdcRegs.ADCCTL1.bit.VREFLOCONV = 1; /* VREFLO internally connected to the ADC for sampling*/\ AdcRegs.ADCCTL1.bit.ADCREFPWD = 1; /* Power up reference */ \ AdcRegs.ADCCTL1.bit.ADCPWDN = 1; /* Power up rest of ADC */ \ AdcRegs.ADCCTL1.bit.ADCENABLE = 1; /* Enable ADC */ \ \ asm(" RPT#100 || NOP"); \ \ AdcRegs.ADCCTL1.bit.INTPULSEPOS=1; \ AdcRegs.ADCCTL1.bit.TEMPCONV=0; \ \ DELAY_US(ADC_usDELAY); \ AdcRegs.SOCPRICTL.bit.RRPOINTER=0x00;\ AdcRegs.SOCPRICTL.bit.SOCPRIORITY=0x04;\ /******* CHANNEL SELECT *******/ \ \ AdcRegs.ADCSOC0CTL.bit.CHSEL = 0; /*Dummy meas. avoid 1st sample issue Rev0 Picollo*/ \ AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC1CTL.bit.CHSEL = 12; /* ChSelect: ADC B4-> Phase A Current */ \ AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 0; /* Set SOC0 start trigger on EPWM1A */ \ AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; /* Set SOC0 S/H Window to 6+1 ADC Clock Cycles */ \ \ AdcRegs.ADCSOC2CTL.bit.CHSEL = 14; /* ChSelect: ADC B6-> Phase B Current */ \ AdcRegs.ADCSOC2CTL.bit.TRIGSEL = 0; /* PWM1 trig */ \ AdcRegs.ADCSOC2CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC3CTL.bit.CHSEL = 1; \ AdcRegs.ADCSOC3CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC3CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC4CTL.bit.CHSEL = 2; /* ChSelect: ADC A2-> VDC_Det */ \ AdcRegs.ADCSOC4CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC4CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC5CTL.bit.CHSEL = 3; \ AdcRegs.ADCSOC5CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC5CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC6CTL.bit.CHSEL = 4; /* ChSelect: ADC A4-> I_SUM */ \ AdcRegs.ADCSOC6CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC6CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC7CTL.bit.CHSEL = 7; /* ChSelect: ADC A7-> here is control Motor start and stop */ \ AdcRegs.ADCSOC7CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC7CTL.bit.ACQPS = 6; \ \ AdcRegs.ADCSOC8CTL.bit.CHSEL = 6; \ AdcRegs.ADCSOC8CTL.bit.TRIGSEL = 0; \ AdcRegs.ADCSOC8CTL.bit.ACQPS = 6;\ EDIS;\ } }