Other Parts Discussed in Thread: CONTROLSUITE, C2000WARE
Tool/software: Code Composer Studio
Hello
I am having a problem to configure the CLA. I want it to calculate the median of some vectors that I give to it.
I'm getting some errors but I have no clue what they mean or where the actual mistake might be.
I added the three files (most important) files that I am using for this project in attachment.
//###########################################################################
// $TI Release: F2837xD Support Library v200 $
// $Release Date: Tue Jun 21 13:00:02 CDT 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################
//
// Included Files
//
#include "F28x_Project.h"
#include "cla_shared.h"
#define RESULTS_BUFFER_SIZE 10
#define OFFSET 0x0852 //0x07FF //Offset value of 2047 (=4095/2)
//
// Globals
//
//typedef struct
//{
// volatile struct EPWM_REGS *EPwmRegHandle;
//Uint16 EPwm_CMPA_Direction;
//Uint16 EPwm_CMPB_Direction;
//Uint16 EPwmTimerIntCount;
//Uint16 EPwmMaxCMPA;
//Uint16 EPwmMinCMPA;
//Uint16 EPwmMaxCMPB;
//Uint16 EPwmMinCMPB;
//}EPWM_INFO;
//CLA defines
#define WAITSTEP asm(" RPT #255 || NOP")
//*****************************************************************************
// globals
//*****************************************************************************
//Task 1 (C) Variables
#ifdef __cplusplus
// CLA Input Data
#pragma DATA_SECTION("CpuToCla1MsgRAM");
#pragma DATA_SECTION("CpuToCla1MsgRAM");
#pragma DATA_SECTION("CpuToCla1MsgRAM");
double I_1[RESULTS_BUFFER_SIZE];
double I_2[RESULTS_BUFFER_SIZE];
double I_3[RESULTS_BUFFER_SIZE];
// CLA Output Data
#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
#pragma DATA_SECTION("Cla1ToCpuMsgRAM");
double i_1_median;
double i_2_median;
double i_3_median;
#else
// CLA Input Data
#pragma DATA_SECTION(I_1,"CpuToCla1MsgRAM");
#pragma DATA_SECTION(I_2,"CpuToCla1MsgRAM");
#pragma DATA_SECTION(I_3,"CpuToCla1MsgRAM");
double I_1[RESULTS_BUFFER_SIZE];
double I_2[RESULTS_BUFFER_SIZE];
double I_3[RESULTS_BUFFER_SIZE];
// Length 3 and 4 are #defined in vmaxfloat_shared.h
// CLA Output Data
#pragma DATA_SECTION(i_1_median,"Cla1ToCpuMsgRAM");
#pragma DATA_SECTION(i_2_median,"Cla1ToCpuMsgRAM");
#pragma DATA_SECTION(i_3_median,"Cla1ToCpuMsgRAM");
double i_1_median;
double i_2_median;
double i_3_median;
#endif
//variables for the median function
float temp;
int a, b;
//double I_1_temp[RESULTS_BUFFER_SIZE];
//double i_1_median;
//double i_2_median;
//double i_3_median;
//variables for the mean function
double sum = 0;
double i_1 = 0;
double i_2 = 0;
double i_3 = 0;
int i;
//PI current controller parameters
double Kp_i = 10; //Proportional gain
double Ki_i = 100; //Integral gain
double i1_ref = 0; //Reference current line 1
double i1 = 0; //Measured current in line 1
double i2_ref = 0; //Reference current line 2
double i2 = 0; //Measured current in line 1
double i3_ref = 0; //Reference current line 3
double i3 = 0; //Measured current in line 1
Uint16 i_max = 10; //The reference current always needs to be in between 0 and 10 amps
Uint16 i_min = 0;
double D_max = 99; //The control effort is in this case the duty cycle, which in theory can only be in between 0 and 100 %
double D_min = 1;
double D1 = 0; //The control effort is in this case the duty cycle in percent
double D2 = 0;
double D3 = 0;
double Up_1 = 0; //Needed for intermediate results in the PI controller
double Ui_1 = 0;
double Ui_1_old = 0;
double Up_2 = 0;
double Ui_2 = 0;
double Ui_2_old = 0;
double Up_3 = 0;
double Ui_3 = 0;
double Ui_3_old = 0;
double Ts_i = 1/10000; //Period of the controller in seconds
Uint16 Ts_i_CLKS = 1000; //Period expressed as a number of clock cycles -> will be loaded to ePWM that calls the interrupt
//PI voltage controller parameters
double Kp_v = 10;
double Ki_v = 100;
double v_max = 120;
double v_min = 10;
double Ui_v_old = 0;
double Ui_v = 0;
double Up_v = 0;
double v_meas = 0; //output voltage!!
double v_ref = 0;
Uint16 Ts_v = 1000;
//MPPT variables
double V_old = 0;
double V_new = 0;
double dV = 0;
double I_old = 0;
double I_new = 0;
double dI = 0;
double P_old = 0;
double P_new = 0;
double dP = 0;
double I_step = 0.1;
double I_PV_meas = 0;
double V_PV_meas = 0;
double I_ref = 0;
double I_ref_old = 0;
//The timer period determines the frequency of each PWM channel
int EPWM1_TIMER_TBPRD = 500; //250 should be 200kHz - 500 should be 100 kHz
int EPWM2_TIMER_TBPRD = 500;
int EPWM3_TIMER_TBPRD = 500;
//HRPWM variables
Uint16 UpdateFine;
Uint16 PeriodFine;
Uint16 status;
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(0) function.
//Duty cycles for the three different legs
double DELTA_1A = 30;
double DELTA_2A = 30;
double DELTA_3A = 30;
//Set initial compare values for the EPWM registers
int SET_EPWM1_CMPA = 100;
int SET_EPWM2_CMPA = 100;
int SET_EPWM3_CMPA = 100;
int PHASE_1A = 0; //(int)(2000*0);
int PHASE_2A = 0; //667; //(int)(2000*(1/3));
int PHASE_3A = 0; //1334; //(int)(2000*(2/3));
//The driver also has an enable pin that will need to be connected with one of the GPIO pins of the µC
Uint16 ENABLE_DRIVER_1 = 0;
Uint16 PIN_EN_DR1 = 86; // GPIO34
Uint16 ENABLE_DRIVER_2 = 0;
Uint16 PIN_EN_DR2 = 90; //GPIO44
Uint16 ENABLE_DRIVER_3 = 0;
Uint16 PIN_EN_DR3 = 94; //GPIO46
Uint16 counter = 0;
Uint16 AdcaResults[RESULTS_BUFFER_SIZE];
Uint16 resultsIndex;
//Create the arrays that contain the measurement results
//double I_1[RESULTS_BUFFER_SIZE];
//double I_2[RESULTS_BUFFER_SIZE];
//double I_3[RESULTS_BUFFER_SIZE];
double I_PV[RESULTS_BUFFER_SIZE];
double V_PV[RESULTS_BUFFER_SIZE];
double V_OUT[RESULTS_BUFFER_SIZE];
double TEMP_1[RESULTS_BUFFER_SIZE];
double TEMP_2[RESULTS_BUFFER_SIZE];
//volatile Uint16 bufferFull;
//The ADC inputs need to be converted to real values
double I_CONV_RATIO = 3.3/4096*20/1.15*2;
double V_CONV_RATIO = 0.5; //Correct value still needs to be calculated
// Function Prototypes
void InitEPwm1(void);
void InitEPwm2(void);
void InitEPwm3(void);
void ConfigureEPWM(void);
void ConfigureADC(void);
void SetupADCEpwm(void);
void Config_ENABLE(void);
double median(int n, double x[]);
//void PID(int ref, ) -> er bestaan geen klasses in C blijkbaar
interrupt void adca1_isr(void); //At the end of conversion
interrupt void epwm4_isr(void); //To call the PI current controller
interrupt void epwm5_isr(void); //To call the PI voltage controller
interrupt void epwm6_isr(void); //To call the MPPT
void CLA_configClaMemory(void);
void CLA_initCpu1Cla1(void);
__interrupt void cla1Isr1();
__interrupt void cla1Isr2();
__interrupt void cla1Isr3();
__interrupt void cla1Isr4();
__interrupt void cla1Isr5();
__interrupt void cla1Isr6();
__interrupt void cla1Isr7();
__interrupt void cla1Isr8();
// Main
void main(void)
{
PHASE_1A = 0; //(int)(2000*0);
PHASE_2A = (int)(EPWM1_TIMER_TBPRD*2/3);
PHASE_3A = (int)(EPWM1_TIMER_TBPRD*2/3);
InitSysCtrl();
InitGpio();
InitEPwm1Gpio();
InitEPwm2Gpio();
InitEPwm3Gpio();
//Configure the enable pins for the drivers
Config_ENABLE();
//GPIO_SetupPinMux(47, GPIO_MUX_CPU1, 0);
//GPIO_SetupPinOptions(47, GPIO_OUTPUT, GPIO_PUSHPULL);
DINT; //Disable all interrupts, the Interrupt Global Mask bit INTM from ST1 register
// Initialize system variables, enable HRPWM
//UpdateFine = 1;
//PeriodFine = 0;
//status = SFO_INCOMPLETE;
//while(status == SFO_INCOMPLETE) // Call until complete
//{
// status = SFO();
// if (status == SFO_ERROR)
// {
// error(); // SFO function returns 2 if an error occurs & # of MEP
// } // steps/coarse step exceeds maximum of 255.
//}
InitPieCtrl(); // De PIE -> alles wat met interrupts te maken heeft, moet in het begin gewoon geinitialiseerd worden
IER = 0x0000; // Interrupt Enable Register
IFR = 0x0000; //Interrupt Flag Register
InitPieVectTable(); //Can be found in F2837xD_PieVect.c - Here also the PIE gets enabled (ENPIE =1)
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1 - De & heeft te maken met een pointer fzo Is dit hier the ISR vector??
EDIS; // This is needed to disable write to EALLOW protected registers
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //enable the interrupt in the PIE table
// Enable global Interrupts and higher priority real-time debug events:
IER |= 0x01; //M_INT1; // Interrupt enable register, enable INT1
EINT; // Enable Global interrupt INTM (enable all interrupts)
ERTM; // Enable Global realtime interrupt DBGM
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
// CLA configuration
// Configure the CLA memory spaces first followed by
// the CLA task vectors
//
CLA_configClaMemory();
CLA_initCpu1Cla1();
//Give the PWM channels the correct frequency, dutycycle, phase shift, ...
InitEPwm1();
InitEPwm2();
InitEPwm3();
// Configure the ADC and power it up
ConfigureADC();
// Setup the ADC for ePWM triggered conversions on channel A0
SetupADCEpwm();
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; //why is this for?? First we put it off, then back on..
EDIS;
GpioDataRegs.GPASET.bit.GPIO31 = 1; // This one is connected to delta 3 and MOS3
GpioDataRegs.GPBSET.bit.GPIO34 = 1; // This one is connected to delta 2 and MOS2
GpioDataRegs.GPBSET.bit.GPIO44 = 1; //This one is connected to delta 1 (MOS1)
while(1) // endless loop
{
SET_EPWM1_CMPA = (int)(((100-DELTA_1A)/100)*EPWM1_TIMER_TBPRD-1);
SET_EPWM2_CMPA = (int)(((100-DELTA_2A)/100)*EPWM2_TIMER_TBPRD-1);
SET_EPWM3_CMPA = (int)(((100-DELTA_3A)/100)*EPWM3_TIMER_TBPRD-1);
EPwm1Regs.CMPA.bit.CMPA = SET_EPWM1_CMPA; // Set compare A value -OK
EPwm2Regs.CMPA.bit.CMPA = SET_EPWM2_CMPA; // Set compare A value -OK
EPwm3Regs.CMPA.bit.CMPA = SET_EPWM3_CMPA; // Set compare A value -OK
counter++;
if(counter==2000)
{counter = 0;
//GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; //GPB is voor gpio32-63
//GpioDataRegs.GPBTOGGLE.bit.GPIO44 = 1;
//GpioDataRegs.GPBTOGGLE.bit.GPIO46 = 1;
}
asm(" NOP");
}
}
void InitEPwm1(void)
{
// Setup TBCLK
EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD; // Set timer period 801 TBCLKs - OK, exacte waarde nadien aanpassen
EPwm1Regs.TBPHS.bit.TBPHS = PHASE_1A; // Phase is 0
EPwm1Regs.TBCTR = 0x0000; // Clear counter
// Set Compare values
EPwm1Regs.CMPA.bit.CMPA = SET_EPWM1_CMPA; // Set compare A value
//EPwm1Regs.CMPA.bit.CMPAHR = (1 << 8); // initialize HRPWM extension (<< 8 means the shift to the left operator by 8 bits)
//EPwm1Regs.CMPB.bit.CMPB = EPWM1_MAX_CMPB; // Set Compare B value
// Setup counter mode
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down - why isn't this equak to 01???
EPwm1Regs.TBCTL.bit.PHSEN = 0x00; //EPWM1 = Master -> 0
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT - Default values
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
EPwm1Regs.TBCTL.bit.SYNCOSEL = 0x01;
// Setup shadowing - This is used such that the compare value does not change during a cycle - It is only allowed to change when the counter starts or stops
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
// EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
// EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set actions
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, upcount
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A,
//Setup HRPWM -> voor later, niet zo prioritair
//EPwm1Regs.HRCNFG.all = 0x0;
//Setup ADC - The ePWM module will sent a signal to the ADC module when the counter equals period
//SOCA-> ADC1
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 0x02; // Select SOC on period match!! (010)
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event -
//SOCB -> ADC2
EPwm1Regs.ETSEL.bit.SOCBEN = 1; // Enable SOC on B group
EPwm1Regs.ETSEL.bit.SOCBSEL = 0x02; // Select SOC on period match!! (010)
EPwm1Regs.ETPS.bit.SOCBPRD = 1; // Generate pulse on 1st event -
//EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up
//EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // Clear PWM1B on event B,
// Interrupt where we will change the Compare Values - momenteel niet nodig
//EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
//EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
//EPwm1Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
}
void InitEPwm2(void)
{
//
// Setup TBCLK
//
EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD; // Set timer period 801 TBCLKs
EPwm2Regs.TBPHS.bit.TBPHS = PHASE_2A; //0x0000; // Phase is 0
EPwm2Regs.TBCTR = 0x0000; // Clear counter
//
// Set Compare values
//
EPwm2Regs.CMPA.bit.CMPA = SET_EPWM2_CMPA; // Set compare A value
//EPwm2Regs.CMPB.bit.CMPB = EPWM2_MIN_CMPB; // Set Compare B value
//
// Setup counter mode
//
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
EPwm2Regs.TBCTL.bit.PHSEN = 0x01; //Slave -> 1
EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
EPwm2Regs.TBCTL.bit.SYNCOSEL = 0x01; //-OK
EPwm2Regs.TBCTL.bit.PHSDIR = 0x01;
//
// Setup shadowing
//
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
//EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero
//EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set actions
//
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM2A on event A, up
EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM2A on event B, down
// count
//Setup ADC
EPwm2Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm2Regs.ETSEL.bit.SOCASEL = 0x02; // Select SOC on period match!! (010)
EPwm2Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
//EPwm2Regs.AQCTLB.bit.ZRO = AQ_CLEAR; // Clear PWM2B on zero
//EPwm2Regs.AQCTLB.bit.PRD = AQ_SET; // Set PWM2B on period
//
// Interrupt where we will change the Compare Values
//
//EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
//EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
//EPwm2Regs.ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
}
void InitEPwm3(void)
{
EPwm3Regs.TBPRD = EPWM3_TIMER_TBPRD; // Set timer period
//
// Setup TBCLK
//
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/down and down
EPwm3Regs.TBCTL.bit.PHSEN = 0x01;//TB_DISABLE; // Disable phase loading
EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;
EPwm3Regs.TBCTL.bit.SYNCOSEL = 0x01; //-OK
EPwm3Regs.TBCTL.bit.PHSDIR = 0x01;
EPwm3Regs.TBPHS.bit.TBPHS = PHASE_3A; //0x0000; // Phase is 0
EPwm3Regs.TBCTR = 0x0000; // Clear counter
// Setup shadow register load on ZERO
EPwm3Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
//EPwm3Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm3Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
//EPwm3Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
//
// Set Compare values
//
EPwm3Regs.CMPA.bit.CMPA = SET_EPWM1_CMPA; // Set compare A value
//EPwm3Regs.CMPB.bit.CMPB = EPWM3_MAX_CMPB; // Set Compare B value
//
// Set Actions
//
EPwm3Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM3A on period
EPwm3Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM3A on event B, down
//Setup ADC
EPwm3Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm3Regs.ETSEL.bit.SOCASEL = 0x02; // Select SOC on period match!! (010)
EPwm3Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event // count
//EPwm3Regs.AQCTLB.bit.PRD = AQ_CLEAR; // Clear PWM3A on period
//EPwm3Regs.AQCTLB.bit.CAU = AQ_SET; // Set PWM3A on event A, up
// count
}
void ConfigureADC(void)
{
EALLOW;
//write configurations
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 - heeft dit iets te maken met snelheid fzo??
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //Deze functie dient om de ADC in te stellen en is te vinden in F2837xD_Adc.c
//Set pulse positions to late
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;
//power up the ADC
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
//delay for 1ms to allow ADC time to power up
DELAY_US(1000);
// Now do the same for ADC2
AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 - heeft dit iets te maken met snelheid fzo??
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
DELAY_US(1000);
EDIS;
}
void SetupADCEpwm(void)
{
// Remark: Notice that ADC1 and ADCA are the same! Also: ADC2 = ADCB
//Remark: Remember that SOC0 stores the result in RESULT0, SOC1 -> RESULT1, ... but SOC0/SOC1 is not necessarily coupled to pin A0/A1
// Determine the acquisition window size
Uint16 acqps;
acqps = 10; //hier kunnen we wss mee spelen om resultaten beter uit te filteren??
// Choose all the ADC channels for the different sensors
//Uint16 is an unsigned short datatype - 16bits
Uint16 SENSE_LEM0;
Uint16 SENSE_LEM1;
Uint16 SENSE_LEM2;
Uint16 SENSE_LEM3;
Uint16 SENSE_Vin;
Uint16 SENSE_Vout;
Uint16 SENSE_TEMP1;
Uint16 SENSE_TEMP2;
// Current measurements
SENSE_LEM1 = 0; //Line 1 - pin ADC1-A0 (9)
SENSE_LEM2 = 2; //Line 2 - pin ADC1-A2 (15)
SENSE_LEM3 = 3; //Line 3 - pin ADC1-A3 (17)
SENSE_LEM0 = 4; //Total current - pin ADC1-A4 (21)
// Voltage measurements
SENSE_Vin = 0; //Input voltage (PV panel) - pin ADC2-A0 (12) -> on the second ADC such that we can use simultaneous sampling for the MPPT
SENSE_Vout = 6; //Output voltage - pin ADC1-A6 (23)
// Temperature measurements
SENSE_TEMP1 = 0;
SENSE_TEMP2 = 0;
//Select the channels to convert and end of conversion flag
EALLOW;
//------------------------------
//Current measurement in line 1 - SOC0
//------------------------------
AdcaRegs.ADCSOC0CTL.bit.CHSEL = SENSE_LEM1; //SOC0 will convert pin ADC1A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0x05; //trigger on ePWM1 SOCA, see page 1347/2472 in datasheet for an overview
//------------------------------
//Current measurement in line 2 - SOC1
//------------------------------
AdcaRegs.ADCSOC1CTL.bit.CHSEL = SENSE_LEM2; //SOC1 will convert pin ADC1A2
AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps;
AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 0x07; //trigger on ePWM2 ADCSOCA
//------------------------------
//Current measurement in line 3 - SOC2
//------------------------------
AdcaRegs.ADCSOC2CTL.bit.CHSEL = SENSE_LEM3; //SOC2 will convert pin ADC1A3
AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps;
AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 0x09; //trigger on ePWM3 ADCSOCA
//------------------------------
//PV panel current and voltage measurement - SOC3 (see page 1301/2472)
//------------------------------
AdcaRegs.ADCSOC3CTL.bit.CHSEL = SENSE_LEM0; //SOC3 will convert pin ADC1A4
AdcaRegs.ADCSOC3CTL.bit.ACQPS = acqps;
AdcaRegs.ADCSOC3CTL.bit.TRIGSEL = 0x06; //trigger on ePWM1 ADCSOCB
AdcbRegs.ADCSOC3CTL.bit.CHSEL = SENSE_Vin; //SOC3 will convert pin ADC2A0 -> This result is stored in AdcbResultRegs.ADCRESULT3
AdcbRegs.ADCSOC3CTL.bit.ACQPS = acqps;
AdcbRegs.ADCSOC3CTL.bit.TRIGSEL = 0x06; //trigger on ePWM1 ADCSOCB
//At the end of conversion (EOC), an interrupt can be generated, e.g. for the control law or for copying the ADCresults to another array
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0x02; //EOC2 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; //enable ADCINT1
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared - a 1 clears the flag bit
EDIS;
}
void Config_ENABLE(void)
{
//GPIO 31 -> enable driver 1 , pin 82
GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);
//GPIO 34 -> enable driver 2 , pin 86
GPIO_SetupPinMux(34, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(34, GPIO_OUTPUT, GPIO_PUSHPULL);
//GPIO 44 -> enable driver 3 , pin 90
GPIO_SetupPinMux(44, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(44, GPIO_OUTPUT, GPIO_PUSHPULL);
}
double median(int n, double x[])
{
// the following two loops sort the array x in ascending order
for(a=0; a<n-1; a++) {
for(b=a+1; b<n; b++) {
if(x[b] < x[a]) {
// swap elements
temp = x[a];
x[a] = x[b];
x[b] = temp;
}
}
}
if(n%2==0) {
// if there is an even number of elements, return mean of the two elements in the middle
return((x[n/2] + x[n/2 - 1]) / 2.0);
} else {
// else return the element in the middle
return x[n/2];
}
}
interrupt void adca1_isr(void)
{ //This is interrupt INT1 from ADC1
//GpioDataRegs.GPACLEAR.bit.GPIO31 = 1;
//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
//First update resultsIndex
if(resultsIndex > (RESULTS_BUFFER_SIZE-1))
{
resultsIndex = 0;
}
else {resultsIndex++;}
//The results registers(0-4095) must be converted to a real value by applying a level shift and a conversion ratio
//Notice that we first cast the Uint16 to a normal (signed) int because the result is otherwise specified as a Uint16 which gives errors
I_3[resultsIndex] = ((int)AdcaResultRegs.ADCRESULT0 - OFFSET)*I_CONV_RATIO;
I_2[resultsIndex] = ((int)AdcaResultRegs.ADCRESULT1 - OFFSET)*I_CONV_RATIO;
I_1[resultsIndex] = ((int)AdcaResultRegs.ADCRESULT2 - OFFSET)*I_CONV_RATIO;
//calculate mean
//for(i=0;i<10;i++)
//{sum+=I_1[i];}
//i_1 = sum/10;
//sum = 0;
//for(i=0;i<10;i++)
//{sum+=I_2[i];}
//i_2 = sum/10;
//sum = 0;
//for(i=0;i<10;i++)
//{sum+=I_3[i];}
//i_3 = sum/10;
//sum = 0;
//calculate median
//I_1_temp[] = I_1[];
i_3_median = (median(10,I_3)-2.5)*0.4405;
i_2_median = (median(10,I_2)-1.531)*0.4915;
i_1_median = (median(10,I_1)-2.563)*0.452;
I_PV[resultsIndex] = ((int)AdcaResultRegs.ADCRESULT3 - OFFSET)*I_CONV_RATIO; // For the moment we assume that all the conversions are the same but this might not be the case if different sensors are used
V_PV[resultsIndex] = ((int)AdcbResultRegs.ADCRESULT3 - OFFSET)*V_CONV_RATIO;
//GpioDataRegs.GPATOGGLE.bit.GPIO31 = 1;
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Hoe komt het dat deze op het einde van een interrupt routine staat en niet in het begin??
}
interrupt void adca2_isr(void)
{ //This is interrupt INT2 from ADC1
}
//Current controller
interrupt void epwm4_isr(void)
{ // This interrupt will update the duty cycles via the PI current control
//First be sure that the reference current is in the limits of what the board is designed for
if(i1_ref > i_max) //Maximum constraint
{i1_ref = i_max;}
if(i1_ref < i_min) //Minimum constraint
{i1_ref = i_min;}
if(i2_ref > i_max)
{i2_ref = i_max;}
if(i2_ref < i_min)
{i2_ref = i_min;}
if(i3_ref > i_max)
{i3_ref = i_max;}
if(i3_ref < i_min)
{i3_ref = i_min;}
//Now calculate the output for all three PI current loops
//First the proportional part
Up_1 = Kp_i*(i1 - i1_ref);
Up_2 = Kp_i*(i2 - i2_ref);
Up_3 = Kp_i*(i3 - i3_ref);
//Then the integral part
Ui_1 = Ki_i*Ts_i*(i1 - i1_ref) + Ui_1_old;
Ui_2 = Ki_i*Ts_i*(i2 - i2_ref) + Ui_2_old;
Ui_3 = Ki_i*Ts_i*(i3 - i3_ref) + Ui_3_old;
//Now combine them to get the total control effort
D1 = Up_1 + Ui_1;
D2 = Up_2 + Ui_2;
D3 = Up_3 + Ui_3;
//Now be sure that the required duty cycle is in between 0 and 100%
if(D1 > D_max)
{D1 = D_max;}
if(D1 < D_min)
{D1 = D_min;}
if(D2 > D_max)
{D2 = D_max;}
if(D2 < D_min)
{D2 = D_min;}
if(D3 > D_max)
{D3 = D_max;}
if(D3 < D_min)
{D3 = D_min;}
//We also want to include integrator antiwindup
//This means that we should limit the integrator memory
Ui_1_old = D1 - Up_1;
Ui_2_old = D1 - Up_2;
Ui_3_old = D1 - Up_3;
//Now set the duty cycles to the desired values by writing the correct value to their registers
}
//Voltage controller
interrupt void epwm5_isr(void)
{ // This interrupt will update the reference value for the currents
//First be sure that the reference current is in the limits of what the board is designed for
if(v_ref > v_max) //Maximum constraint
{v_ref = v_max;}
if(v_ref < v_min) //Minimum constraint
{v_ref = v_min;}
//Proportional term
Up_v = Kp_v*(v_meas - v_ref);
//Integral term
Ui_v = Ki_v*Ts_v*(v_meas - v_ref) + Ui_v_old;
//Now combine them to get the total control effort - In this case the current is the output!!
i1_ref = Up_v + Ui_v;
//Now be sure that the required current lies in between the limits (limit the output)
if(i1_ref > i_max) //Maximum constraint
{i1_ref = i_max;}
if(i1_ref < i_min) //Minimum constraint
{i1_ref = i_min;}
//Give the same reference to the two other phases
i2_ref = i1_ref;
i3_ref = i1_ref;
//We also want to include integrator antiwindup
//This means that we should limit the integrator memory
Ui_v_old = i1_ref - Up_v;
//Now set the duty cycles to the desired values by writing the correct value to their registers
//Here we don't really need to call anything anymore as the duty cycle will be updated by the current controller
}
//Maximum Power Point Tracker (MPPT) - Perturb & Observe
//Deze interrupt zou eigenlijk geroepen moeten worden aan het eind van een ADC conversie van de PV spanning en stroom, dus mss onder adc2 plaatsen?
interrupt void epwm6_isr(void)
{ V_new = V_PV_meas;
I_new = I_PV_meas;
P_new = V_new*I_new;
dV = V_new - V_old;
dI = I_new - I_old;
dP = P_new - P_old;
if(dP > 0)
{
if(dV < 0)
{I_ref = I_ref_old + I_step;}
else
{I_ref = I_ref_old - I_step;}
}
else
{
if(dV < 0)
{I_ref = I_ref_old - I_step;}
else
{I_ref = I_ref_old + I_step;}
}
//Hier nog eventueel stroomlimieten toevoegen
V_old = V_new;
I_old = I_new;
P_old = P_new;
I_ref_old = I_ref;
}
//
// End of file
//
/*
* cla_shared.h
*
* Created on: 15-jun.-2017
* Author: sravyts
*/
//De twee eerste lijnen hier is iets dat blijkbaar standaard wordt gedaan bij het maken van een header file
#ifndef CLA_SHARED_H_
#define CLA_SHARED_H_
//*****************************************************************************
// includes
//*****************************************************************************
#include "F2837xD_Cla_typedefs.h"
#include "F2837xD_Cla_defines.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
//*****************************************************************************
// defines
//*****************************************************************************
//*****************************************************************************
// typedefs
//*****************************************************************************
//*****************************************************************************
// globals
//*****************************************************************************
//Dus hier gaan we straks de variabelen per taak moeten toevoegen
//Task 1 (C) Variables
extern double i_1_median;
extern double i_2_median;
extern double i_3_median;
extern double I_1[];
extern double I_2[];
extern double I_3[];
//Task 2 (C) Variables
//Task 3 (C) Variables
//Task 4 (C) Variables
//Task 5 (C) Variables
//Task 6 (C) Variables
//Task 7 (C) Variables
//Task 8 (C) Variables
//Common (C) Variables
//extern int32 i;
//*****************************************************************************
// function prototypes
//*****************************************************************************
// The following are symbols defined in the CLA assembly code
// Including them in the shared header file makes them
// .global and the main CPU can make use of them.
//CLA C Tasks
__interrupt void Cla1Task1();
__interrupt void Cla1Task2();
__interrupt void Cla1Task3();
__interrupt void Cla1Task4();
__interrupt void Cla1Task5();
__interrupt void Cla1Task6();
__interrupt void Cla1Task7();
__interrupt void Cla1Task8();
#ifdef __cplusplus
}
#endif // extern "C"
#endif /* CLA_SHARED_H_ */
//Simon Ravyts
//In deze file staan specifiek de taken die de CLA zal uitvoeren
//Task 1: Mediaan berekenen van de gemeten stromen
//Task 2 : PI current controller
//Nadien ook nog spanningscontrole en/of MPPT
// Group: C2000
// Target Family: F2837xD
//
//*****************************************************************************
// includes
//*****************************************************************************
#include "cla_shared.h"
//*****************************************************************************
// defines
//*****************************************************************************
//*****************************************************************************
// globals
//*****************************************************************************
//*****************************************************************************
// function definitions
//*****************************************************************************
//Task 1 : Calculate median of the currents
//We gevenb hem een vector met meetwaarden en we willen per vector één waarde terugkrijgen
//The input variables are the three vectors with the current I_1,I_2,I_3
//The output variables are the medians
__interrupt void Cla1Task1 ( void )
{
i_3_median = (median(10,I_3)-2.5)*0.4405;
i_2_median = (median(10,I_2)-1.531)*0.4915;
i_1_median = (median(10,I_1)-2.563)*0.452;
}
//Task 2 : Vector min
__interrupt void Cla1Task2 ( void )
{
}
//Task 3 : Vector min
__interrupt void Cla1Task3 ( void )
{
}
__interrupt void Cla1Task4 ( void )
{
}
__interrupt void Cla1Task5 ( void )
{
}
__interrupt void Cla1Task6 ( void )
{
}
__interrupt void Cla1Task7 ( void )
{
}
__interrupt void Cla1Task8 ( void )
{
}
// End of file
Below you have the console log:
**** Build of configuration CPU1_RAM for project epwm_updown_aq_cpu01 ****
"C:\\Program Files\\ccsv6\\utils\\bin\\gmake" -k all
'Building target: epwm_updown_aq_cpu01.out'
'Invoking: C2000 Linker'
"C:/Program Files/ccsv6/tools/compiler/c2000_15.12.3.LTS/bin/cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -g --define=CPU1 --diag_warning=225 --display_error_number --diag_suppress=10063 -z -m"epwm_updown_aq_cpu01.map" --stack_size=0x100 --warn_sections -i"C:/Program Files/ccsv6/tools/compiler/c2000_15.12.3.LTS/lib" -i"C:/Program Files/ccsv6/tools/compiler/c2000_15.12.3.LTS/include" -i"C:/Program Files/controlSUITE/device_support/F2837xD/v200/F2837xD_common/cmd" -i"C:/Program Files/controlSUITE/device_support/F2837xD/v200/F2837xD_headers/cmd" --reread_libs --display_error_number --xml_link_info="epwm_updown_aq_cpu01_linkInfo.xml" --entry_point=code_start --rom_model -o "epwm_updown_aq_cpu01.out" "./F2837xD_Adc.obj" "./F2837xD_CodeStartBranch.obj" "./F2837xD_DefaultISR.obj" "./F2837xD_EPwm.obj" "./F2837xD_GlobalVariableDefs.obj" "./F2837xD_Gpio.obj" "./F2837xD_Ipc.obj" "./F2837xD_PieCtrl.obj" "./F2837xD_PieVect.obj" "./F2837xD_SysCtrl.obj" "./F2837xD_usDelay.obj" "./cla_taks.obj" "./epwm_updown_aq_cpu01.obj" -lrts2800_fpu32.lib -l2837xD_RAM_lnk_cpu1.cmd -lF2837xD_Headers_nonBIOS_cpu1.cmd -llibc.a
<Linking>
warning #10247-D: creating output section "Cla1Prog" without a SECTIONS
specification
warning #10247-D: creating output section "Cla1ToCpuMsgRAM" without a SECTIONS
specification
warning #10247-D: creating output section "CpuToCla1MsgRAM" without a SECTIONS
specification
undefined first referenced
symbol in file
--------- ----------------
_CLA_configClaMemory ./epwm_updown_aq_cpu01.obj
_CLA_initCpu1Cla1 ./epwm_updown_aq_cpu01.obj
error #10234-D: unresolved symbols remain
error #10010: errors encountered during linking; "epwm_updown_aq_cpu01.out" not
built
gmake: *** [epwm_updown_aq_cpu01.out] Error 1
gmake: Target 'all' not remade because of errors.
>> Compilation failure
makefile:148: recipe for target 'epwm_updown_aq_cpu01.out' failed
**** Build Finished ****