Part Number: TMDSSOLARUINVKIT
Hello and good afternoon,
I have a super noob question concerning the TI Solar Micro Inverter Development kit. My embedded programing skills extend to one university course implementing very basic functions. I am not 100% certain on how to execute section 6.1.3.1 numbers 5 and 6 which read as follows: 5.Run an offset calibration routine to calculate the analog offset on the ADC input channels for PV current and the grid. 6. Configure the interrupt for a 50-KHz ISR, which is used for the control loop and 1-KHz ISR for background tasks. The 1-KHz ISR is chosen such that the 50-KHz ISR can interrupt the 1-KHz ISR.
Is there a demonstration somewhere or a HowTo that will explain exactly what I need to do with the given code? I have used MPLAB IDE but never Code Composer. I am concerned that by adding to or altering the code I may damage the board or one of the components should the file actually compile and build. Thanks so much for any assistance. Below is the .c file and link to the development kit user guide.
//---------------------------------------------------------------------------------- // FILE: SolarMicroInv_F2803x-Main.C // // Description: Solar MicroInverter Project // // Version: 1.0 // // Target: TMS320F2803x(PiccoloB), // //---------------------------------------------------------------------------------- // Copyright Texas Instruments © 2004-2013 //---------------------------------------------------------------------------------- // Revision History: //---------------------------------------------------------------------------------- // Date | Description / Status //---------------------------------------------------------------------------------- // June 26 2013 : (Manish Bhardwaj, Shamim Choudhury) //---------------------------------------------------------------------------------- // // PLEASE READ - Useful notes about this Project // Although this project is made up of several files, the most important ones are: // "{ProjectName}-Main.C" - this file // - Application Initialization, Peripheral config, // - Application management // - Slower background code loops and Task scheduling // "{ProjectName}-DevInit_F28xxx.C // - Device Initialization, e.g. Clock, PLL, WD, GPIO mapping // - Peripheral clock enables // - DevInit file will differ per each F28xxx device series, e.g. F280x, F2833x, // "{ProjectName}-Settings.h" // - Global defines (settings) project selections are found here // - This file is referenced by both C and ASM files. // "{ProjectName}-Includes.h" // - Include file used by project are defined in this file // // Code is made up of sections, e.g. "FUNCTION PROTOTYPES", "VARIABLE DECLARATIONS" ,..etc // each section has FRAMEWORK and USER areas. // FRAMEWORK areas provide useful ready made "infrastructure" code which for the most part // does not need modification, e.g. Task scheduling, ISR call, GUI interface support,...etc // USER areas have functional example code which can be modified by USER to fit their appl. // // Code can be compiled with various build options (Incremental Builds IBx), these // options are selected in file "{ProjectName}-Settings.h". Note: "Rebuild All" compile // tool bar button must be used if this file is modified. //---------------------------------------------------------------------------------- #include "SolarMicroInv-Includes.h" //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // FUNCTION PROTOTYPES //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Add prototypes of functions being used in the project here void DeviceInit(void); #ifdef FLASH void InitFlash(); #endif void MemCopy(); #ifdef FLASH #pragma CODE_SECTION(Inv_ISR,"ramfuncs"); #pragma CODE_SECTION(OneKhzISR,"ramfuncs"); #endif //This is the control loop ISR run at 50Khz interrupt void Inv_ISR(void); //This is 1 Khz ISR slaved off CPU timer 2, interrupt void OneKhzISR(); void InitECapture(); void ADC_SOC_CNF(int ChSel[], int Trigsel[], int ACQPS[], int IntChSel, int mode); void PWM_1ch_UpDwnCnt_CNF(int16 n, Uint16 period, int16 mode, int16 phase); void PWM_MicroInvLineClamp_CNF(int n,int period,int deadband_rising,int deadband_falling); // -------------------------------- FRAMEWORK -------------------------------------- // State Machine function prototypes //---------------------------------------------------------------------------------- // Alpha states void A0(void); //state A0 void B0(void); //state B0 // A branch states void A1(void); //state A1 void A2(void); //state A2 void A3(void); //state A3 void A4(void); //state A4 // B branch states void B1(void); //state B1 void B2(void); //state B2 void B3(void); //state B3 // Variable declarations void (*Alpha_State_Ptr)(void); // Base States pointer void (*A_Task_Ptr)(void); // State pointer A branch void (*B_Task_Ptr)(void); // State pointer B branch //---------------------------------------------------------------------------------- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // VARIABLE DECLARATIONS - GENERAL //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // -------------------------------- FRAMEWORK -------------------------------------- int16 VTimer0[4]; // Virtual Timers slaved off CPU Timer 0 int16 VTimer1[4]; // Virtual Timers slaved off CPU Timer 1 // Used for running BackGround in flash, and ISR in RAM extern Uint32 *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart; extern Uint32 *IQfuncsLoadStart, *IQfuncsLoadEnd, *IQfuncsRunStart; // Used for ADC Configuration int ChSel[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int TrigSel[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int ACQPS[16] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; //--------------------------------------------------------------------------- // Used to indirectly access all EPWM modules volatile struct EPWM_REGS *ePWM[] = { &EPwm1Regs, //intentional: (ePWM[0] not used) &EPwm1Regs, &EPwm2Regs, &EPwm3Regs, &EPwm4Regs, &EPwm5Regs, &EPwm6Regs, &EPwm7Regs, }; // Used to indirectly access all Comparator modules volatile struct COMP_REGS *Comp[] = { &Comp1Regs,//intentional: (Comp[0] not used) &Comp1Regs, &Comp2Regs, &Comp3Regs }; // ---------------------------------- USER ----------------------------------------- //-----------------------------Inverter & DC-DC Control Loop Variables ------------- // String to describe the state of the PV Inverter char cPV_State[40]; // Solar Library Objects // RAMP to generate forced angle when grid is not present RAMPGEN_IQ rgen1; // CNTL 3p3z for inverter current control #pragma DATA_SECTION(cntl3p3z_InvI_vars,"cntl_var_RAM") #pragma DATA_SECTION(cntl3p3z_InvI_coeff,"cntl_coeff_RAM") CNTL_3P3Z_IQ_VARS cntl3p3z_InvI_vars; CNTL_3P3Z_IQ_COEFFS cntl3p3z_InvI_coeff; // CNTL 2p2z for flyback current control #pragma DATA_SECTION(cntl2p2z_DCDCI_vars,"cntl_var_RAM") #pragma DATA_SECTION(cntl2p2z_DCDCI_coeff,"cntl_coeff_RAM") CNTL_2P2Z_IQ_VARS cntl2p2z_DCDCI_vars; CNTL_2P2Z_IQ_COEFFS cntl2p2z_DCDCI_coeff; // CNTL PI for bus control CNTL_PI_IQ cntlPI_BusInv; int16 UpdateCoef; long Pgain_BusInv, Dgain_BusInv, Igain_BusInv, Dmax_BusInv; // SPLL Objects of two types for grid angle lock SPLL_1ph_IQ spll1; SPLL_1ph_SOGI_IQ spll2; float c2, c1; long Phase_Jump, Phase_Jump_Trig; // Sine analyzer block for RMS Volt, Curr and Power measurements SINEANALYZER_DIFF_wPWR_IQ sine_mains; // notch filter objects for filtering bus voltage, pv current and voltage sense signals #pragma DATA_SECTION(Bus_Volt_notch,"cntl_var_RAM") #pragma DATA_SECTION(PV_volt_notch,"cntl_var_RAM") #pragma DATA_SECTION(PV_cur_notch,"cntl_var_RAM") #pragma DATA_SECTION( notch_TwiceGridFreq,"cntl_coeff_RAM") NOTCH_COEFF_IQ notch_TwiceGridFreq; NOTCH_VARS_IQ Bus_Volt_notch,PV_volt_notch,PV_cur_notch; // MPPT object for flyback current reference selection MPPT_INCC_I_IQ mppt_incc_I1; int16 MPPT_slew; int16 Run_MPPT; int16 MPPT_ENABLE; // Datalogger to plot variables #if INCR_BUILD==1 || INCR_BUILD==2 DLOG_4CH_IQ dlog1; int16 DBUFF1[100], DBUFF2[100], DBUFF3[100], DBUFF4[100]; int16 D_val1, D_val2, D_val3, D_val4; #endif //TODO // Inverter and Flyback Variables _iq24 inv_meas_cur_inst, inv_meas_vol_inst, vbus_meas_inst, vbus_meas_avg ; // reference variable Inverter _iq24 InvModIndex, inv_Iset, inv_ref_cur_inst, inv_bus_ref; // Measure Values DC-DC Stage long pv_meas_cur_inst,pv_meas_vol_inst,pv_meas_cur_avg, pv_meas_vol_avg; // Reference Values DC-DC Stage long pv_ref_cur_inst, pv_ref_cur_mppt, pv_ref_cur_fixed; // Measurement Offsets _iq24 offset_165, offset_GridCurrent, PV_SenseVolt_Offset, PV_SenseCurr_Offset,DC_Bus_Offset; //Offset filter coefficient K1: 0.05/(T+0.05); _iq K1 = _IQ(0.998); //Offset filter coefficient K2: T/(T+0.05) _iq K2 = _IQ(0.001999); int16 OffsetCalCounter; // Duty variables for flyback and inverter (per unit and compare register values) _iq24 duty_flyback_pu, duty_inv_pu; long duty_inv, duty_flyback; // Duty for which the inverter is not switched around zero int16 DontSwitchZeroLimit; // Flags for clearing trips and closing the loops and the Relay int16 CloseIloopInv, ClearInvTrip,CloseFlybackLoop, ClearFlyBackTrip, RlyConnect; // Flags for detecting ZCD _iq24 InvSine, InvSine_prev; int16 ZCDDetect; // State Machine Variable enum PVInverterStates { Idle = 0, CheckGrid = 1, CheckPV = 2, MonitorDCBus = 3, EnableMPPT = 4, PVInverterActive = 5, ResetState1 = 6, ResetState2 = 7, FaultState=8 }; enum PVInverterStates PVInverterState = Idle; enum PVInverterStates PVInverterState_Old= Idle; int16 SlewState4; int32 SlewClrInvTrip; // Value that is emperically tested to make sure the relay connect happens at ZCD // This accounts for any delay in the relay connection from the time the GPIO is triggered high long RlyConnectVal; // DC Bus voltage values where the state machine is triggered to connect relay, // start the invetrter and flag faults volatile long inv_bus_rly_connect, inv_bus_start_volt, inv_bus_UV, inv_bus_OV; //detecting faults enum Faults { NoFault = 0, OverVoltageDCBus = 1, UnderVoltageDCBus = 2, OverVoltageGrid = 3, UnderVoltageGrid = 4, OverCurrentFlag = 5 }; enum Faults FaultFlag = NoFault; int16 BusOverVoltageTrip, BusUnderVoltageTrip,OverCurrent; Uint16 Gui_InvStart; Uint16 Gui_InvStop; // Measuring AC signal long ACFreq_SysTicks; volatile float AC_Freq; volatile _iq24 ACFreq; _iq24 ACFreq2; volatile int UF_Flag, OF_Flag, UV_Flag, OV_Flag; volatile long GRID_MAX_VRMS, GRID_MIN_VRMS; volatile long GRID_MIN_FREQ, GRID_MAX_FREQ; int Grid_Freq = GRID_FREQ; long ECAP_TimerMaxVal; volatile long inv_emavg_vol; // Stand Alone Flash Image Instrumentation // GPIO toggles for different states int16 LedBlinkCnt1, LedBlinkCnt2; int16 timer1; // Display Values // Monitor ("Get") // Display as: int32 Gui_Vbus; //Q20 int32 Gui_Vpv; //Q20 int32 Gui_Ipv; //Q20 int32 Gui_GridFreq; //Q20 int32 Gui_Prms; //Q6 int32 Gui_Irms; //Q12 long Gui_Vrms; //Q6 int32 Gui_Vavg; int Gui_MPPTEnable; long IRMS, VRMS, PRMS; long K_Irms, K_Vrms, K_Prms, K_Vpv, K_Ipv; // The following declarations are required in order to use the SFO // library functions: int MEP_ScaleFactor; // Global variable used by the SFO library // Result can be used for all HRPWM channels // This variable is also copied to HRMSTEP // register by SFO() function. int status; //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // MAIN CODE - starts here //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void main(void) { //================================================================================= // INITIALISATION - General //================================================================================= // The DeviceInit() configures the clocks and pin mux registers // The function is declared in {ProjectName}-DevInit_F2803/2x.c, // Please ensure/edit that all the desired components pin muxes // are configured properly that clocks for the peripherals used // are enabled, for example the individual PWM clock must be enabled // along with the Time Base Clock DeviceInit(); // Device Life support & GPIO //-------------------------------- FRAMEWORK -------------------------------------- // Only used if running from FLASH // Note that the variable FLASH is defined by the compiler with -d FLASH #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); MemCopy(&IQfuncsLoadStart, &IQfuncsLoadEnd, &IQfuncsRunStart); // Call Flash Initialization to setup flash waitstates // This function must reside in RAM InitFlash(); // Call the flash wrapper init function #endif //(FLASH) // Timing sync for background loops // Timer period definitions found in PeripheralHeaderIncludes.h CpuTimer0Regs.PRD.all = mSec5; // A tasks CpuTimer1Regs.PRD.all = mSec50; // B tasks // Configure CPU-Timer 2 to interrupt every second: // 60MHz CPU Freq, Period (in uSeconds) // Configure CPU Timer interrupt for 1KHz interrupt ConfigCpuTimer(&CpuTimer2, 60, 1000); CpuTimer2Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0 // Tasks State-machine init Alpha_State_Ptr = &A0; A_Task_Ptr = &A1; B_Task_Ptr = &B1; VTimer0[0] = 0; VTimer1[0] = 0; LedBlinkCnt1 = 5; LedBlinkCnt2 = 5; //================================================================================== // INCREMENTAL BUILD OPTIONS - NOTE: selected via {ProjectName-Settings.h //================================================================================== // ---------------------------------- USER ----------------------------------------- //TODO PWM Configuration /************* PWM Configuration **************************/ SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable clocks for EPWM // 50Khz at 60Mhz device = > 60*1000/50 =1200, PWM_MicroInvLineClamp_CNF(1, (CPU_FREQ/(INV_FREQ)), INV_DEADBAND, INV_DEADBAND); // Put DC-DC PWM configuration here PWM_1ch_UpDwnCnt_CNF(3, (CPU_FREQ / (FLYBACK_FREQ)), 0, (CPU_FREQ / (FLYBACK_FREQ * 2)) - 2); // PWM 4 configured only to verify the blanking pulse for over current trips // PWM_1ch_UpDwnCnt_CNF(4, (CPU_FREQ / (FLYBACK_FREQ)), 0, // (CPU_FREQ / (FLYBACK_FREQ * 2)) - 2); // // EPwm4Regs.TBPHS.half.TBPHS=EPwm4Regs.TBPHS.half.TBPHS-2; // // EPwm4Regs.AQCTLA.bit.CAD=AQ_SET; // EPwm4Regs.AQCTLA.bit.CBU=AQ_CLEAR; // EPwm4Regs.AQCTLA.bit.CAU=AQ_NO_ACTION; // // EPwm4Regs.CMPA.half.CMPA=0; // EPwm4Regs.CMPB=0; // Add the dead band configuration for PWM3 EALLOW; EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; /* Rising Delay on 1A & Falling Delay on 1B*/ EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; /* Active high complementary mode (EPWMxA is inverted)*/ EPwm3Regs.DBCTL.bit.IN_MODE = DBA_ALL; /* 1A for Rising& Falling*/ EPwm3Regs.DBRED = FLYBACK_DEADBAND_RED; /* Delay at Rising edge*/ EPwm3Regs.DBFED = FLYBACK_DEADBAND_FED; /* Delay at Falling edge*/ EDIS; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable TBCLK // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor. // MEP_ScaleFactor/HRMSTEP must be filled with calibrated value in order // for the module to work status = SFO_INCOMPLETE; while (status == SFO_INCOMPLETE) { // Call until complete status = SFO(); } if (status != SFO_ERROR) { // IF SFO() is complete with no errors EALLOW; EPwm1Regs.HRMSTEP = MEP_ScaleFactor; EDIS; } if (status == SFO_ERROR) { while (1) ; // SFO function returns 2 if an error occurs // The code would loop here for infinity if it // returns an error } /************ PWM Configuration END **********************/ /****************** ADC Configuration *******************/ //TODO ADC Configuration #define IPV_FB AdcResult.ADCRESULT1 #define VPV_FB AdcResult.ADCRESULT2 #define VBUS_FB AdcResult.ADCRESULT3 #define IINV_FB AdcResult.ADCRESULT5 #define VAC_FB AdcResult.ADCRESULT6 #define VREF165_FB AdcResult.ADCRESULT7 #define V0_5_REF AdcResult.ADCRESULT8 //Map channel to ADC Pin // the dummy reads are to account for first sample issue in Rev 0 silicon // Please refer to the Errata and the datasheet, this would be fixed in later versions of the silicon // EPWM 3 SOC Signals ChSel[0] = 6; // Dummy read for first ChSel[1] = 6; // A6 - IPV, A2 - IP1 Sen - CT ChSel[2] = 11; // B3 - VPV //ChSel[3] = 14; // B6 - VBOOST in Rev 1 PCB ChSel[3] = 4; // A4 - VBOOST in Rev 2 PCB // EPWM 1 SOC Signals ChSel[4] = 1; // A1 - IGRID ChSel[5] = 1; // A1 - IGRID ChSel[6] = 9; // B1 - VGRID ChSel[7] = 7; // A7 - Ref_1.65V ChSel[8] = 5; // A5 - Ref_0.5V ChSel[9] = 8; // B0 - LEM Current Reference Output //ChSel[10] = 0; // A0 - PLC // Select Trigger Event TrigSel[0] = ADCTRIG_EPWM3_SOCA; TrigSel[1] = ADCTRIG_EPWM3_SOCA; TrigSel[2] = ADCTRIG_EPWM3_SOCA; TrigSel[3] = ADCTRIG_EPWM2_SOCA; TrigSel[4] = ADCTRIG_EPWM2_SOCA; TrigSel[5] = ADCTRIG_EPWM2_SOCA; TrigSel[6] = ADCTRIG_EPWM2_SOCA; TrigSel[7] = ADCTRIG_EPWM2_SOCA; TrigSel[8] = ADCTRIG_EPWM2_SOCA; //TrigSel[9]= ADCTRIG_EPWM2_SOCA; //TrigSel[10]= ADCTRIG_EPWM2_SOCA; // use auto clr ADC int flag mode=2 // end of conversion of inverter current triggers ADC INT 1 ADC_SOC_CNF(ChSel, TrigSel, ACQPS, 5, 2); // Configure the PWM to issue appropriate Start of Conversion for the ADC // DC-DC Flyback EPwm3Regs.ETSEL.bit.SOCAEN = 1; /* Enable SOC on A group*/ EPwm3Regs.ETSEL.bit.SOCASEL = ET_CTRD_CMPB; /* Select SOC from counter at ctr = 0*/ EPwm3Regs.ETPS.bit.SOCAPRD = ET_1ST; /* Generate pulse on 1st even*/ EPwm3Regs.ETSEL.bit.SOCAEN = 1; /* Enable SOC on A group*/ EPwm3Regs.CMPB = 12; // DC-AC Inverter // Note: SOCA is configured by the PWM CNF macro // but we ovewirte it to make the adc sampling centered EPwm2Regs.ETSEL.bit.SOCAEN = 1; EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTRD_CMPB; EPwm2Regs.ETPS.bit.SOCAPRD = ET_1ST; EPwm2Regs.ETSEL.bit.SOCAEN = 1; EPwm2Regs.CMPB = 70; // EPWM 2 is phase shifter by 50 i.e. when EPWM1 Ctr is zero then EPWM2 Ctr is 52 // The we take 8 cycles to sample + 6 cycles to covert the first dummy // and add half the ADC sample width =? 52+8+6+4 /************ ADC Configuration END **********************/ /************ ECAP Init **********************************/ InitECapture(); /************ ECAP Init END ******************************/ /************ Control Variable Initialization ************/ //TODO Solar Library Module Initialization // Initialize the net variables //RAMPGEN RAMPGEN_IQ_init(&rgen1); rgen1.Freq = _IQ24(GRID_FREQ); rgen1.StepAngleMax = _IQ24(1.0/INV_FREQ); //CNTL3P3Z Inverter Current Loop CNTL_3P3Z_IQ_VARS_init(&cntl3p3z_InvI_vars); CNTL_3P3Z_IQ_COEFFS_init(&cntl3p3z_InvI_coeff); cntl3p3z_InvI_coeff.Coeff_A1 = _IQ24(1.584); cntl3p3z_InvI_coeff.Coeff_A2 = _IQ24(-0.6978); cntl3p3z_InvI_coeff.Coeff_A3 = _IQ24(0.1137); cntl3p3z_InvI_coeff.Coeff_B0 = _IQ24(0.2866); cntl3p3z_InvI_coeff.Coeff_B1 = _IQ24(-0.3173); cntl3p3z_InvI_coeff.Coeff_B2 = _IQ24(0.3338); cntl3p3z_InvI_coeff.Coeff_B3 = _IQ24(-0.2616); cntl3p3z_InvI_coeff.Max = _IQ24(0.95); cntl3p3z_InvI_coeff.Min = _IQ24(-0.95); //CNTL2P2Z Flyback DCDC Current Loop CNTL_2P2Z_IQ_VARS_init(&cntl2p2z_DCDCI_vars); CNTL_2P2Z_IQ_COEFFS_init(&cntl2p2z_DCDCI_coeff); cntl2p2z_DCDCI_coeff.Coeff_A1 = _IQ24(1.0); // A1 = 1 cntl2p2z_DCDCI_coeff.Coeff_A2 = 0.0; // A2 = 0 cntl2p2z_DCDCI_coeff.Coeff_B0 = _IQ24(0.0917); // B0 cntl2p2z_DCDCI_coeff.Coeff_B1 = _IQ24(-0.07138); // B1 cntl2p2z_DCDCI_coeff.Coeff_B2 = _IQ24(0.0); // B2 cntl2p2z_DCDCI_coeff.Max = _IQ24(0.8); cntl2p2z_DCDCI_coeff.Min = _IQ24(0.0); cntl2p2z_DCDCI_coeff.IMin = _IQ24(-0.05); //CNTL PI Inverter Bus Voltage Regulation Loop Dmax_BusInv = _IQ24(0.80); Pgain_BusInv = _IQ24(1.0); Igain_BusInv = _IQ24(0.001); CNTL_PI_IQ_init(&cntlPI_BusInv); cntlPI_BusInv.Kp = Pgain_BusInv; cntlPI_BusInv.Ki = Igain_BusInv; cntlPI_BusInv.Umax = Dmax_BusInv; cntlPI_BusInv.Umin = _IQ(0.025); // MPPT MPPT_INCC_I_IQ_init(&mppt_incc_I1); mppt_incc_I1.IpvH = _IQ24(0.000); mppt_incc_I1.IpvL = _IQ24(0.000); mppt_incc_I1.VpvH = _IQ24(0.000); mppt_incc_I1.VpvL = _IQ24(0.000); mppt_incc_I1.MaxI = _IQ24(0.5); mppt_incc_I1.MinI = _IQ24(0.0); mppt_incc_I1.Stepsize = _IQ24(0.005); mppt_incc_I1.mppt_first = 1; mppt_incc_I1.mppt_enable = 1; mppt_incc_I1.StepFirst = _IQ24(0.01); // SPLL 1ph Notch Filter Method intialization SPLL_1ph_IQ_init(GRID_FREQ, _IQ21((float)(1.0/ISR_FREQUENCY)), &spll1); spll1.lpf_coeff.B0_lf = _IQ21(B0_LPF); spll1.lpf_coeff.B1_lf = _IQ21(B1_LPF); spll1.lpf_coeff.A1_lf = _IQ21(A1_LPF); c1 = 0.1; c2 = 0.00001; SPLL_1ph_IQ_notch_coeff_update(((float) (1.0 / ISR_FREQUENCY)), (float) (2 * PI * GRID_FREQ * 2), (float) c2, (float) c1, &spll1); //SPLL 1ph SOGI Method initialization SPLL_1ph_SOGI_IQ_init(GRID_FREQ, _IQ23((float)(1.0/ISR_FREQUENCY)), &spll2); spll2.lpf_coeff.B0_lf = _IQ23(B0_LPF); spll2.lpf_coeff.B1_lf = _IQ23(B1_LPF); spll2.lpf_coeff.A1_lf = _IQ23(A1_LPF); SPLL_1ph_SOGI_IQ_coeff_update(((float) (1.0 / ISR_FREQUENCY)), (float) (2 * PI * GRID_FREQ), &spll2); // NOTCH COEFF update for measurement filtering NOTCH_FLTR_IQ_VARS_init(&Bus_Volt_notch); NOTCH_FLTR_IQ_VARS_init(&PV_volt_notch); NOTCH_FLTR_IQ_VARS_init(&PV_cur_notch); NOTCH_FLTR_IQ_COEFF_Update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*GRID_FREQ*2),(float)c2,(float)c1, ¬ch_TwiceGridFreq); //sine analyzer initialization SINEANALYZER_DIFF_wPWR_IQ_init(&sine_mains); sine_mains.Vin = 0; sine_mains.Iin = 0; sine_mains.SampleFreq = _IQ15(1000.0); sine_mains.Threshold = _IQ15(0.1); sine_mains.nsamplesMax=1000/UNIVERSAL_GRID_MIN_FREQ; sine_mains.nsamplesMin=1000/UNIVERSAL_GRID_MAX_FREQ; // Initialize DATALOG module #if INCR_BUILD==1 || INCR_BUILD==2 dlog1.input_ptr1 = &D_val1; dlog1.input_ptr2 = &D_val2; dlog1.input_ptr3 = &D_val3; // spll.Out logged in buff3 dlog1.input_ptr4 = &D_val4; // ramp_sin logged in buff4 dlog1.output_ptr1 = DBUFF1; dlog1.output_ptr2 = DBUFF2; dlog1.output_ptr3 = DBUFF3; dlog1.output_ptr4 = DBUFF4; dlog1.prev_value = 0; dlog1.trig_value = _IQ15(0.1); dlog1.status = 0; dlog1.pre_scalar = 10; dlog1.skip_count = 0; dlog1.size = 100; dlog1.count = 0; #endif //Variable initialization // inverter measurement inv_meas_cur_inst=0; inv_meas_vol_inst=0; vbus_meas_inst=0; vbus_meas_avg=0; // reference variable Inverter InvModIndex=0; inv_Iset=0; inv_ref_cur_inst=0; inv_bus_ref = DC_BUS_REF_60HZ; // Measure Values DC-DC Stage pv_meas_cur_inst=0; pv_meas_vol_inst=0; pv_meas_cur_avg=0; pv_meas_vol_avg=0; // Reference Values DC-DC Stage pv_ref_cur_inst=0; pv_ref_cur_mppt=0; pv_ref_cur_fixed = _IQ24(0.15); // Measurement Offsets offset_GridCurrent = OFFSET_GRIDCURRENT_MEAS; PV_SenseVolt_Offset = OFFSET_PV_SENSEVOLT_MEAS; PV_SenseCurr_Offset = OFFSET_PV_SENSECURR_MEAS; DC_Bus_Offset=OFFSET_DC_BUS_MEAS; offset_165=0; // Duty variables for flyback and inverter (per unit and compare register values) duty_flyback_pu=0; duty_inv_pu=0;; duty_inv=0; duty_flyback=0; // Duty for which the inverter is not switched around zero DontSwitchZeroLimit = 15; // Flags for clearing trips and closing the loops and the Relay CloseIloopInv=0; ClearInvTrip=0; CloseFlybackLoop=0; ClearFlyBackTrip=0; RlyConnect=0; // Flags for detecting ZCD InvSine=0; InvSine_prev=0; ZCDDetect=0; PVInverterState = Idle; PVInverterState_Old= Idle; SlewState4=0; SlewClrInvTrip=0; // Value that is emperically tested to make sure the relay connect happens at ZCD // This accounts for any delay in the relay connection from the time the GPIO is triggered high RlyConnectVal = _IQ24(0.55); // DC Bus voltage values where the state machine is triggered to connect relay, // start the invetrter and flag faults inv_bus_rly_connect = DC_BUS_RELAY_CONNECT_VOLT_60HZ; inv_bus_start_volt = DC_BUS_INV_START_VOLT_60HZ; inv_bus_UV = DC_BUS_UNDERVOLTAGE_LIMIT_60HZ; inv_bus_OV = DC_BUS_OVERVOLTAGE_LIMIT_60HZ; FaultFlag = NoFault; BusOverVoltageTrip = 0; BusUnderVoltageTrip = 0; OverCurrent=0; Gui_InvStart=0; Gui_InvStop=0; // Measuring AC signal ACFreq_SysTicks=0; AC_Freq=0; ACFreq=0; ACFreq2=0; UF_Flag=0; OF_Flag=0; UV_Flag=0; OV_Flag=0; GRID_MIN_FREQ = UNIVERSAL_GRID_MIN_FREQ; GRID_MAX_FREQ = UNIVERSAL_GRID_MAX_FREQ; GRID_MIN_VRMS = UNIVERSAL_GRID_MIN_VRMS; GRID_MAX_VRMS = UNIVERSAL_GRID_MAX_VRMS; Grid_Freq = GRID_FREQ; ECAP_TimerMaxVal = (CPU_FREQ / CAP_MIN_FREQ_MEAS) >> 1; // Where 40 is the lowest frequency measured by ECAP module inv_emavg_vol=0; // Gui Variables Gui_Vbus=0; Gui_Vpv=0; Gui_Ipv=0; Gui_GridFreq=0; //Q20 Gui_Prms=0; //Q6 Gui_Irms=0; //Q12 Gui_Vrms=0; //Q6 Gui_MPPTEnable=1; Gui_Vavg=0; K_Vrms = 26803; //K_Vrms=(418/511)*32767 = 26803, //RMS voltage is viewed as a Q6 number K_Irms = 28671; //K_Irms=(7/8)*32767 = 28671, //Current is viewed as a Q12 number K_Prms = 187624;//K_Prms=(7*418/511)*32767 = 187624, //Power is viewed as a Q6 number K_Vpv = 17732; //K_Vpv=(138/255)*32767= 17732, // Panel Voltage is viewed as Q8 K_Ipv = 30719;//K_Ipv=(15/16)*32767=30719 // Panel Current is viewed in Q11 number UpdateCoef = 0; MPPT_ENABLE = 0; Run_MPPT = 0; MPPT_slew = 0; strcpy(cPV_State,"Idle"); /************ Control Variable Initialization END *********/ /********* Protection Mechanisms *****************/ //TODO Protection Code EALLOW; // Cycle by cycle interrupt for CPU halt trip EPwm1Regs.TZSEL.bit.CBC6 = 0x1; EPwm2Regs.TZSEL.bit.CBC6 = 0x1; EPwm3Regs.TZSEL.bit.CBC6 = 0x1; // Adding one shot trip for over-current protection on the inverter TZ2 EPwm1Regs.TZSEL.bit.OSHT2 = 0x1; EPwm2Regs.TZSEL.bit.OSHT2 = 0x1; // Adding one shot trip for over current of the flyback stage but avoid the <1% duty condition using blanking // First enable the COMP3 Comp3Regs.COMPCTL.bit.COMPDACEN =0x1; Comp3Regs.COMPCTL.bit.SYNCSEL =0x0; // asynchronous version of the COMP signal is passed to the EPWM/GPIO module Comp3Regs.COMPCTL.bit.CMPINV =0x0; // Output of the comparator is passed directly Comp3Regs.COMPCTL.bit.COMPSOURCE =0x0; // inverting input of the comparator is connected to the internal DAC Comp3Regs.DACVAL.bit.DACVAL =700; // set DAC input to peak trip point ~10 Amps, full scale is 15Amps AdcRegs.COMPHYSTCTL.bit.COMP1_HYST_DISABLE = 0x1; //Select COMP3 as one shot trip EPwm3Regs.DCTRIPSEL.bit.DCAHCOMPSEL=DC_COMP3OUT ; EPwm3Regs.TZDCSEL.bit.DCAEVT1=TZ_DCAH_HI; EPwm3Regs.DCACTL.bit.EVT1SRCSEL = DC_EVT_FLT ; EPwm3Regs.DCACTL.bit.EVT1FRCSYNCSEL=DC_EVT_ASYNC; EPwm3Regs.TZSEL.bit.DCAEVT1=0x1; //Add blanking to avoid conditions where the over current trip generates <1% duty cycle EPwm3Regs.DCFCTL.bit.BLANKE=DC_BLANK_ENABLE; // Blanking window is enabled EPwm3Regs.DCFCTL.bit.BLANKINV=DC_BLANK_NOTINV; // Blanking window is not inverted EPwm3Regs.DCFCTL.bit.SRCSEL=DC_SRC_DCAEVT1; //DCAEVT1 EPwm3Regs.DCFCTL.bit.PULSESEL=DC_PULSESEL_PRD; // apply offset from TBCTR=TBPRD EPwm3Regs.DCFOFFSET=59; EPwm3Regs.DCFWINDOW=255; // What do we want the OST/CBC events to do? // TZA events can force EPWMxA // TZB events can force EPWMxB EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low EPwm3Regs.TZCTL.bit.TZA = TZ_FORCE_LO; // EPWMxA will go low EPwm3Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWMxB will go low //clear any spurious trips EPwm1Regs.TZCLR.bit.OST = 1; EPwm2Regs.TZCLR.bit.OST = 1; EPwm3Regs.TZCLR.bit.OST = 1; // Force a trip event on all the PWM modules for safety EPwm1Regs.TZFRC.bit.OST = 0x1; EPwm2Regs.TZFRC.bit.OST = 0x1; EPwm3Regs.TZFRC.bit.OST = 0x1; EDIS; /********* Protection Mechanism END *****************/ /********* Run Calibration for offset in grid and panel current ******/ //TODO Run Calibration Task OffsetCalCounter=0; offset_GridCurrent=0; PV_SenseCurr_Offset=0; while(OffsetCalCounter<5000) { if(AdcRegs.ADCINTFLG.bit.ADCINT1==1) { PV_SenseCurr_Offset= _IQmpy(K1,PV_SenseCurr_Offset)+_IQmpy(K2,_IQ12toIQ(IPV_FB)); offset_GridCurrent=_IQmpy(K1,offset_GridCurrent)+_IQmpy(K2,_IQ12toIQ(IINV_FB)); OffsetCalCounter++; AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag } } /********* INTERRUPTS & ISR INITIALIZATION ***********/ // (best to run this section after other initialization) // Set up C28x Interrupt EALLOW; PieVectTable.ADCINT1 = &Inv_ISR; // Inverter Control Interrupt PieVectTable.TINT2 = &OneKhzISR; // 1kHz interrupt from CPU timer 2 PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable ADCINT1 in PIE group 1 //ADC interrupt already enabled by ADC SOC Cnf IER |= M_INT1; // Enable CPU INT1 for ADCINT1,ADCINT2,ADCINT9,TripZone IER |= M_INT14; // CPU timer 2 is connected to CPU INT 14 EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM EDIS; /************** BACKGROUND ********************/ //--------------------------------- FRAMEWORK ------------------------------------- for (;;) //infinite loop { // State machine entry & exit point //=========================================================== (*Alpha_State_Ptr)(); // jump to an Alpha state (A0,B0,...) //=========================================================== } } //END MAIN CODE //================================================================================= // STATE-MACHINE SEQUENCING AND SYNCRONIZATION //================================================================================= //--------------------------------- FRAMEWORK ------------------------------------- void A0(void) { // loop rate synchronizer for A-tasks if (CpuTimer0Regs.TCR.bit.TIF == 1) { CpuTimer0Regs.TCR.bit.TIF = 1; // clear flag //----------------------------------------------------------- (*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,...) //----------------------------------------------------------- VTimer0[0]++; // virtual timer 0, instance 0 (spare) } Alpha_State_Ptr = &B0; // Comment out to allow only A tasks } void B0(void) { // loop rate synchronizer for B-tasks if (CpuTimer1Regs.TCR.bit.TIF == 1) { CpuTimer1Regs.TCR.bit.TIF = 1; // clear flag //----------------------------------------------------------- (*B_Task_Ptr)(); // jump to a B Task (B1,B2,B3,...) //----------------------------------------------------------- VTimer1[0]++; // virtual timer 1, instance 0 (spare) } Alpha_State_Ptr = &A0; // Allow C state tasks } //================================================================================= // A - TASKS //================================================================================= //-------------------------------------------------------- void A1(void) //-------------------------------------------------------- { if(PVInverterState_Old!=PVInverterState) { switch(PVInverterState) { case Idle: strcpy(cPV_State,"Idle"); break; case CheckGrid: strcpy(cPV_State,"CheckGrid"); break; case CheckPV: strcpy(cPV_State,"CheckPV"); break; case MonitorDCBus: strcpy(cPV_State,"MonitorDCBus"); break; case EnableMPPT: strcpy(cPV_State,"EnableMPPT"); break; case PVInverterActive: strcpy(cPV_State,"PVInverterActive"); break; case ResetState1: strcpy(cPV_State,"ResetState1"); break; case ResetState2: strcpy(cPV_State,"ResetState2"); break; case FaultState:if(FaultFlag==OverVoltageDCBus) strcpy(cPV_State,"FaultState: DC Bus Over Voltage"); else if (FaultFlag==UnderVoltageDCBus) strcpy(cPV_State,"FaultState: DC Bus Under Voltage"); else if (FaultFlag==OverVoltageGrid) strcpy(cPV_State,"FaultState: Over Voltage Grid"); else if (FaultFlag==UnderVoltageGrid) strcpy(cPV_State,"FaultState: Under Voltage Grid"); else if (FaultFlag==OverCurrentFlag) strcpy(cPV_State,"FaultState: Grid Current Over"); else strcpy(cPV_State,"FaultState"); break; } } PVInverterState_Old=PVInverterState; if(PVInverterState==Idle) Gui_GridFreq=ACFreq<<16; else Gui_GridFreq=(long)(spll2.fo)>>3; //------------------- //the next time CpuTimer0 'counter' reaches Period value go to A2 A_Task_Ptr = &A2; //------------------- } //-------------------------------------------------------- void A2(void) // Connect Disconnect //----------------------------------------------------------------- { #if(INCR_BUILD==1)||(INCR_BUILD==2) if(RlyConnect==1) { GpioDataRegs.GPASET.bit.GPIO22=1; } else { GpioDataRegs.GPACLEAR.bit.GPIO22=1; } #endif //------------------- //the next time CpuTimer0 'counter' reaches Period value go to A1 A_Task_Ptr = &A3; //------------------- } //-------------------------------------------------------- void A3(void) //----------------------------------------- { //----------------- //the next time CpuTimer0 'counter' reaches Period value go to A1 A_Task_Ptr = &A4; //----------------- } //-------------------------------------------------------- void A4(void) // Spare //-------------------------------------------------------- { //----------------- //the next time CpuTimer0 'counter' reaches Period value go to A1 A_Task_Ptr = &A1; //----------------- } //================================================================================= // B - TASKS //================================================================================= //---------------------------------------- void B1(void) //---------------------------------------- { if (UpdateCoef == 1) { UpdateCoef = 0; //SPLL_1ph_IQ_notch_coeff_update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*GRID_FREQ*2),c2,c1, &spll1); } //----------------- //the next time CpuTimer1 'counter' reaches Period value go to B2 B_Task_Ptr = &B2; //----------------- } //---------------------------------------- void B2(void) // Blink LED on the control CArd //---------------------------------------- { // Toggle LD3 on control card to show execution of code if (LedBlinkCnt1 == 0) { GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1;//turn on/off LD3 on the controlCARD LedBlinkCnt1 = 4; } else LedBlinkCnt1--; //----------------- //the next time CpuTimer1 'counter' reaches Period value go to B3 B_Task_Ptr = &B3; //----------------- } //---------------------------------------- void B3(void) // State Machine, Enable Disable Loops, User Controls //---------------------------------------- { #if ((INCR_BUILD == 1)) if (ClearInvTrip==1) { EALLOW; EPwm1Regs.TZCLR.bit.OST=0x1; EPwm2Regs.TZCLR.bit.OST=0x1; EDIS; ClearInvTrip=0; } #endif #if ((INCR_BUILD==1)||(INCR_BUILD==2)) if (ClearFlyBackTrip==1) { EALLOW; EPwm3Regs.TZCLR.bit.OST=0x1; EDIS; ClearFlyBackTrip=0; } #endif //----------------- //the next time CpuTimer1 'counter' reaches Period value go to B4 B_Task_Ptr = &B1; //----------------- } // ISR for inverter interrupt void Inv_ISR() { /*************************************************/ /************ Inverter Code *********************/ /*************************************************/ //------------------------------------------------------------------- // Inverter Current and Voltage Measurements //------------------------------------------------------------------- // TODO Inverter ISR offset_165 = ((int32) VREF165_FB) << 12; vbus_meas_inst = (((long)VBUS_FB<<12)-DC_Bus_Offset); inv_meas_vol_inst = ((long) (((long) VAC_FB << 12) - offset_165)) << 1; inv_meas_cur_inst = (((int32) IINV_FB << 12) - offset_GridCurrent) << 1; //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 1 ) // Open Loop Check //----------------------------------------------------------------------------------------- // Run the ramp ctl to generate the forced sine angle for open loop test of the inverter RAMPGEN_IQ_MACRO(rgen1); if(Phase_Jump==1) { rgen1.Angle+=_IQ24(0.25); if(rgen1.Angle>_IQ24(1.0)) rgen1.Angle=rgen1.Angle-_IQ24(1.0); rgen1.Out=rgen1.Angle; Phase_Jump=0; if(Phase_Jump_Trig==0) Phase_Jump_Trig=_IQ24(1.0); else Phase_Jump_Trig=0; } // Use the angle value to compute the sine value InvSine = _IQsinPU(rgen1.Out); //NOTCH PLL /*spll1.AC_input=(long)InvSine>>3; // Q24 to Q21 SPLL_1ph_IQ_MACRO(spll1);*/ //SOGI PLL spll2.u[0]=(long)InvSine>>1; SPLL_1ph_SOGI_IQ_MACRO(spll2); // inverter duty value duty_inv_pu=_IQ24mpy(InvSine,InvModIndex); #endif // (INCR_BUILD == 1) //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 2) //Closed Current Loop Inverter with forced/internal sine angle //----------------------------------------------------------------------------------------- #if (GRID_CONNECT==1) // Run the SPLL and compute the inverter sine value spll2.u[0]=(long)inv_meas_vol_inst>>1;// shift from Q24 to Q23 SPLL_1ph_SOGI_IQ_MACRO(spll2); InvSine=spll2.sin<<1;// shift from Q23 to Q24 #else // Run the ramp ctl to generate the forced sine angle for open loop test of the inverter RAMPGEN_IQ_MACRO(rgen1); // Use the angle value to compute the sine value InvSine = _IQsinPU(rgen1.Out); #endif if((InvSine_prev<=_IQ24(0.00))&&(InvSine>_IQ24(0.00))) ZCDDetect=1; else ZCDDetect=0; if (ClearInvTrip==1 && ZCDDetect==1) { EALLOW; EPwm1Regs.TZCLR.bit.OST=0x1; EPwm2Regs.TZCLR.bit.OST=0x1; EDIS; ClearInvTrip=0; CloseIloopInv=1; } inv_ref_cur_inst = _IQ24mpy(inv_Iset, InvSine); if(CloseIloopInv==1) { cntl3p3z_InvI_vars.Ref=inv_ref_cur_inst; cntl3p3z_InvI_vars.Fdbk=inv_meas_cur_inst; CNTL_3P3Z_IQ_ASM(&cntl3p3z_InvI_coeff,&cntl3p3z_InvI_vars); duty_inv_pu=_IQ24div((cntl3p3z_InvI_vars.Out+inv_meas_vol_inst),vbus_meas_inst); duty_inv_pu= (duty_inv_pu>_IQ24(1.0))?_IQ24(1.0):duty_inv_pu; duty_inv_pu= (duty_inv_pu<_IQ24(-1.0))?_IQ24(-1.0):duty_inv_pu; } else { duty_inv_pu=0; } #endif //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 3 ) //Grid Connected Test //----------------------------------------------------------------------------------------- #if (GRID_CONNECT==1) // Run the SPLL and compute the inverter sine value spll2.u[0]=(long)inv_meas_vol_inst>>1;// shift from Q24 to Q23 SPLL_1ph_SOGI_IQ_MACRO(spll2); InvSine=spll2.sin<<1;// shift from Q23 to Q24 #else // Run the ramp ctl to generate the forced sine angle for open loop test of the inverter RAMPGEN_IQ_MACRO(rgen1); // Use the angle value to compute the sine value InvSine = _IQsinPU(rgen1.Out); #endif if((InvSine_prev<=_IQ24(0.00))&&(InvSine>_IQ24(0.00))) { ZCDDetect=1; if(MPPT_slew==0) { if(MPPT_ENABLE==1) { Run_MPPT=1; } MPPT_slew=10; } else MPPT_slew--; } else { ZCDDetect=0; } if((InvSine_prev<=RlyConnectVal)&&(InvSine>RlyConnectVal)) { if(RlyConnect==1) { RlyConnect=0; GpioDataRegs.GPASET.bit.GPIO22=1; } } InvSine_prev=InvSine; if ( ClearInvTrip==1 && ZCDDetect==1 ) { EALLOW; EPwm1Regs.TZCLR.bit.OST=0x1; EPwm2Regs.TZCLR.bit.OST=0x1; EDIS; ClearInvTrip=0; CloseIloopInv=1; } if(CloseIloopInv==1) { cntlPI_BusInv.Ref =Bus_Volt_notch.Out; cntlPI_BusInv.Fbk =inv_bus_ref; CNTL_PI_IQ_MACRO(cntlPI_BusInv) inv_Iset=cntlPI_BusInv.Out; inv_ref_cur_inst = _IQ24mpy(inv_Iset, InvSine); cntl3p3z_InvI_vars.Ref=inv_ref_cur_inst; cntl3p3z_InvI_vars.Fdbk=inv_meas_cur_inst; CNTL_3P3Z_IQ_ASM(&cntl3p3z_InvI_coeff,&cntl3p3z_InvI_vars); duty_inv_pu=_IQ24div((cntl3p3z_InvI_vars.Out+inv_meas_vol_inst),vbus_meas_inst); duty_inv_pu= (duty_inv_pu>_IQ24(1.0))?_IQ24(1.0):duty_inv_pu; duty_inv_pu= (duty_inv_pu<_IQ24(-1.0))?_IQ24(-1.0):duty_inv_pu; } #endif // (INCR_BUILD == 3) //-------------------------------------------------------------------------------- // PWM Driver for the inverter //-------------------------------------------------------------------------------- duty_inv = _IQ24mpy((long)(INV_PWM_PERIOD),_IQ24abs(duty_inv_pu)); if (duty_inv < DontSwitchZeroLimit) { if (duty_inv_pu > 0) { EPwm1Regs.CMPA.half.CMPA = 0; EPwm1Regs.CMPB = 0; EPwm2Regs.CMPA.half.CMPA = INV_PWM_PERIOD; } else { EPwm1Regs.CMPB = 0; EPwm1Regs.CMPA.half.CMPA = 0; EPwm2Regs.CMPA.half.CMPA = 0; } } else { if (duty_inv_pu > 0) { EPwm1Regs.CMPA.half.CMPA = duty_inv; EPwm1Regs.CMPB = 0; EPwm2Regs.CMPA.half.CMPA = EPwm2Regs.TBPRD; } else { EPwm1Regs.CMPA.half.CMPA = 0; EPwm1Regs.CMPB = duty_inv; EPwm2Regs.CMPA.half.CMPA = 0; } } /*************************************************/ /************ fly back Code **********************/ /*************************************************/ //TODO Fly Back ISR //------------------------------------------------------------------- // PV Current and Voltage //------------------------------------------------------------------- pv_meas_cur_inst = _IQsat((((long)IPV_FB<<12)- PV_SenseCurr_Offset),_IQ24(1.0),_IQ24(0.0)); //pv_meas_cur_inst=_IQsat((((long)IPV_FB<<12)- ((long)V0_5_REF<<12)),_IQ24(1.0),_IQ24(0.0)); // use this when using CT pv_meas_vol_inst = _IQsat((((long)VPV_FB<<12)-PV_SenseVolt_Offset),_IQ24(1.0),_IQ24(0.0)); pv_meas_cur_inst=(pv_meas_cur_inst>0)?pv_meas_cur_inst:0; //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 1 ) // Open Loop Check //----------------------------------------------------------------------------------------- // flyback duty value #endif // (INCR_BUILD == 1) //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 2) //Closed Current Loop Flyback //----------------------------------------------------------------------------------------- cntl2p2z_DCDCI_vars.Ref=pv_ref_cur_inst; cntl2p2z_DCDCI_vars.Fdbk=pv_meas_cur_inst; CNTL_2P2Z_IQ_ASM(&cntl2p2z_DCDCI_coeff,&cntl2p2z_DCDCI_vars); duty_flyback_pu=cntl2p2z_DCDCI_vars.Out; #endif // (INCR_BUILD == 2) //----------------------------------------------------------------------------------------- #if (INCR_BUILD == 3) //Closed Current Loop Fly back //----------------------------------------------------------------------------------------- if(CloseFlybackLoop==1) { cntl2p2z_DCDCI_vars.Ref=pv_ref_cur_inst; //cntl2p2z_DCDCV_vars.Out; cntl2p2z_DCDCI_vars.Fdbk=pv_meas_cur_inst; CNTL_2P2Z_IQ_ASM(&cntl2p2z_DCDCI_coeff,&cntl2p2z_DCDCI_vars); // fly back duty value duty_flyback_pu=cntl2p2z_DCDCI_vars.Out; } #endif // (INCR_BUILD == 2) //-------------------------------------------------------------------------------- // PWM Driver for fly back DC-DC //-------------------------------------------------------------------------------- duty_flyback =(_IQ22mpy((int32)(FLYBACK_PWM_PERIOD)<<22,(int32)duty_flyback_pu>>2))>> 6; if (duty_flyback > _IQ16(25)) EPwm3Regs.CMPA.all = duty_flyback; else EPwm3Regs.CMPA.all = 0; //-------------------------------------------------------------------------------- // Moving Average for MPPT and Notch Filters //-------------------------------------------------------------------------------- Bus_Volt_notch.In=vbus_meas_inst; NOTCH_FLTR_IQ_ASM(&Bus_Volt_notch,¬ch_TwiceGridFreq); PV_volt_notch.In=pv_meas_vol_inst; NOTCH_FLTR_IQ_ASM(&PV_volt_notch,¬ch_TwiceGridFreq); PV_cur_notch.In=pv_meas_cur_inst; NOTCH_FLTR_IQ_ASM(&PV_cur_notch,¬ch_TwiceGridFreq); MATH_EMAVG2_IQ_MACRO(Bus_Volt_notch.Out, vbus_meas_avg, _IQ(0.0005)); MATH_EMAVG2_IQ_MACRO(PV_cur_notch.Out, pv_meas_cur_avg, _IQ(0.0005)); pv_meas_cur_avg=(pv_meas_cur_avg>0)?pv_meas_cur_avg:0; MATH_EMAVG2_IQ_MACRO(PV_volt_notch.Out, pv_meas_vol_avg, _IQ(0.0005)); pv_meas_vol_avg=(pv_meas_vol_avg>0)?pv_meas_vol_avg:0; // ------------------------------------------------------------------------------ // Connect inputs of the Datalogger module // ------------------------------------------------------------------------------ #if INCR_BUILD==1 // First two DBUFF check SPLL operations D_val1 = (int16)_IQtoIQ15(InvSine); D_val2 = (int16)_IQtoIQ15(spll2.sin<<1); // Next two check Vac and Iac measurement D_val3 = (int16)_IQtoIQ15(inv_meas_cur_inst); D_val4 = (int16)_IQtoIQ15(inv_meas_vol_inst); DLOG_4CH_IQ_MACRO(dlog1); #endif #if INCR_BUILD==2 #if GRID_CONNECT==1 D_val1 = (int16)_IQtoIQ15(inv_meas_vol_inst); D_val2 = (int16)_IQtoIQ15(InvSine); #else D_val1 = (int16)_IQtoIQ15(InvSine); D_val2 = (int16)_IQtoIQ15(inv_meas_vol_inst); #endif D_val3 = (int16)_IQtoIQ15(inv_meas_cur_inst); D_val4 = (int16)_IQtoIQ15(inv_ref_cur_inst); DLOG_4CH_IQ_MACRO(dlog1); #endif //------------------------------------------------------------------- // Acknowledge interrupt //------------------------------------------------------------------- PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Must acknowledge the PIE group AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear ADCINT1 flag //------------------------------------------------------------------- return; } // One KHz ISR interrupt void OneKhzISR() { // Let the inv_ISR interrupt this routine EINT; //TODO State Machine #if (INCR_BUILD == 3) // Inverter State ==0 , Idle state, wait for the inverter start command // Inverter State ==1 , Check if grid is present // Inverter State ==2 , Check if sufficient panel voltage is available // Inverter State ==3 , Check if dc bus is enough to feed power into the grid // Inverter State ==4 , wait for stop command, Check if dc bus goes into under volatage condition // Inverter State ==5 , if stop, trip all PWM's, shut down MPPT and return to state 0, reset all values switch(PVInverterState) { case Idle: // Wait for the command to start the inverter if(Gui_InvStart==1) { PVInverterState=CheckGrid; Gui_InvStart=0; } break; case CheckGrid: // once the inverter command is issued check if the grid is present // once identified re -initailize the VRMS and FREQ limit for that grid range // also modify the PLL coefficients for the grid frequency #if(GRID_CONNECT==1) if(OV_Flag==0&&UV_Flag==0&&UF_Flag==0&&OF_Flag==0) { if(_IQ4abs((ACFreq-_IQ4(50.0)))<_IQ4(GRID_OVER_UNDER_FREQ_LIMIT)) { PVInverterState=CheckPV; Grid_Freq=50; GRID_MIN_FREQ=Grid_Freq-GRID_OVER_UNDER_FREQ_LIMIT; GRID_MAX_FREQ=Grid_Freq+GRID_OVER_UNDER_FREQ_LIMIT; GRID_MIN_VRMS=220-GRID_OVER_UNDER_VRMS_LIMIT; GRID_MAX_VRMS=220+GRID_OVER_UNDER_VRMS_LIMIT; // SPLL 1ph Notch Filter Method intialization SPLL_1ph_IQ_init(Grid_Freq,_IQ21((float)(1.0/ISR_FREQUENCY)),&spll1); spll1.lpf_coeff.B0_lf=B0_LPF; spll1.lpf_coeff.B1_lf=B1_LPF; spll1.lpf_coeff.A1_lf=A1_LPF; c1=0.1; c2=0.00001; SPLL_1ph_IQ_notch_coeff_update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*Grid_Freq*2),(float)c2,(float)c1, &spll1); NOTCH_FLTR_IQ_COEFF_Update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*Grid_Freq*2),(float)c2,(float)c1, ¬ch_TwiceGridFreq); //SPLL 1ph SOGI Method initialization SPLL_1ph_SOGI_IQ_init(Grid_Freq,_IQ23((float)(1.0/ISR_FREQUENCY)),&spll2); spll2.lpf_coeff.B0_lf=_IQ23(166.877556); spll2.lpf_coeff.B1_lf=_IQ23(-166.322444); spll2.lpf_coeff.A1_lf=_IQ23(-1.0); SPLL_1ph_SOGI_IQ_coeff_update(((float)(1.0/ISR_FREQUENCY)),(float)(2*PI*Grid_Freq),&spll2); inv_bus_ref=DC_BUS_REF_50HZ; inv_bus_rly_connect= DC_BUS_RELAY_CONNECT_VOLT_50HZ; inv_bus_start_volt=DC_BUS_INV_START_VOLT_50HZ; inv_bus_UV=DC_BUS_UNDERVOLTAGE_LIMIT_50HZ; inv_bus_OV=DC_BUS_OVERVOLTAGE_LIMIT_50HZ; cntlPI_BusInv.Umin =_IQ(0.015); SlewClrInvTrip=10; } else if(_IQ4abs((ACFreq-_IQ4(60.0)))<_IQ4(GRID_OVER_UNDER_FREQ_LIMIT)) { PVInverterState=CheckPV; Grid_Freq=60; GRID_MIN_FREQ=Grid_Freq-GRID_OVER_UNDER_FREQ_LIMIT; GRID_MAX_FREQ=Grid_Freq+GRID_OVER_UNDER_FREQ_LIMIT; GRID_MIN_VRMS=110-GRID_OVER_UNDER_VRMS_LIMIT; GRID_MAX_VRMS=110+GRID_OVER_UNDER_VRMS_LIMIT; // SPLL 1ph Notch Filter Method intialization SPLL_1ph_IQ_init(Grid_Freq,_IQ21((float)(1.0/ISR_FREQUENCY)),&spll1); spll1.lpf_coeff.B0_lf=B0_LPF; spll1.lpf_coeff.B1_lf=B1_LPF; spll1.lpf_coeff.A1_lf=A1_LPF; c1=0.1; c2=0.00001; SPLL_1ph_IQ_notch_coeff_update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*Grid_Freq*2),(float)c2,(float)c1, &spll1); NOTCH_FLTR_IQ_COEFF_Update(((float)(1.0/ISR_FREQUENCY)), (float)(2*PI*Grid_Freq*2),(float)c2,(float)c1, ¬ch_TwiceGridFreq); //SPLL 1ph SOGI Method initialization SPLL_1ph_SOGI_IQ_init(Grid_Freq,_IQ23((float)(1.0/ISR_FREQUENCY)),&spll2); spll2.lpf_coeff.B0_lf=_IQ23(166.877556); spll2.lpf_coeff.B1_lf=_IQ23(-166.322444); spll2.lpf_coeff.A1_lf=_IQ23(-1.0); SPLL_1ph_SOGI_IQ_coeff_update(((float)(1.0/ISR_FREQUENCY)),(float)(2*PI*Grid_Freq),&spll2); inv_bus_ref=DC_BUS_REF_60HZ; inv_bus_rly_connect= DC_BUS_RELAY_CONNECT_VOLT_60HZ; inv_bus_start_volt=DC_BUS_INV_START_VOLT_60HZ; inv_bus_UV=DC_BUS_UNDERVOLTAGE_LIMIT_60HZ; inv_bus_OV=DC_BUS_OVERVOLTAGE_LIMIT_60HZ; cntlPI_BusInv.Umin =_IQ(0.025); SlewClrInvTrip=10; } } #else PVInverterState=CheckPV; #endif if(Gui_InvStop==1) { PVInverterState=Idle; Gui_InvStop=0; } break; case CheckPV: // AC is present, check if PV is present if(Gui_InvStop==1) { PVInverterState=ResetState1; // go to the re-initalization state, this logs any fault conditions as well Gui_InvStop=0; } if(Gui_Vpv>VPV_MIN) { // sufficient PV voltage is present // Clear Fly Back Trip and monitor DC BUs PVInverterState=MonitorDCBus; EALLOW; EPwm3Regs.TZCLR.bit.OST=0x1; CloseFlybackLoop=1; EDIS; pv_ref_cur_inst=_IQ24(0.1); pv_ref_cur_fixed=_IQ24(0.15); } break; case MonitorDCBus: // Flyback is pumping current into the DC Bus // Monitor the DC Bus Value #if(GRID_CONNECT==1) if(UV_Flag==1||OV_Flag==1) //UF_Flag==1||||OF_Flag==1 { Gui_InvStop=1; } #endif if(vbus_meas_inst>inv_bus_OV) // Check for Over Voltage Condition { BusOverVoltageTrip=1; Gui_InvStop=1; } if(Gui_InvStop==1) { PVInverterState=ResetState1; // go to the re-initalization state Gui_InvStop=0; } if(vbus_meas_inst>inv_bus_rly_connect) { RlyConnect=1; } // Check if DC Bus is greater than DC_BUS_INV_START_VOLT // Also Check if the Relay has been connected // As currently the inverter is off this will happen quickly if(vbus_meas_inst>inv_bus_start_volt && GpioDataRegs.GPADAT.bit.GPIO22==1) { SlewClrInvTrip--; if(SlewClrInvTrip==0) { PVInverterState=EnableMPPT; // Take inverter out of reset ClearInvTrip=1; } } SlewState4=250; break; case EnableMPPT: // Wait Before enabling MPPT SlewState4--; if(SlewState4==0) { PVInverterState=PVInverterActive; //Enable MPPT MPPT_ENABLE=1; mppt_incc_I1.mppt_first=1; mppt_incc_I1.mppt_enable=1; } // check for under voltage if(vbus_meas_inst<inv_bus_UV) { BusUnderVoltageTrip=1; Gui_InvStop=1; } // Check for Over Voltage Condition if(vbus_meas_inst>inv_bus_OV) { BusOverVoltageTrip=1; Gui_InvStop=1; } #if(GRID_CONNECT==1) if(UV_Flag==1||OV_Flag==1) //UF_Flag==1||||OF_Flag==1 { Gui_InvStop=1; } #endif if(Gui_InvStop==1) { PVInverterState=ResetState1; // go to the re-initalization state Gui_InvStop=0; } break; case PVInverterActive: //Inverter is Fully Active Now // Check for Faults or Stop Command #if(GRID_CONNECT==1) if(UV_Flag==1||OV_Flag==1) //||OF_Flag==1UF_Flag==1|| { Gui_InvStop=1; } #endif // check for under voltage if(vbus_meas_inst<inv_bus_UV) { BusUnderVoltageTrip=1; Gui_InvStop=1; } // Check for Over Voltage Condition if(vbus_meas_inst>inv_bus_OV) { BusOverVoltageTrip=1; Gui_InvStop=1; } if(Gui_InvStop==1) { PVInverterState=ResetState1; // go to the re-initalization state Gui_InvStop=0; } break; case ResetState1: #if(GRID_CONNECT==1) /*if(UF_Flag==1) { FaultFlag=1; Gui_InvStop=1; } else if (OF_Flag==1) { FaultFlag=2; Gui_InvStop=1; } */ if(UV_Flag==1) { FaultFlag=UnderVoltageGrid; } else if(OV_Flag==1) { FaultFlag=OverVoltageGrid; } else if(BusUnderVoltageTrip==1) { FaultFlag=UnderVoltageDCBus; } else if(BusOverVoltageTrip==1) { FaultFlag=OverVoltageDCBus; } #endif // Run the reset sequence // Fist disable MPPT and set the ref current command to zero // This is done to make sure the flyback does not see <10% duty when tripping MPPT_ENABLE=0; mppt_incc_I1.mppt_first=1; mppt_incc_I1.mppt_enable=0; pv_ref_cur_inst=_IQ24(0.0); // zero the buffer values, this makes sure the DC-DC Flyback stage shuts down fast //DINT; // CNTL_2P2Z_IQ_C_VAR_INIT(cntl2p2z_DCDCI_vars); //EINT; duty_flyback=0; duty_flyback_pu=0; CloseFlybackLoop=0; PVInverterState=ResetState2; break; case ResetState2: //Disconnect relay GpioDataRegs.GPACLEAR.bit.GPIO22=1; // by now the CMPA value should be zero if(EPwm3Regs.CMPA.half.CMPA==0) { // Trip the PWM for the inverter // software force the trip of inverter and flyback EALLOW; EPwm1Regs.TZFRC.bit.OST=0x1; EPwm2Regs.TZFRC.bit.OST=0x1; EPwm3Regs.TZFRC.bit.OST=0x1; EPwm1Regs.CMPA.half.CMPA=0; EPwm1Regs.CMPB=0; EPwm2Regs.CMPA.half.CMPA=0; EPwm3Regs.CMPA.half.CMPA=0; EDIS; duty_inv_pu=0; duty_inv=0; inv_Iset=0; CloseIloopInv=0; #if (GRID_CONNECT==1) if(FaultFlag==0) PVInverterState=Idle; else PVInverterState=FaultState; #else PVInverterState=Idle; #endif CNTL_2P2Z_IQ_VARS_init(&cntl2p2z_DCDCI_vars); CNTL_3P3Z_IQ_VARS_init(&cntl3p3z_InvI_vars); cntlPI_BusInv.up=0; cntlPI_BusInv.ui=0; cntlPI_BusInv.v1=0; cntlPI_BusInv.i1=0; cntlPI_BusInv.up=0; cntlPI_BusInv.w1=0; } break; default: break; } #endif //TODO AC Measurements //--------------------------------------------------------------------- // Grid Frequency Measurements //--------------------------------------------------------------------- ACFreq_SysTicks = (ECap1Regs.CAP1 + ECap1Regs.CAP2 + ECap1Regs.CAP3 + ECap1Regs.CAP4) << 3; ACFreq = _IQ4div(_IQ4(CPU_FREQ), ACFreq_SysTicks); if (ECap1Regs.TSCTR > ECAP_TimerMaxVal || (ECap1Regs.CAP1 > ECAP_TimerMaxVal) || (ECap1Regs.CAP2 > ECAP_TimerMaxVal) || (ECap1Regs.CAP3 > ECAP_TimerMaxVal)) { ACFreq_SysTicks = 0; ACFreq = 0; } if (ACFreq < _IQ4(GRID_MIN_FREQ)) UF_Flag = 1; else UF_Flag = 0; if (ACFreq > _IQ4(GRID_MAX_FREQ)) OF_Flag = 1; else OF_Flag = 0; MATH_EMAVG2_IQ_MACRO((_IQ24abs(inv_meas_vol_inst)), inv_emavg_vol, _IQ24(0.0003)); Gui_Vavg = _IQ16mpy((int32)inv_emavg_vol>>8,_IQ16(AC_PEAK_SENSE)); if (Gui_Vavg < _IQ16(GRID_MIN_VRMS)) UV_Flag = 1; else UV_Flag = 0; if (Gui_Vavg > _IQ16(GRID_MAX_VRMS)) OV_Flag = 1; else OV_Flag = 0; if (UF_Flag == 0 && Gui_Vavg > _IQ16(40.0)) { //Calculate RMS input voltage and input frequency sine_mains.Iin = inv_meas_cur_inst >> 9; sine_mains.Vin = inv_meas_vol_inst >> 9; SINEANALYZER_DIFF_wPWR_IQ_MACRO(sine_mains); VRMS = (sine_mains.Vrms) << 9;// Convert sine_mainsV.Vrms from Q15 to Q24 and save as VrectRMS IRMS = (sine_mains.Irms) << 9;// Convert sine_mainsV.Irms from Q15 to Q24 and save as IrectRMS PRMS = (sine_mains.Prms) << 9;// Convert sine_mainsV.Prms from Q15 to Q24 and save as PinRMS Gui_Prms = (sine_mains.Prms * K_Prms) >> 15; Gui_Irms = (sine_mains.Irms * K_Irms) >> 15; Gui_Vrms = (sine_mains.Vrms * K_Vrms) >> 15; /*if(Gui_Vrms<_IQ6(GRID_MIN_VRMS)) UV_Flag=1; else UV_Flag=0; if(Gui_Vrms>_IQ6(GRID_MAX_VRMS)) OV_Flag=1; else OV_Flag=0; */ } else { VRMS = 0;// Convert sine_mainsV.Vrms from Q15 to Q24 and save as VrectRMS IRMS = 0;// Convert sine_mainsV.Irms from Q15 to Q24 and save as IrectRMS PRMS = 0;// Convert sine_mainsV.Prms from Q15 to Q24 and save as PinRMS Gui_Prms = 0; Gui_Irms = 0; Gui_Vrms = 0; SINEANALYZER_DIFF_wPWR_IQ_init(&sine_mains); sine_mains.Vin = 0; sine_mains.Iin = 0; sine_mains.SampleFreq = _IQ15(1000.0); sine_mains.Threshold = _IQ15(0.1); sine_mains.nsamplesMax=1000/UNIVERSAL_GRID_MIN_FREQ; sine_mains.nsamplesMin=1000/UNIVERSAL_GRID_MAX_FREQ; } Gui_Vpv = _IQ20mpy(pv_meas_vol_avg>>4,_IQ20(PV_VOL_SENSE_MAX)); Gui_Ipv = _IQ20mpy(pv_meas_cur_avg>>4,_IQ20(PV_CURR_SENSE_MAX)); Gui_Vbus = _IQ20mpy(vbus_meas_avg>>4,_IQ20(VBUS_VOL_SENSE_MAX)); //Freq_Vin = sine_mainsV.SigFreq;// Q15 //VrmsReal = _IQ15mpy (KvInv, sine_mainsV.Vrms); //Gui_PinRMS = (sine_mainsV.Prms*K_Prms) >> 15;//Q15*Q15 >> 15 = Q15, When no calibration is used // if((sine_mainsV.Prms>123)&&(sine_mainsV.Prms <= 858)){ //Max Power used for normalization is 19.8*405.2=8022.96W.// // //So 210W = 210/8022.96 *32767 = 858 in Q15 format// // // 30W = 30/8022.96 *32767 = 123 in Q15 format// // Gui_PinRMS = (((sine_mainsV.Prms*slope_Pcorr) >> 15)- offset_Pcorr);//Q15*Q15 >> 15 = Q15, // //apply calibration between 30W and 210W // } // else{ // Gui_PinRMS = (sine_mainsV.Prms*K_Prms) >> 15;//Q15*Q15 >> 15 = Q15, apply zero calibration // } // // // Gui_PinRMS_16 = (int16)(Gui_PinRMS); //TODO MPPT Task #if INCR_BUILD==2 if(MPPT_ENABLE==1) { if(MPPT_slew==0) { Run_MPPT=1; MPPT_slew=100; } else MPPT_slew--; } #endif if (Run_MPPT == 1) { Run_MPPT = 0; // MPPT routine mppt_incc_I1.Ipv =pv_meas_cur_avg; //IpvRead; mppt_incc_I1.Vpv =pv_meas_vol_avg; //VpvRead; MPPT_INCC_I_IQ_MACRO(mppt_incc_I1); pv_ref_cur_mppt = mppt_incc_I1.ImppOut; #if(MPPT==1) if(Gui_MPPTEnable==1) pv_ref_cur_inst=pv_ref_cur_mppt; else pv_ref_cur_inst=pv_ref_cur_fixed; #else pv_ref_cur_inst = pv_ref_cur_fixed; #endif } if (EPwm1Regs.TZFLG.bit.OST == 1 && RlyConnect == 1 && PVInverterState >= 4) { OverCurrent = 1; } else if (EPwm1Regs.TZFLG.bit.OST == 0) { OverCurrent = 0; } } /**********************************************************/ /********************** ECAP INIT *************************/ /**********************************************************/ void InitECapture() { ECap1Regs.ECEINT.all = 0x0000; // Disable all capture interrupts ECap1Regs.ECCLR.all = 0xFFFF; // Clear all CAP interrupt flags ECap1Regs.ECCTL1.bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // Make sure the counter is stopped // Configure peripheral registers ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // Operation in Continuous Mode ECap1Regs.ECCTL2.bit.STOP_WRAP = 3; // Wrap after 4 events ECap1Regs.ECCTL1.bit.CAP1POL = 1; // Falling edge ECap1Regs.ECCTL1.bit.CAP2POL = 0; // Rising edge ECap1Regs.ECCTL1.bit.CAP3POL = 1; // Falling edge ECap1Regs.ECCTL1.bit.CAP4POL = 0; // Rising edge ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // Difference operation ECap1Regs.ECCTL1.bit.CTRRST2 = 1; // Difference operation ECap1Regs.ECCTL1.bit.CTRRST3 = 1; // Difference operation ECap1Regs.ECCTL1.bit.CTRRST4 = 1; // Difference operation ECap1Regs.ECCTL2.bit.SYNCI_EN = 0; // Enable sync in ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0; // Pass through ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable capture units ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // Start Counter //ECap1Regs.ECCTL2.bit.REARM = 1; // arm one-shot ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads // ECap1Regs.ECEINT.bit.CEVT4 = 1; // 4 events = interrupt }