hi Guys,
I use a Concerto F28M35H52C1 and did on C28 code
from Solar Explorer Development Kit with a few small changes.
( CCS 6.11.00022 )
I little confused, I can not explain why currently logically
go following things or not:
following works well :
325 // for Testing
326 int16 upcount1 = 0;
327 int16 upcount2 = 0;
328 int16 upcount3 = 0;
329 int16 upcount4 = 0;
//
..
737 upcount1 ++;
751 upcount2++;
this crashed the Program:
325 // for Testing
326 Uint32 upcount1 = 0;
327 Uint32 upcount2 = 0;
328 Uint32 upcount3 = 0;
329 Uint32 upcount4 = 0;
//
..
737 upcount1 ++;
751 upcount1 ++;
works fine:
//C28x owned memory region
struct CtoM_Message {
int32 InverterStatus;
float PanelPower;
float PanelPower_Theoretical;
float PanelVoltage;
float PanelCurrent;
float BoostVoltage;
Uint32 upcount1;
Uint32 upcount2;
Uint32 upcount3;
Uint32 upcount4;
};
737 upcount1 ++;
751 upcount1 ++;
can anyone explain me, why my code does not work when i declare 4 int32 or Uint32 variables instead of int16 / Uint16 ?
But why can i do a struct with exact the same amount of variables ?
thanks for your help
holger
//----------------------------------------------------------------------------------
// FILE: SolarExplorer-Main.C
//
// Description: SolarExplorer Kit [R5] Demo using F28M35x, ver 1.0 of control card
// with floating point support for PV Inverter
//
// Version: 1.0
//
// Target: F28M35x
//
//----------------------------------------------------------------------------------
// Copyright Texas Instruments © 2004-2011
//----------------------------------------------------------------------------------
// Revision History:
//----------------------------------------------------------------------------------
// Date | Description / Status
//----------------------------------------------------------------------------------
// Nov 18 2011 - Manish Bhardwaj
//----------------------------------------------------------------------------------
//
// 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}-DPL-ISR.asm"
// - Assembly level library Macros and any cycle critical functions are found here
// "{ProjectName}-Settings.h"
// - Global defines (settings) project selections are found here
// - This file is referenced by both C and ASM files.
//
// 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 "SolarExplorer-Includes.h"
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// FUNCTION PROTOTYPES
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Add protoypes of functions being used in the project here
void DeviceInit(void);
#ifdef FLASH_F28M35x
void InitFlash();
#endif
void MemCopy();
#ifdef FLASH_F28M35x
#pragma CODE_SECTION(Inv_ISR,"ramfuncs");
#endif
__interrupt void Inv_ISR(void);
#pragma INTERRUPT (Inv_ISR, LPI)
//------------------------------- DPLib ----------------------------------------------
void PWM_1ch_UpDwnCntCompl_CNF(int16 n, int16 period, int16 mode, int16 phase);
void ADC_CNF(int AdcNum, int ChSel[], int TrigSel[], int ACQPS[]);
// ---------------------------- FRAMEWORK --------------------------------------------
// State Machine function prototypes
//------------------------------------------------------------------------------------
// Alpha states
void A0(void); //state A0
void B0(void); //state B0
void C0(void); //state C0
// 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
void B4(void); //state B4
// C branch states
void C1(void); //state C1
void C2(void); //state C2
void C3(void); //state C3
void C4(void); //state C4
// 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
void (*C_Task_Ptr)(void); // State pointer C 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
int16 VTimer2[4]; // Virtual Timers slaved off CPU Timer 2
// Used for running BackGround in flash, and ISR in RAM
extern Uint16 *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart;
// Used for copying CLA code from load location to RUN location
extern Uint16 Cla1funcsLoadStart, Cla1funcsLoadEnd, Cla1funcsRunStart;
// Used for ADC Configuration
int ChSel1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int TrigSel1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int ACQPS1[16] = {8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8};
int ChSel2[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int TrigSel2[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int ACQPS2[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,
&EPwm8Regs,
&EPwm9Regs
};
// Used to indirectly access all Comparator modules
volatile struct COMP_REGS *Comp[] =
{ &Comp1Regs, //intentional: (Comp[0] not used)
&Comp1Regs,
&Comp2Regs,
&Comp3Regs,
&Comp4Regs,
&Comp5Regs,
&Comp6Regs
};
volatile struct ADC_REGS *ADC[] =
{ &Adc1Regs, //intentional: (ADC[0] not used)
&Adc1Regs,
&Adc2Regs
};
// ---------------------------------- USER -----------------------------------------
//-------------------------------- IPC -----------------------------------------------
//*****************************************************************************
// Definitions used in this example
//*****************************************************************************
#define C28_CTOM_PASSMSG 0x0003F800 // Used by C28 to pass address
// of local variables to perform
// actions on
#define C28_MTOC_PASSMSG 0x0003FC00
// Variables that need to shared with C28x and M3
// m3 owned memory region
struct MtoC_Message {
int32 InvStart;
int32 InvStop;
float LightCommand;
};
volatile struct MtoC_Message *MtoC_Message1_Ptr;
//C28x owned memory region
struct CtoM_Message {
int32 InverterStatus;
float PanelPower;
float PanelPower_Theoretical;
float PanelVoltage;
float PanelCurrent;
float BoostVoltage;
Uint32 upcount1;
Uint32 upcount2;
Uint32 upcount3;
Uint32 upcount4;
};
volatile struct CtoM_Message *CtoM_Message1_Ptr;
// ---------------------------- DPLIB Net Pointers ---------------------------------
// Declare net pointers that are used to connect the DP Lib Macros here
// ADCDRV_1ch
// extern volatile float *ADC1DRV_1ch_Rlt5; //instance #2
// extern volatile float *ADC1DRV_1ch_Rlt6; //instance #3
// extern volatile float *ADC1DRV_1ch_Rlt7; //instance #5
// extern volatile float *ADC2DRV_1ch_Rlt1; // instance #1
// PWMDRV_1ch
//extern volatile float *PWMDRV_1ch_Duty3; // instance #3, EPWM3
extern volatile float *PWMDRV_1ch_UpDwnCntCompl_Duty3;
extern volatile float PWMDRV_1ch_UpDwnCntCompl_Period3;
//
// ---------------------------- DPLIB Variables ---------------------------------
// Declare the net variables being used by the DP Lib Macro here
volatile float Duty3A,Duty3A_fixed;
volatile float VboostRead;
volatile float VpvRef;
volatile float VpvRead, IpvRead;
volatile float VpvRead_EMAVG, IpvRead_EMAVG;
volatile float IboostswRead;
volatile float IboostSwRef;
volatile float IboostSwRef2;
volatile float VpvRef_MPPT;
float Pgain_V,Igain_V,Dgain_V,Dmax_V;
float Pgain_I,Igain_I,Dgain_I,Dmax_I;
int16 UpdateCoef;
//-------------------------- MPPT tracking PnO and Incc ---------------------------
mppt_incc mppt_incc1 = mppt_incc_DEFAULTS;
mppt_pno mppt_pno1 = mppt_pno_DEFAULTS;
int16 MPPT_slew;
int16 Run_MPPT;
int16 MPPT_ENABLE;
int16 PanelBoostConnect; // 0 when Panel is connected to battery input
// 1 when panel is connected to boost input
int16 MPPT_method; // 0 for INCC
// 1 for PnO
//-----------------------------Inverter Variables ----------------------------------
//--------------------------------- SINE GEN LIB ------------------------------------
SGENHP_2 sgen = SGENHP_2_DEFAULTS;
//-------------------------------- PWM DAC driver -----------------------------------
int16 PwmDacCh1=0;
int16 PwmDacCh2=0;
int16 PwmDacCh3=0;
int16 PwmDacCh4=0;
PWMDAC pwmdac1 = PWMDAC_DEFAULTS;
//-------------- PID GRANDO INSTANCE Voltage Loop and Current Loop -----------------
PID_GRANDO_CONTROLLER pidGRANDO_Iinv = {PID_TERM_DEFAULTS, PID_PARAM_DEFAULTS, PID_DATA_DEFAULTS};
PID_GRANDO_CONTROLLER pidGRANDO_Vinv = {PID_TERM_DEFAULTS, PID_PARAM_DEFAULTS, PID_DATA_DEFAULTS};
// ------------- Sine Analyzer Block to measure RMS, frequency and ZCD ---------
SineAnalyzer_diff sine_mainsV = SineAnalyzer_diff_DEFAULTS;
// ------------- Software PLL for Grid Tie Applications ------------------------------
SPLL_1ph spll1;
// ------------- Data Logger ---------------------------------------------------------
// Datalogger options and instance creation
int16 DlogCh1 = 0;
int16 DlogCh2 = 0;
int16 DlogCh3 = 0;
int16 DlogCh4 = 0;
//DLOG_4CH dlog = DLOG_4CH_DEFAULTS;
int16 PVInverterState;
int16 CloseVloopInv;
int16 CloseIloopInv;
int16 ClearInvTrip;
int16 ResetPLL;
float inv_ref_vol_inst,inv_meas_vol_inst;
float inv_ref_cur_inst, inv_meas_cur_inst;
float inv_meas_cur_lleg1_inst;
float inv_meas_cur_lleg2_inst;
float InvModIndex;
float inv_Iset;
float InvSine;
float duty=0.0;
float Grid_Freq=GRID_FREQ;
float Vac_in;
float Offset_Volt;
float VrmsReal, VavgReal;
float ScaleFactor;
// Stand Alone Flash Image Instrumentation, GPIO toggles for different states
int16 LedBlinkCnt,LedBlinkCnt2;
int16 timer1;
Uint16 VloopTicker=0;
Uint16 ZCDDetect=0;
int16 sine_prev=0;
//------------------------ Display Values ------------------------------------------
// Monitor ("Get") // Display as:
volatile float Gui_Vpv;
volatile float Gui_Ipv;
volatile float Gui_Vboost;
volatile float Gui_PanelPower;
volatile float Gui_PanelPower_Theoretical;
volatile float Gui_Light;
volatile float Gui_LightCommand;
volatile float Gui_LightCommand_Prev;
volatile long double Gui_Vpv_Big;
volatile float Gui_Vpv_half;
Uint16 Gui_MPPTEnable;
Uint16 Gui_InvStart;
Uint16 Gui_InvStop;
Uint16 i;
// Testing
// int16 upcount3=0;
// int16 upcount4=0;
//
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// MAIN CODE - starts here
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void main(void)
{
//=================================================================================
// INITIALISATION - General
//=================================================================================
DeviceInit(); // Device Life support & GPIO
// Only used if running from FLASH
// Note that the variable FLASH_F28M35x is defined by the compiler with -d FLASH_F28M35x
#ifdef FLASH_F28M35x
// 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);
// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM
InitFlash(); // Call the flash wrapper init function
#endif //(FLASH)
// On Concerto the comparator output is not mapped internally to the PWM TZ
// The comparator output needs to be brought out on a AGPIO pin and then routed to a GPIO on the C28x side
// COMP1 which is the Boost Voltage compare out is brought out on AGPIO1 i.e. pin 129 on #144 package
// This selection is done in the AGPIO section in the DevInit File
// The pin 129 is connected on the concerto control card to PF3_GPIO35 which is configured as a trip source below
EALLOW;
GpioTripRegs.GPTRIP10SEL.bit.GPTRIP10SEL =35; //Map Trip input 10 (COMP1OUT) to PF3_GPIO35
EDIS;
//-------------------------------- FRAMEWORK --------------------------------------
// Timing sync for background loops
CpuTimer0Regs.PRD.all = mSec5; // A tasks
CpuTimer1Regs.PRD.all = mSec50; // B tasks
CpuTimer2Regs.PRD.all = mSec1000; // C tasks
// Tasks State-machine init
Alpha_State_Ptr = &A0;
A_Task_Ptr = &A1;
B_Task_Ptr = &B1;
C_Task_Ptr = &C1;
VTimer0[0] = 0;
VTimer1[1] = 0;
VTimer2[2] = 0;
for (i=0; i<16; i++)
{
ChSel1[i] = 0;
TrigSel1[i] = 0;
ACQPS1[i] = 8;
ChSel2[i] = 0;
TrigSel2[i] = 0;
ACQPS2[i] = 8;
}
// ---------------------------------- USER -----------------------------------------
// put common initialization/variable definitions here
Gui_Vpv=0;
Gui_Ipv=0;
Gui_Vboost=0;
Gui_PanelPower_Theoretical=0.0;
LedBlinkCnt = 5;
PanelBoostConnect=0;
UpdateCoef=0;
MtoC_Message1_Ptr= (void *)C28_MTOC_PASSMSG;
CtoM_Message1_Ptr= (void *)C28_CTOM_PASSMSG;
CtoM_Message1_Ptr->BoostVoltage=0;
CtoM_Message1_Ptr->InverterStatus=0;
CtoM_Message1_Ptr->PanelCurrent=0;
CtoM_Message1_Ptr->PanelPower=0;
CtoM_Message1_Ptr->PanelPower_Theoretical=0;
CtoM_Message1_Ptr->PanelVoltage=0;
// ---------------------------------- USER -----------------------------------------
// configure the PWM1 for the inverter driver
// 20Khz = (150Mhz/20Khz)/2 = 3750
// From the datasheet of the mosfet used the Ton and Toff is 264ns
// therefore 150 Mhz => ~40 Ticks
PWM_1phInv_unipolar_CNF(1,3750,40,40);
// SOC for DCDC Boost MPPT
EPwm3Regs.ETSEL.bit.SOCAEN = 1;
EPwm3Regs.ETSEL.bit.SOCASEL = ET_CTR_PRD ; // Use PRD event as trigger for ADC SOC
EPwm3Regs.ETPS.bit.SOCAPRD = ET_2ND; // Generate pulse on 2nd event
#define Ileg1_fb Adc1Result.ADCRESULT1
#define Ileg2_fb Adc1Result.ADCRESULT2
#define Vac_FB Adc1Result.ADCRESULT3
#define Ipv_FB Adc1Result.ADCRESULT5
#define Vpv_FB Adc1Result.ADCRESULT6
#define Vboost_FB Adc1Result.ADCRESULT7
#define Iboostsw_FB Adc2Result.ADCRESULT1
#define LIGHT_FB Adc2Result.ADCRESULT2
// ADC Channel Selection
ChSel1[0] = 4; //ADC1 SOC 0 -> Ileg1-fb -> ADC1-A4 on F28M3x rev 1.0 -> ADC-A4 {Piccolo}, dummy
ChSel1[1] = 4; //ADC1 SOC 0 -> Ileg1-fb -> ADC1-A4 on F28M3x rev 1.0 -> ADC-A4 {Piccolo}
ChSel1[2] = 6; //ADC1 SOC 1 -> Ileg2-fb -> ADC1-A6 on F28M3x rev 1.0 -> ADC-A6 {Piccolo}
ChSel1[3] = 7; //ADC1 SOC 4 -> Vac-fb -> ADC1-A7 on F28M3x rev 1.0 -> ADC-A5 {Piccolo}
ChSel1[4] = 0; //ADC1 SOC 2 -> Ipv-fb -> ADC1-A0 on F28M3x rev 1.0 -> ADC-A0 {Piccolo}, dummy
ChSel1[5] = 0; //ADC1 SOC 2 -> Ipv-fb -> ADC1-A0 on F28M3x rev 1.0 -> ADC-A0 {Piccolo}
ChSel1[6] = 8; //ADC1 SOC 3 -> Vpv-fb -> ADC1-B0 on F28M3x rev 1.0 -> ADC-A1 {Piccolo}
ChSel1[7] = 2; //ADC1 SOC 5 -> Vboost-fb -> ADC1-A2 on F28M3x rev 1.0 -> ADC-A2 {Piccolo}
// ADC Trigger Selection
TrigSel1[0] = 6; // ADC1 SOC 0 -> Ileg1-fb, dummy
TrigSel1[1] = 6; // ADC1 SOC 0 -> Ileg1-fb
TrigSel1[2] = 6; // ADC1 SOC 1 -> Ileg2-fb
TrigSel1[3] = 6; // ADC1 SOC 4 -> Vac-fb
TrigSel1[4] = 5; // ADC1 SOC 2 -> Ipv-fb , dummy
TrigSel1[5] = 5; // ADC1 SOC 2 -> Ipv-fb
TrigSel1[6] = 5; // ADC1 SOC 3 -> Vpv-fb
TrigSel1[7] = 5; // ADC1 SOC 5 -> Vboost-fb
// Let Trigger 1 be used for the Boost Control and the Trigger 2 be used for the inverter control
// Configure the CIB triggers (Note this needs to be done before the ADC SOC trigger selection)
EALLOW;
AnalogSysctrlRegs.TRIG1SEL.all = ADCTRIG_EPWM3_SOCA; // EPWM3SOCA to TRIGGER 1 of the analog subsystem
AnalogSysctrlRegs.TRIG2SEL.all = ADCTRIG_EPWM1_SOCA; // EPWM1SOCA to Trigger 2 of the analog subsystem
EDIS;
ADC_CNF(1, ChSel1, TrigSel1, ACQPS1);
// ADC Channel Selection
ChSel2[0] = 6; //ADC2 SOC 0 -> Iboostsw-fb-> ADC2-A6 on F28M3x rev 1.0 -> ADC-B6 {Piccolo}
ChSel2[1] = 6; //ADC2 SOC 0 -> Iboostsw-fb-> ADC2-A6 on F28M3x rev 1.0 -> ADC-B6 {Piccolo}
ChSel2[2] = 0; //ADC2 SOC 1 -> Vlight-fb -> ADC2-A0 on F28M3x rev 1.0 -> ADC-B0 {Piccolo}
// ADC Trigger Selection
TrigSel2[0] = 5; // ADC2 SOC 0 -> Iboostsw-fb, dummy
TrigSel2[1] = 5; // ADC2 SOC 0 -> Iboostsw-fb
TrigSel2[2] = 6; // ADC2 SOC 2 -> Vlight-fb
ADC_CNF(2, ChSel2, TrigSel2, ACQPS2);
// Digital Power CLA(DP) library initialisation
// DPL_Init();
// Lib Module connection to "nets"
//----------------------------------------
// Connect the PWM Driver input to an input variable, Open Loop System
// PWMDRV_1ch_UpDwnCntCompl_Duty3 = &Duty3A_fixed; //&Duty3A; //&Duty3A_fixed;
// ADC2DRV_1ch_Rlt1 = &IboostswRead;
// ADC1DRV_1ch_Rlt5 = &IpvRead;
// ADC1DRV_1ch_Rlt6 = &VpvRead;
// ADC1DRV_1ch_Rlt7 = &VboostRead;
// Initialize the net variables
// Duty3A =0.0;
VboostRead=0.0;
IboostswRead=0.0;
VpvRef=0.9; // to increase current, we need to reduce VpvRef, thus initailize it with a high value.
IboostSwRef=0.0;
// Duty3A_fixed=0.0;
VpvRead_EMAVG=0.0;
IpvRead_EMAVG=0.0;
//Inverter
// Signal Generator module initialisation
sgen.offset=0;
sgen.gain=0x7fff; // gain=1 in Q15
sgen.freq=0x14F8CF92; // freq = (Required Freq/Max Freq)*2^31
// = (50/305.17)*2^31 = 0x14f8cf92
sgen.step_max=0x3E7FB26; // Max Freq= (step_max * sampling freq)/2^32
// =(0x3E7FB26*20k)/2^32 = 305.17
sgen.phase=0x80000000; // Phase= (required Phase)/180 in Q31 format
// = (+90/180) in Q31 = 8000h
//sine analyzer initialization
sine_mainsV.Vin=0;
sine_mainsV.SampleFreq=20000.0;
sine_mainsV.Threshold=0.0;
pidGRANDO_Iinv.param.Kp=0.8;
pidGRANDO_Iinv.param.Ki=(0.15);
pidGRANDO_Iinv.param.Kd=(0.0);
pidGRANDO_Iinv.param.Kr=(1.0);
pidGRANDO_Iinv.param.Umax=(1.0);
pidGRANDO_Iinv.param.Umin=(-1.0);
// Initialize PWMDAC module
pwmdac1.PeriodMax = 500; // 3000->10kHz, 1500->20kHz, 1000-> 30kHz, 500->60kHz
pwmdac1.PwmDacInPointer0 = &PwmDacCh1;
pwmdac1.PwmDacInPointer1 = &PwmDacCh2;
pwmdac1.PwmDacInPointer2 = &PwmDacCh3;
pwmdac1.PwmDacInPointer3 = &PwmDacCh4;
pidGRANDO_Vinv.param.Kp=(3.0);
pidGRANDO_Vinv.param.Ki=(0.005);
pidGRANDO_Vinv.param.Kd=(0.0);
pidGRANDO_Vinv.param.Kr=(1.0);
pidGRANDO_Vinv.param.Umax=(0.95);
pidGRANDO_Vinv.param.Umin=(0.000);
PWMDAC_INIT_MACRO(pwmdac1)
SPLL_1ph_init(GRID_FREQ,(0.00005),&spll1);
PanelBoostConnect=0;
MPPT_ENABLE = 0;
Run_MPPT=0;
MPPT_slew=0;
VpvRef_MPPT=(0.0);
CloseVloopInv = 0;
CloseIloopInv = 0;
ClearInvTrip=0;
InvModIndex = 0;
ScaleFactor = (1.0);
inv_Iset = (0.0);
InvSine=0;
VrmsReal=0;
UpdateCoef=0;
timer1=0;
Offset_Volt=(0.5); // the input sinusoid is offset with 1.65 V
PVInverterState=0;
Gui_MPPTEnable=0;
Gui_InvStart=0;
Gui_InvStop=0;
// keep the PLL in reset by default
ResetPLL=1;
Gui_LightCommand=0.0;
//====================================================================================
// INTERRUPTS & ISR INITIALIZATION (best to run this section after other initialization)
//====================================================================================
//Also Set the appropriate # define's in the HVLLC-Settings.h
//to enable interrupt management in the ISR
EALLOW;
// Set up C28x Interrupt
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// PWM based ISR trigger, Boost DC DC Interrupt
// PieVectTable.EPWM3_INT = &DPL_ISR; // Map DPL Interrupt from EPWM3
// PieCtrlRegs.PIEIER3.bit.INTx3 = 1; // PIE level enable, Grp3 / Int3 -> EPWM3
// EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // INT on PRD event
// EPwm3Regs.ETSEL.bit.INTEN = 1; // Enable INT
// EPwm3Regs.ETPS.bit.INTPRD = ET_2ND; // Generate INT on every second event
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//PWM Based ISR Trigger, Inverter
PieVectTable.EPWM1_INT = &Inv_ISR; // Map DPL Interrupt from EPWM1
PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // PIE level enable, Grp3 / Int1 -> EPWM1
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // INT on zero event
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on every event
IER |= M_INT3; // Enable CPU INT3 connected to EPWM1-6 INTs:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
EDIS;
// Protection for over voltage on the Boost
// Vboost-fb is mapped to ADC2 -> A2 which is also connected to Comparator 4
EALLOW;
Comp1Regs.COMPCTL.bit.COMPDACEN = 1; // Power up Comparator 1 locally
Comp1Regs.COMPCTL.bit.COMPSOURCE = 0; // Connect the inverting input to the internal DAC
Comp1Regs.DACVAL.bit.DACVAL = 950; // Set DAC output to midpoint
// cannot disable hysteresis for now on COMP1 , need to identify the bit field from product apps
Adc1Regs.COMPHYSTCTL.bit.COMP1_HYST_DISABLE=1;
EDIS;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
EALLOW;
// Cycle by cycle trip for overvoltage protection
EPwm3Regs.DCTRIPSEL.bit.DCAHCOMPSEL=DC_TRIPIN10 ;
EPwm3Regs.TZDCSEL.bit.DCAEVT2=TZ_DCAH_HI;
EPwm3Regs.DCACTL.bit.EVT2SRCSEL = DC_EVT1;
EPwm3Regs.DCACTL.bit.EVT2FRCSYNCSEL=DC_EVT_ASYNC;
EPwm3Regs.TZSEL.bit.DCAEVT2=0x1;
// Define an event (DCAEVT1) based on TZ1 and TZ2
EPwm3Regs.DCAHTRIPSEL.bit.TRIPINPUT10 = 1; // Map Trip input 10(COMP2OUT) to DCAH
// What do we want the DCAEVT1 and DCBEVT1 events to do?
// DCAEVTx events can force EPWMxA
// DCBEVTx events can force EPWMxB
EPwm3Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm3Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
// CBC6 is still CPU EMU trip, no doc tells if this is true so just guessing
EPwm3Regs.TZSEL.bit.CBC6=0x1;
EPwm1Regs.TZSEL.bit.CBC6=0x1;
EPwm2Regs.TZSEL.bit.CBC6=0x1;
EPwm3Regs.TZEINT.bit.CBC=1;
//clear any spurious trips
EPwm3Regs.TZCLR.bit.OST=1;
EPwm3Regs.TZCLR.bit.DCAEVT1=1;
// software force the trip of inverter to disable the inverter completely
EPwm1Regs.TZFRC.bit.OST=0x1;
EPwm2Regs.TZFRC.bit.OST=0x1;
EDIS;
// connect the panel output to the Boost input
Run_MPPT=0;
VpvRef_MPPT=0.0;
MPPT_slew=0;
//=================================================================================
// BACKGROUND (BG) LOOP
//=================================================================================
//--------------------------------- 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
//----------------4-------------------------------------------
(*A_Task_Ptr)(); // jump to an A Task (A1,A2,A3,...)
//-----------------------------------------------------------
VTimer0[0]++; // virtual timer 0, instance 0 (spare)
CtoM_Message1_Ptr->upcount1 ++ ;
//upcount1 ++;
}
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)
CtoM_Message1_Ptr->upcount2 ++;
}
Alpha_State_Ptr = &C0; // Allow C state tasks
}
void C0(void)
{
// loop rate synchronizer for C-tasks
if(CpuTimer2Regs.TCR.bit.TIF == 1)
{
CpuTimer2Regs.TCR.bit.TIF = 1; // clear flag
//-----------------------------------------------------------
(*C_Task_Ptr)(); // jump to a C Task (C1,C2,C3,...)
//-----------------------------------------------------------
VTimer2[0]++; //virtual timer 2, instance 0 (spare)
CtoM_Message1_Ptr->upcount3 ++;
}
Alpha_State_Ptr = &A0; // Back to State A0
}
//=================================================================================
// A - TASKS
//=================================================================================
//--------------------------------------------------------
void A1(void) // Dash Board Measurements
//--------------------------------------------------------
{
// Dashboard measurement calculated by:
Gui_Vpv=VpvRead_EMAVG*Vpv_SENSE_MAX;
Gui_Ipv=IpvRead_EMAVG*Ipv_SENSE_MAX;
Gui_PanelPower_Theoretical=MAX_PANEL_POWER*Gui_LightCommand;
Gui_PanelPower= Gui_Vpv*Gui_Ipv;
Gui_Vboost=VboostRead*Vboost_SENSE_MAX;
Gui_Light = LIGHT_FB*(1.0/4025.0)*(3.3/2.4);
//-------------------
//the next time CpuTimer0 'counter' reaches Period value go to A2
A_Task_Ptr = &A2;
//-------------------
}
//-----------------------------------------------------------------
void A2(void) // Panel Connect Disconnect
//-----------------------------------------------------------------
{
if(PanelBoostConnect==0)
{
GpioG1DataRegs.GPACLEAR.bit.GPIO12=0x1;
}
else if (PanelBoostConnect==1)
{
GpioG1DataRegs.GPASET.bit.GPIO12=0x1;
}
//-------------------
//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)
//---------------------------------------------------------
{
//-----------------
//the next time CpuTimer0 'counter' reaches Period value go to A1
A_Task_Ptr = &A1;
//-----------------
}
//=================================================================================
// B - TASKS
//=================================================================================
//----------------------------------------
void B1(void) // MPPT Execution
//----------------------------------------
{
if(Run_MPPT==1)
{
if(MPPT_method==0)
{
mppt_incc1.mppt_enable=1;
// MPPT routine
mppt_incc1.Ipv = IpvRead_EMAVG; //IpvRead;
mppt_incc1.Vpv = VpvRead_EMAVG; //VpvRead;
mppt_incc_MACRO(mppt_incc1);
VpvRef_MPPT = mppt_incc1.VmppOut;
mppt_pno1.mppt_first=1;
mppt_pno1.mppt_enable=0;
}
else
{
mppt_pno1.mppt_enable=1;
mppt_pno1.Ipv = IpvRead_EMAVG; //IpvRead;
mppt_pno1.Vpv = VpvRead_EMAVG; //VpvRead;
mppt_pno_MACRO(mppt_pno1);
VpvRef_MPPT = mppt_pno1.VmppOut;
mppt_incc1.mppt_enable=0;
mppt_incc1.mppt_first=0;
}
if(VpvRef_MPPT<0.0)
{
VpvRef_MPPT=0.0;
}
else if(VpvRef_MPPT>0.9)
{
VpvRef_MPPT=0.9;
}
VpvRef=VpvRef_MPPT;
Run_MPPT=0;
}
//MPPT is a slow task, the following code enables to modulate the rate at which the MPPT is called
if(MPPT_slew==0)
{
if(MPPT_ENABLE==1)
{
Run_MPPT=1;
}
MPPT_slew=0;
}
else
MPPT_slew--;
// Toggle LD2 on the control card if MPPT enabled
if(MPPT_ENABLE==1)
{
if(LedBlinkCnt2==0)
{
if(GpioG1DataRegs.GPCDAT.bit.GPIO71==0x1)
{
GpioG1DataRegs.GPCCLEAR.bit.GPIO71=0x1;
}
else
{
GpioG1DataRegs.GPCSET.bit.GPIO71=0x1;
}
LedBlinkCnt2=1;
}
else
LedBlinkCnt2--;
}
//-----------------
//the next time CpuTimer1 'counter' reaches Period value go to B2
B_Task_Ptr = &B2;
//-----------------
}
//----------------------------------------
void B2(void) // Blink LED on the controlCARD
//----------------------------------------
{
if(LedBlinkCnt==0)
{
if(GpioG1DataRegs.GPCDAT.bit.GPIO70==0x1)
{
GpioG1DataRegs.GPCCLEAR.bit.GPIO70=0x1;
}
else
{
GpioG1DataRegs.GPCSET.bit.GPIO70=0x1;
}
LedBlinkCnt=1;
}
else
LedBlinkCnt--;
//-----------------
//the next time CpuTimer1 'counter' reaches Period value go to B1
B_Task_Ptr = &B3;
//-----------------
}
//----------------------------------------
void B3(void) // State Machine, Enable Disable Loops, User Controls
//----------------------------------------
{
if(MtoC_Message1_Ptr->InvStart==1)
{
Gui_InvStart=1;
CtoM_Message1_Ptr->InverterStatus=1;
}
if(MtoC_Message1_Ptr->InvStop==1)
{
Gui_InvStop=1;
CtoM_Message1_Ptr->InverterStatus=0;
}
Gui_LightCommand = MtoC_Message1_Ptr->LightCommand;
#if (INCR_BUILD == 2)
// Inverter State ==0 , wait for the command to start production of power
// Inverter State ==1 , Check if panel voltage is available, i.e. Vpv > 5V
// if true enable MPPT
// Inverter State ==2 , Check if Gui_Vboost>33V
// enable closed voltage loop regulation and current loop regulation
// Inverter State ==3, wait for stop command, if stop, trip all PWM's, shut down MPPT and return to state 0, reset all values
switch(PVInverterState)
{
case 0: // wait for the command to start the inverter
if(Gui_InvStart==1)
{
PVInverterState=1;
Gui_InvStart=0;
// Duty3A=0;
// PWMDRV_1ch_UpDwnCntCompl_Duty3 = &Duty3A;
}
break;
case 1: // check if PV is present
if(Gui_Vpv>(3.0))
{
PVInverterState=2;
//Enable MPPT
MPPT_ENABLE=1;
ClearInvTrip=1;
InvModIndex=(0.2);
pidGRANDO_Vinv.term.Fbk = (0.75); // 30V/ 39.97
mppt_incc1.Stepsize = (0.01);
mppt_pno1.Stepsize = 0.01;
}
if(Gui_InvStop==1)
{
PVInverterState=3;
}
break;
case 2: // Check if DC Bus is greater than 33V , as currently the inverter is off this woudl happen quickly
if(Gui_Vboost>(31.0))
{
PVInverterState=3;
CloseVloopInv=1;
CloseIloopInv=1;
mppt_incc1.Stepsize = (0.005);
mppt_pno1.Stepsize = 0.005;
}
if(Gui_InvStop==1)
{
PVInverterState=3;
}
break;
case 3: // Wait for shut down sequence
if(Gui_InvStop==1)
{
// switch off MPPT and also open the loop for current and voltage
// the open loop index on the inverter is used to discharge the boost till it is close to the input panle voltage
MPPT_ENABLE=0;
mppt_incc1.mppt_first=1;
mppt_pno1.mppt_first=1;
VpvRef=(0.9);
// Run the reset sequence
// Trip the PWM for the inverter
// software force the trip of inverter to disable the inverter completely
EALLOW;
EPwm1Regs.TZFRC.bit.OST=0x1;
EPwm2Regs.TZFRC.bit.OST=0x1;
EDIS;
// Wait for the command to be restarted
PVInverterState=0;
CloseVloopInv=0;
CloseIloopInv=0;
// Duty3A_fixed=0.0;
// PWMDRV_1ch_UpDwnCntCompl_Duty3 = &Duty3A_fixed;
Gui_InvStop=0;
}
break;
default:
break;
}
#endif
if(timer1<20)
timer1++;
if(timer1==20)
{
PanelBoostConnect=1;
timer1++;
}
//-----------------
//the next time CpuTimer1 'counter' reaches Period value go to B4
B_Task_Ptr = &B1;
//-----------------
}
//=================================================================================
// C - TASKS
//=================================================================================
//------------------------------------------------------
void C1(void) // Update Coefficients
//------------------------------------------------------
{
//Update Coefficients
if(UpdateCoef==1)
{
}
CtoM_Message1_Ptr->BoostVoltage=Gui_Vboost;
CtoM_Message1_Ptr->PanelCurrent=Gui_Ipv;
CtoM_Message1_Ptr->PanelPower=Gui_PanelPower;
CtoM_Message1_Ptr->PanelPower_Theoretical=Gui_PanelPower_Theoretical;
CtoM_Message1_Ptr->PanelVoltage=Gui_Vpv;
//-----------------
//the next time CpuTimer2 'counter' reaches Period value go to C2
C_Task_Ptr = &C1;
//-----------------
}
// ISR for inverter
__interrupt void Inv_ISR()
{
EINT;
CtoM_Message1_Ptr->upcount4 ++;
//-------------------------------------------------------------------
// Inverter State execution
//-------------------------------------------------------------------
VrmsReal = _IQ15mpy (KvInv, sine_mainsV.Vrms);
//-----------------------------------------------------------------------------------------
#if (INCR_BUILD == 1 ) // Current command is fixed
//-----------------------------------------------------------------------------------------
// frequency generation using Sine Gen function
sgen.calc(&sgen);
InvSine = (float)sgen.out1*0.000030517578125;
if (ClearInvTrip==1)
{
EALLOW;
EPwm1Regs.TZCLR.bit.OST=0x1;
EPwm2Regs.TZCLR.bit.OST=0x1;
EDIS;
ClearInvTrip=0;
}
#endif // (INCR_BUILD == 1)
//-----------------------------------------------------------------------------------------
#if (INCR_BUILD == 2) // determine the current command
//-----------------------------------------------------------------------------------------
// frequency generation using Sine Gen function
sgen.calc(&sgen);
InvSine = (float)sgen.out1*0.000030517578125;
// Connect inputs of the PID_REG3 module and call the PID IQ controller
// Voltage loop
pidGRANDO_Vinv.term.Ref = VboostRead; //Ref=VDC/sqrt(2) at full modulation index
if((sine_prev<=0)&&(sgen.out1>0))
{
ZCDDetect=1;
}
if((sine_prev>=0)&&(sgen.out1<0))
{
ZCDDetect=1;
}
sine_prev=sgen.out1;
if ( ClearInvTrip==1 && ZCDDetect==1 )
{
EALLOW;
EPwm1Regs.TZCLR.bit.OST=0x1;
EPwm2Regs.TZCLR.bit.OST=0x1;
EDIS;
ClearInvTrip=0;
}
if ((CloseVloopInv==1) && (ZCDDetect==1))
{
PID_GR_MACRO(pidGRANDO_Vinv);
inv_Iset=pidGRANDO_Vinv.term.Out;
VloopTicker++;
ZCDDetect=0;
}
#endif // (INCR_BUILD == 2)
//-----------------------------------------------------------------------------------------
#if (INCR_BUILD == 3) // determine the current command
//-----------------------------------------------------------------------------------------
// PLL Start
spll1.AC_input=((float)Vac_FB*0.000244140625-0.5)*2.0;
SPLL_1ph_run(&spll1);
//SPLL_1ph_MACRO(spll1);
InvSine =(spll1.sin[0]);
// Voltage loop
pidGRANDO_Vinv.term.Fbk = (0.75); // 30V/ 39.97
pidGRANDO_Vinv.term.Ref = VboostRead; //Ref=VDC/sqrt(2) at full modulation index
if (CloseVloopInv==1 && sine_mainsV.ZCD==1)
{
PID_GR_MACRO(pidGRANDO_Vinv);
inv_Iset=pidGRANDO_Vinv.term.Out;
}
if (ResetPLL==1)
{
SPLL_1ph_init(GRID_FREQ,(0.00005),&spll1);
ResetPLL=0;
}
if (sine_mainsV.ZCD==1 && ClearInvTrip==1)
{
EALLOW;
EPwm1Regs.TZCLR.bit.OST=0x1;
EPwm2Regs.TZCLR.bit.OST=0x1;
EDIS;
ClearInvTrip=0;
}
#endif // (INCR_BUILD == 3)
inv_ref_cur_inst = inv_Iset*InvSine;
inv_meas_cur_lleg1_inst=(float)Ileg1_fb*0.000244140625 -0.5;
inv_meas_cur_lleg2_inst=(float)Ileg2_fb*0.000244140625 -0.5;
inv_meas_cur_inst = (inv_meas_cur_lleg1_inst - inv_meas_cur_lleg2_inst)*2.0;
inv_meas_vol_inst =((float)Vac_FB*0.000244140625-0.5)*2.0;
pidGRANDO_Iinv.term.Fbk=inv_meas_cur_inst;
pidGRANDO_Iinv.term.Ref=inv_ref_cur_inst;
if(CloseIloopInv==1)
{
PID_GR_MACRO(pidGRANDO_Iinv);
}
// Apply inverter o/p correction
if (CloseIloopInv ==0)
{
duty=InvSine*InvModIndex;
PWMDRV_1phInv_unipolar(1,3750.0,(duty));
}
else
{
PWMDRV_1phInv_unipolar(1,3750.0,pidGRANDO_Iinv.term.Out);
}
// ------------------------------------------------------------------------------
// Connect inputs to the sine analyzer block , compute RMS, Freq, ZCD
// ------------------------------------------------------------------------------
sine_mainsV.Vin =(((float)Vac_FB*0.000244140625)-0.5)*2;
SineAnalyzer_diff_MACRO (sine_mainsV);
// ------------------------------------------------------------------------------
// Connect inputs of the PWMDAC module
// ------------------------------------------------------------------------------
#if (INCR_BUILD == 2 || INCR_BUILD == 1)
PwmDacCh1 = (int16)_IQtoQ15(inv_ref_cur_inst);
PwmDacCh2 = (int16)_IQtoQ15(inv_meas_cur_inst);
#elif (INCR_BUILD == 3)
PwmDacCh1 = (int16)_IQtoQ15(spll1.sin[0]);
PwmDacCh2 = (int16)_IQtoQ15(inv_meas_vol_inst);
#endif
// ------------------------------------------------------------------------------
// Call the PWMDAC update macro.
// ------------------------------------------------------------------------------
PWMDAC_MACRO(pwmdac1)
// ------------------------------------------------------------------------------
// Connect inputs of the Datalogger module
// ------------------------------------------------------------------------------
/*
#if (INCR_BUILD == 2 || INCR_BUILD == 1)
DlogCh1 = (Uint16)sgen.out1;
#elif (INCR_BUILD == 3)
DlogCh1 = (Uint16)_IQtoQ15(spll1.sin[0]); //PLL is in Q21, shift left by 3 to make it Q24
#endif
//DlogCh2 = (int16)_IQtoQ15(inv_meas_vol_inst);
DlogCh2 = (int16)_IQtoQ15(CtoM_Message1_Ptr->PanelPower);
DlogCh3 = (int16)_IQtoQ15(inv_meas_cur_inst);
DlogCh4 = (int16)_IQtoQ15(inv_ref_cur_inst);
dlog.update(&dlog);
*/
EPwm1Regs.ETCLR.bit.INT = 1;
// Acknowledge interrupt to recieve more interrupts from PIE group 3
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
return;
}