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
}