Other Parts Discussed in Thread: SFRA, CONTROLSUITE
Hi there,
what is the meaning of the argument of the function SFRA_F_INJECT()?
e.g. SFRA_F_INJECT(Duty_pu_DC) what is the meaning of Duty_pu_DC?
Thanks so much
Leo
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Other Parts Discussed in Thread: SFRA, CONTROLSUITE
Hi there,
what is the meaning of the argument of the function SFRA_F_INJECT()?
e.g. SFRA_F_INJECT(Duty_pu_DC) what is the meaning of Duty_pu_DC?
Thanks so much
Leo
Leo,
SFRA is based on small signal injection into the duty cycle and checking the response on the feedback to determine the plant response.
the INJECT function argument is the DC Point of the duty
Return of the function argument is DC Point plus the small signal injection
1. yes you can orogram it like that, the reason why i recommend using a variable is that it gives you flexibility to change without having to recompile the code, that's why i recommend
Duty_pu=SFRA_F_INJECT(Duty_pu_DC);
but what you have understood is correct.
2. If the PWM is programmed in UP Count mode, BUCK_PWM_Period = EPwm1Regs.TBPRD
the example you are referring to is UP Count, so your understanding is correct
Hi Manish,
Thanks for your help. I have finally managed to 'run' the SFRA, but I believe I am doing something incorrectly in the software. I have a buck converter, and I am trying to use the SFRA in open loop, around a steady state duty cycle of 0.5, my switching frequency is 200kHz, same as the interrupt frequency. In the software below the SFRA is always on (which is what I intended to do, but perhaps there are scaling errors, or other errors which I need help to find).
I report my main.c program below, with the parts I think are relevant for the correct config of the SFRA.
From the main.c:
...
#include "math.h"
...
#define MATH_TYPE 1 //FLOAT_MATH
#include "SFRA_F_Include.h"
...
define SFRA_ISR_FREQ 200000
#define SFRA_FREQ_START 1000
#define SFRA_FREQ_LENGTH 100
//SFRA step Multiply = 10^(1/No of steps per decade(40))
#define FREQ_STEP_MULTIPLY (float)1.0233//1.059253
SFRA_F SFRA1;
//extern to access tables in ROM
extern long FPUsinTable[];
float32 Plant_MagVect[SFRA_FREQ_LENGTH];
float32 Plant_PhaseVect[SFRA_FREQ_LENGTH];
float32 OL_MagVect[SFRA_FREQ_LENGTH];
float32 OL_PhaseVect[SFRA_FREQ_LENGTH];
float32 FreqVect[SFRA_FREQ_LENGTH];
int SFRA_flag=0;
float Duty_pu;
float Vpv_read;
...
// SFRA initialization
//SFRA Object Initialization
//Specify the injection amplitude
SFRA1.amplitude=0.1;
//Specify the length of SFRA
SFRA1.Vec_Length=SFRA_FREQ_LENGTH;
//Specify the SFRA ISR Frequency
SFRA1.ISR_Freq=SFRA_ISR_FREQ;
//Specify the Start Frequency of the SFRA analysis
SFRA1.Freq_Start=SFRA_FREQ_START;
//Specify the Frequency Step
SFRA1.Freq_Step=FREQ_STEP_MULTIPLY;
//Assign array location to Pointers in the SFRA object
SFRA1.FreqVect=FreqVect;
SFRA1.GH_MagVect=OL_MagVect;
SFRA1.GH_PhaseVect=OL_PhaseVect;
SFRA1.H_MagVect=Plant_MagVect;
SFRA_F_INIT(&SFRA1);
...
//***************************************************************************
// Infinite loop
//***************************************************************************
while (1) {
//*************** SFRA ***************
if(SFRA_flag == 1) {
SFRA_F_BACKGROUND(&SFRA1);
SFRA1.start =1; // PS note I run the SFRA continuously
}
} // end of while(1)
....
interrupt void adcb1_isr(void) {
...
resultsbIndex = resultsbIndex + 1;
v_pv[resultsbIndex] = (double) (AdcbResultRegs.ADCRESULT4) * (-0.03953) + 74.91;
//Read ADC and computer Fbk Value
Vpv_read=(float32)v_pv[resultsbIndex]/4096.0;
//Add SFRA injection into the duty cycle for the open loop converter
Duty_pu=SFRA_F_INJECT(0.5);
//Update PWM value
EPwm6Regs.CMPA.bit.CMPA = ( ((PWM.PR)) * Duty_pu ); // Set compare A value to a certain TBPRD counts
EPwm6Regs.CMPB.bit.CMPB = (1.5 * PWM.PR); // condition never met -> PWM 6B always high (boost HO high, LO low)
SFRA_F_COLLECT(&Duty_pu,&Vpv_read);
...
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
interrupt_exit++;
}
it is an adc interrupt triggered when the PWM CTR equals PRD. Below are other settings that may be relevant:
From ePWM6 settings:
...
//v2 ADC conversion related to switching EPWM6
EPwm6Regs.ETSEL.bit.SOCAEN = 1; // enable SOC on A group
EPwm6Regs.ETSEL.bit.SOCASEL = 2; // EPWM6 SOCA Pulse Generated TBCTR=TBPRD //the ADC synch'd by the PWM
EPwm6Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
...
From the ADC setup: (I am using ADC B-4, triggered by ePWM6)
...
AdcbRegs.ADCSOC4CTL.bit.CHSEL = 4;
AdcbRegs.ADCSOC4CTL.bit.ACQPS = acqps;
AdcbRegs.ADCSOC4CTL.bit.TRIGSEL = 15;
...
1) Now when the SFRA is run, all elements of the Plant_PhaseVect are 0.0 and never change, while the elements of the Plant_MagVect vector change and they are about -100 (a value that I did not expect).
2) Also, when I debug the main.c I get the following warning (I am not sure if I need to worry about)
It also seems like that the switching frequency of the converter is changing: the pink waveform is the duty cycle of the converter, changing as the SFRA sweep moves to different frequencies, for different times. The yellow waveform is the voltage (the one I am trying to use in my SFRA)
Any help you could provide would be great.
Thank you so much again
Leo
Few issues
1.
if(SFRA_flag == 1) {
SFRA_F_BACKGROUND(&SFRA1);
SFRA1.start =1; // PS note I run the SFRA continuously
}
this may interfere with how SFRA works,
if you want to wait for the sweep to end and immediately start another sweep, i recommend the below
if(SFRA_flag == 1) {
SFRA_F_BACKGROUND(&SFRA1);
if(SFRA1.state==0)
SFRA1.start=1;
}
2.
If it is a buck example i highly recommend you review the code here
C:\ti\controlSUITE\development_kits\BOOSTXL_BUCKCONV\v1_01_00_00\Buck_VMC_F2837xS
C:\ti\controlSUITE\libs\app_libs\SFRA\v1_10_00_00\examples\DPSWrkShpKit_SFRA_F28069
and compare your code against them,
For example the below is going to take a long time , you should cast to float which is single precision floating point..
also review the code above to understand scaling, i recommend doing things in PU format i.e. ADC ins 0-1 range , cntl output in 0-1 range etc the way it is in above examples.
v_pv[resultsbIndex] = (float) (AdcbResultRegs.ADCRESULT4) * (-0.03953) + 74.91;