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.

F28027 PI controller

Other Parts Discussed in Thread: CONTROLSUITE

Hello Guys,

I am a newbie to Piccolo and i am currently designing a switching converter for an university project, i have the following adc routine running at 50KSps. I am trying to implement a simple PI controller inside the ADC routine (i am not sure this is correct but based on reading online materials i think is somewhat done).

My problem is my integrator output saturates and doesnt increment  over period of time (actual output of Integrator is sum of past errors) until i declare the variables to be "static". But when i declare the variables to be static my loop samples is reduced to 10KSps. The following is the ADC routine in i have to declare variables in_A and k_5 as static but significantly loosing the loop performance. 

Is there any way to design a simple PI controller using F28027 or any example i can refer ? Please kindly help thanks a lot in advance...

interrupt void adc_isr(void)
{ float err_5, A_5,B_5,v_5,Vpi_5=0.0; static float in_A=0, k_5=0.0; 

GPIO_toggle(myGpio, GPIO_Number_1);
//discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0
Voltage1[ConversionCount] =ADC_readResult(myAdc, ADC_ResultNumber_1);


err_5=1.25-3.3*(Voltage1[ConversionCount])/4096;
//if(ConversionCount>1)
A_5 = err_5 * 0.4; //proportional error

/* integrator

B_5 = err_5 * 727.27;
v_5 = k_5 + 0.5/50000 * (B_5 + in_A); //in_A and k_5 has to be declared static 
k_5 = v_5;
in_A = B_5;

*/
Vpi_5=v_5+A_5;

  • Srinivasan,

    I think your problem is likely to be because you are emulating floating-point on a fixed-point machine.  You don't say which clock speed F28027 part you have, but at 50ksps you probably only have 1,000 or so clock cycles per interrupt.  Emulating floating-point will consume a few hundred, which is why your sample rate drops - the controller can't keep up.  It probably accounts for the numerical issues you're having too.

    If you want to stay with the F28027 and codeyour own PI controller, I strongly recommend doing it using IQ math.  You can find more information about the IQ math library in control suite, and there is a PI regulator (pi_reg3.h) built using it in the DMC motor library.  If you have controlSUITE installed in the default location, you can find this at:

    C:\ti\controlSUITE\libs\app_libs\motor_control\math_blocks\v4.3

    If you want to move to a newer floating-point device, such as F2806x, there is a digital controller library at:

    C:\ti\controlSUITE\libs\control\DCL\v1_00_00_00

    Regards,

    Richard

  • Dear Richard,

    Thanks for your quick reply, i also tried IQ math lib and the results are at 8 KSps i am clocking dsp at max of 60 MHz. I'll try to implement PI regulator in the motor library and keep you updated. So if this is a constraint on the device how is it possible to design a PID control or PI with high sampling rate (not sure with this device) ? Am i missing something here.....

    And my loop speed reduced only when i use "Static float" type operands inside the routine. Can you please explain me how "Static float or int" reduces the loop speed? I have seen the same with global and arrays (both global and local) thanks!!!

  • Srinivisan,

    A basic PI controller such as the one in DMC library should only consume around 40 CPU cycles or so.  If the device were doing nothing else, you should be able to run it at around 1MSPS on this platform.  

    Therefore I think there must be something going on which isn't obvious from the code.  If you can reduce your CCS project to a minimal size and post it here I'll be glad to take a look.

    Regards,

    Richard

  • Hello Richard,

    Thanks a lot for your help and suggestions. Here is my code

    //Global variables

    uint16_t ConversionCount;
    short int Voltage1[10];// array to store sampled adc values


    ADC_Handle myAdc;
    CLK_Handle myClk;
    FLASH_Handle myFlash;
    GPIO_Handle myGpio;
    PIE_Handle myPie;
    SCI_Handle mySci;
    PWM_Handle myPwm, myPwm2;

    void main()
    {

    CPU_Handle myCpu;
    PLL_Handle myPll;
    WDOG_Handle myWDog;

    // Initialize all the handles needed for this application
    myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
    myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
    myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
    myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
    myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
    myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
    myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
    mySci = SCI_init((void *)SCIA_BASE_ADDR, sizeof(SCI_Obj));
    myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
    myPwm = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
    myPwm2 = PWM_init((void *)PWM_ePWM2_BASE_ADDR, sizeof(PWM_Obj));

    // Perform basic system initialization
    WDOG_disable(myWDog); //disable watch dog
    CLK_enableAdcClock(myClk); //enable adc clock
    (*Device_cal)();

    //Select the internal oscillator 1 as the clock source
    CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

    // Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
    PLL_setup(myPll, PLL_Multiplier_12, PLL_DivideSelect_ClkIn_by_2);

    // Disable the PIE and all interrupts
    PIE_disable(myPie);
    PIE_disableAllInts(myPie);
    CPU_disableGlobalInts(myCpu);
    CPU_clearIntFlags(myCpu);

    // If running from flash copy RAM only functions to RAM
    #ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
    #endif

    // Initalize GPIO
    // Enable XCLOCKOUT to allow monitoring of oscillator 1
    GPIO_setMode(myGpio, GPIO_Number_18, GPIO_18_Mode_XCLKOUT);
    CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_1);

    // Setup a debug vector table and enable the PIE
    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);
    // Register interrupt handlers in the PIE vector table
    PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr);

    // Initialize the ADC
    ADC_enableBandGap(myAdc);
    ADC_enableRefBuffers(myAdc);
    ADC_powerUp(myAdc);
    ADC_enable(myAdc);
    ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);
    // Enable ADCINT1 in PIE
    PIE_enableAdcInt(myPie, ADC_IntNumber_1);
    // Enable CPU Interrupt 1
    CPU_enableInt(myCpu, CPU_IntNumber_10);
    // Enable Global interrupt INTM
    CPU_enableGlobalInts(myCpu);
    // Enable Global realtime interrupt DBGM
    CPU_enableDebugInt(myCpu);

    ConversionCount = 0;

    // Configure GPIO 1 and 0 as output
    //GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
    GPIO_setMode(myGpio, GPIO_Number_1, GPIO_0_Mode_GeneralPurpose); //outputing the adc soc pwm on gpio 0
    GPIO_setMode(myGpio, GPIO_Number_19, GPIO_1_Mode_GeneralPurpose); //toggling gpio 1 to measure the adc routine speed

    GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Output);
    GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Output);

    GPIO_setPullUp(myGpio, GPIO_Number_0, GPIO_PullUp_Disable);
    GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_EPWM1A);

    // Configure ADC
    //Note: Channel ADCINA4 will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata
    ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior); //ADCINT1 trips after AdcResults latch
    ADC_enableInt(myAdc, ADC_IntNumber_1); //Enabled ADCINT1
    ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag); //Disable ADCINT1 Continuous mode
    ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC3); //setup EOC2 to trigger ADCINT1 to fire
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4); //set SOC0 channel select to ADCINA4
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A7); //set SOC1 channel select to ADCINA7
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_2, ADC_SocChanNumber_A3); //set SOC2 channel select to ADCINA3
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_3, ADC_SocChanNumber_A1); //set SOC3 channel select to ADCINA1

    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_2, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC2 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_3, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC2 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2

    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles); //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_14_cycles); //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_2, ADC_SocSampleWindow_14_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_3, ADC_SocSampleWindow_14_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)

    CLK_disableTbClockSync(myClk);

    // Enable PWM clock
    CLK_enablePwmClock(myClk, PWM_Number_1);

    // Set actions
    PWM_setActionQual_Zero_PwmA(myPwm, PWM_ActionQual_Set); // Set PWM1A on Zero
    PWM_setActionQual_CntUp_CmpA_PwmA(myPwm, PWM_ActionQual_Clear); // Clear PWM1A on event A, up count

    // Setup PWM
    PWM_enableSocAPulse(myPwm); // Enable SOC on A group
    PWM_setSocAPulseSrc(myPwm, PWM_SocPulseSrc_CounterEqualCmpAIncr); // Select SOC from from CPMA on upcount PWM_SocPulseSrc_CounterEqualCmpAIncr
    PWM_setSocAPeriod(myPwm, PWM_SocPeriod_FirstEvent); // Generate pulse on 1st event
    PWM_setCmpA(myPwm, 750/2); //750 to produce 50Khz sampling

    PWM_setPeriod(myPwm, 750); // Set period for ePWM1
    PWM_setCounterMode(myPwm, PWM_CounterMode_Up); // count up and start
    PWM_setHighSpeedClkDiv(myPwm, PWM_HspClkDiv_by_1); // Clock ratio to SYSCLKOUT
    PWM_setClkDiv(myPwm, PWM_ClkDiv_by_1);

    // FLASH_setup(myFlash);

    CLK_enableTbClockSync(myClk);

    while(1)
    {}



    }

    interrupt void adc_isr(void)
    {float err_5, A_5,B_5,v_5,Vpi_5=0.0; //variables for pi controller
    static float in_A=0 ,k_5=0.0; //variables for integrator
    GPIO_toggle(myGpio, GPIO_Number_1); //toggles at 5.75 Khz with the pi controller and 25Khz (half of adc soc pwm) without the pi controller
    Voltage1[ConversionCount] =ADC_readResult(myAdc, ADC_ResultNumber_1);

    err_5=1.25-3.3*(Voltage1[ConversionCount])/4096; //error mesaurement
    //if(ConversionCount>1)
    A_5 = err_5 * 0.4; //proportional term
    B_5 = err_5 * 727.27;
    {
    v_5 = k_5 + 0.5/50000 * (B_5 + in_A); //integral term
    k_5 = v_5; //integrator output increases only when in_A and k_5 are declared as static !!!
    in_A = B_5;
    }
    Vpi_5=A_5 +v_5; //output of pi
    if(Vpi_5>0)
    {
    }
    // If 10 conversions have been logged, start over
    if(ConversionCount == 10)
    {
    ConversionCount = 0;
    }
    else ConversionCount++;

    // Clear ADCINT1 flag reinitialize for next SOC
    ADC_clearIntFlag(myAdc, ADC_IntNumber_1);
    // Acknowledge interrupt to PIE
    PIE_clearInt(myPie, PIE_GroupNumber_10);

    return;
    }


    Please kindly help me !!! I am toggling gpio 1 in the adc routine and observing the toggle rate using dso i observe this
    declaring local variables inside the routine gives me 25 Khz (50 Khz ) the actual sampling
    using global or static variables gives me 4.17Khz (10 Khz) 1-5th the sampling rate
    using an array both global and loca gives me 4.17 Khz (8 Khz) the sampling rate
    I am really confused my biggest question is it a crime to use global variables in the routine ? also how can i design an integrator if i cant store the past value ?????????
  • Srinivisan,

    I'm going to need the project, not just the code.  Can you zip and attach the entire CCS project?  That way I can see project settings and hoe the linker is setup. Thanks.

    Regards,

    Richard

  • Example_F2802xLaunchPadDemo.rar

    Hello Richard,

    I tried the PI controller from DMC library but i implemented the sturcture in my code and i still have the same problem output of the integrator is saturating when the error is positive or negative. But the loop speed has increased to 16 Khz.

    Please find attached my project. 

  • Hello Richard,

    I conducted some experiments and here are my observations
    1) while(1) //execution is 125Khz
    {
    GPIO_toggle(myGpio, GPIO_Number_1);
    }
    Toggles gpio 1 at 125 khz with nothing else running in the loop and all interrupts, adc disabled

    2a) err_5=1.25; //just a float variable
    while(1) //execution is 8.9Khz
    {

    GPIO_toggle(myGpio, GPIO_Number_1);
    // A_5 = err_5 * 0.4; //float variable
    B_5 = err_5 * 727.27; //float variable
    v_5 = k_5 + 0.5/50000 * (B_5 + in_A); // float variable
    k_5 = v_5; // static float variable integrator works only when defined in static type to keep the past value
    in_A = B_5; //static float variable

    }
    Simple floating multiplication operation causes the gpio 1 to toggle at 8.8 Khz.
    2b) err_5=1.25
    while(1) //execution at 75 Khz
    {

    GPIO_toggle(myGpio, GPIO_Number_1);
    // A_5 = err_5 * 0.4;
    B_5 = _IQmpy(err_5, 727.27);
    v_5 = k_5 + _IQmpy( 0.5/50000, (B_5 + in_A));
    k_5 = v_5;// static _iq type not sure if this right !!!!! have to check
    in_A = B_5;
    }
    using iqmath lib i am getting higher toggle rate at 75Khz Amaziing !!!!!

    3a) while(1) //15Khz
    {
    GPIO_toggle(myGpio, GPIO_Number_1);

    if(Count>1)
    {
    // A_5 = err_5 * 0.4;
    B_5 = err_5 * 727.27;
    integrator[Count] = integrator[Count-1]+ 0.5/50000 * (B_5 );
    //k_5 = v_5;
    in_A = B_5;
    }

    if(Count==10)
    {

    Count=0;
    }
    else Count++;


    }
    by using float type array toggle rate is 15 Khz

    3b) GPIO_toggle(myGpio, GPIO_Number_1);
    while(1) //execution at 62 Khz
    {
    if(Count>1)
    {
    // A_5 = err_5 * 0.4;
    B_5 = _IQmpy(err_5, 727.27);
    integrator[Count] = integrator[Count-1]+ _IQmpy(0.5/50000,(B_5));
    //k_5 = v_5;
    // in_A = B_5;
    }

    if(Count==10)
    {

    Count=0;
    }
    else Count++;
    }

    using iqmath lib and creating array of size 11 i am getting higher toggle rate at 62Khz

    I am able to get the correct toggle rate when i run the PI controller in the main loop instead of inside the adc routine using _IQ math lib. My new problem is I am not able to verify the results when i output the result to a serial port every second. Before i output the results i convert them back to float using the _IQtoF(); command but my result is always zero. I always get a warning when compiling "Description Resource Path Location Type
    build attribute vendor section TI missing in Example_F2802xLaunchPadDemo C/C++ Problem
    "

    Thanks a lot for the help
  • Srinivisan,

    The execution speed is also being influenced by the fact the code is running from flash. I had not realised this before. If you want the ISR to be as fast as possible you should copy it into RAM before executing. There is a good application note (spra958) which describes how to do this, and includes some example code for the F28027.

    Take a look at the IQ quantity before you convert it back to float. Is it zero? I think there might be a bug somewhere in the way you're using IQ math.

    When a PI controller runs it is normal for the integral path to saturate. The pi_reg4 code includes anti-windup which disables the integrator when the controller output exceeds pre-defined limits. Your original code has a very high integral path gain, so this might be happening very quickly. It's not necessarily a problem providing it's handled correctly in the code.

    I still recommend using the PI controller from the DMC library. That is already written in IQmath and is known to work correctly. BTW, you can safely ignore the warning about the missing build attribute - that is expected.

    Regards,

    Richard

  • Hello Richard,

    Thanks a lot for all the help and suggestions. I moved the adc routine to RAM and used IQmath library and to my surprise i am getting a sample rate of 40 Khz when the adc pin is left floating and 50 Khz when the adc pin is grounded. Is it because of all the floating point calculations taking place inside the routine ??? I also re-set the parameters of EPWM that starts the SOC
    // Setup PWM
    PWM_enableSocAPulse(myPwm); // Enable SOC on A group
    PWM_setSocAPulseSrc(myPwm, PWM_SocPulseSrc_CounterEqualZero); // Select SOC from from CPMA on upcount PWM_SocPulseSrc_CounterEqualCmpAIncr
    PWM_setSocAPeriod(myPwm, PWM_SocPeriod_FirstEvent); // Generate pulse on 1st event
    PWM_setCmpA(myPwm, 600/2); //from 1200/2

    PWM_setPeriod(myPwm, 600); // from 1200
    doing this i am getting 40 Khz but i cant output the pwm anymore on gpio1(shows higher rate not a problem). Could you please suggest me an accurate way to measure the loop time ? are there any inbuilt tools in ccs ?
    I dont know if i should actually play around with EPWM to get high sample not sure if it's good engineering practice.
    I will try to implement the PI controller from the DMC library and share my results.

    I meant only the integral output should ramp up or down depending on the error like when i have no saturation points. Now i am getting that !!!
    Yes I had a small bug when calling the IQlibrary. Thanks a lot...

    I hope my company will be convinced to use TI processors lol...
  • Srinivasan,

    You're welcome.  Glad to know you're making progress.

    There's an easy way to get cycle count numbers using CCS.  Set a break-point where you want to start measuring and run the code to that point.  Then, in CCS: Run -> Clock - Enable.  This puts a clock in the lower right corner of the ODE.  Set another break-point where you want to stop measuring and run to that point.  The clock shows the cycle count.  You reset the counter by double-clicking on it.

    I suggest looking again at the code examples for F28027 in controlSUITE.  There is one which shows an ADC end-of-conversion interrupt routine (Example_2802xAdcSoc.c).  You can change the EPWM1 settings in that code to get the sample rate you want (nothing wrong with that), then add your PI code to the ISR.  Again, I recommend using the DMC library code mentioned above.

    This way you'll have the controller operating at a known rate and with known code.  If you want a flash implementation you can convert it later using the application note I mentioned above.  I think that will be an easier route.

    I hope this helps.

    Regards,

    Richard

  • Hello Richard,

    Many thanks for your reply. I really appreciate your efforts to help me out. I did like you suggested i tried measuring the clock counts these are my findings:

    speed of ADC routine is 1162 clock counts i think this is about 19 uS which is about 53.7 Khz.

    my issue is it sometimes takes 600 clock counts (10 uS) to call the adc routine i am confused why this happening ? this is interrupt shouldnt it take the same time every clock ? or is it because the conversion of the adc is taking a long time ?

    ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4); //set SOC0 channel select to ADCINA4
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A7); //set SOC1 channel select to ADCINA7
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_2, ADC_SocChanNumber_A3); //set SOC2 channel select to ADCINA3
    ADC_setSocChanNumber (myAdc, ADC_SocNumber_3, ADC_SocChanNumber_A1); //set SOC3 channel select to ADCINA1

    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_EPWM1_ADCSOCA);
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_2, ADC_SocTrigSrc_EPWM1_ADCSOCA);
    ADC_setSocTrigSrc(myAdc, ADC_SocNumber_3, ADC_SocTrigSrc_EPWM1_ADCSOCA);

    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles); //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_14_cycles); //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_2, ADC_SocSampleWindow_14_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_3, ADC_SocSampleWindow_14_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)

    i am using this to perform the soc conversions am i doing something wrong here ? i have adc 0 set to 7 cycles and others to 14 as per datasheet the total conversion is approxi about 700ns so the total clock count for calling the adc routine should be about 40-50clocks but iam getting like 600...

    Can you please explain this line

    PWM_setIntMode(myPwm, PWM_IntMode_CounterEqualCmpAIncr); // Select INT on Zero event

    PWM_setIntPeriod(myPwm, PWM_IntPeriod_FirstEvent); // Generate INT on 1st event

    this means the interrupt routine is triggered when the pwm is low right ?

    What does this first event mean ?
  • Hello Richard,

    Ok i think i found the problem actually i observed two issues with my code first was toggling GPIO in the isr took 137 clock cycles and secondly in the main loop i had scia running every second transmitting debugging messages when i disabled these two i am getting about 52Khz
    Really Amazing !!!!!
    I am still having problem with the dmc pi controller actually i copied the code in my .c file and tried running it i see the output is doesnt ramp up to max value! i will check this again...thanks a lot for your help.
  • Hello,

    I am working on DC/DC converter and in close loop voltage control I need to implement PI.

    So I was looking on your code, why there is multiplication of 727.7..? ..second doubt is if I need to vary my PWM compare as per PI value, what should I do..?

    Please share your view.

    Thanks in advance.

  • Hello,

    That multiplication is because of Ki*error here my ki=727.27 it's too large it was taken from a simulation i did.
    Second: PI's output is used as duty. But make sure to saturate the output to min to max level like for flyback it is like 10% to 50%.
    I hope this helps

    Regards,

    Srini
  • Hi Srini,

    Thank you for the reply.

    I am trying to impliment SEPIC and my maximum duty cycle goes up to 70%. I will be needing one PI for voltage and another for current loop control. I am not good at coding anyway I am trying to learn. Do I need to use IQ math library or this simple code will work..?

    Please share your view.

    Thank you.

  • Hi,

    It depends on the sampling rate of your voltage and current loops. Yes please use IQ math library if you are using F28027 as this is a floating point device if you are using a device with floating point support you dont have to use it. Also make sure to set the global Q value in the IQ math library to match your requirements by default it is 24.  

    70% is not a problem just saturate the output to 70 or 0.7 depending on how you code the PI. 

    my issue is with sampling rate of the control loop i am not able to push it to increase. 

    Hope this helps.

    Srini

  • Hello Srini,

    Thank you for your reply.
    My doubt is my sensed value (i.e. Output Voltage) comes at ADC in the form of 4096 count or 3.3V. And the operation in PI loop is in per unit system. How to corelate that. My guess is I cannot multiply/divide directly. Adn after all that I need to give compare count for PWM pulses in the form of count. How to do that.

    Please share your view.

    Thanks.
  • Hello Srini,

    In your code you have multiplied with 0.5/50000, is it for integral time/smapling frequency..?..Please let me know.
    I am trying to convert everything into count form, for calculation.

    Please share your view.
  • Hi Anup,
    yeah it is the sampling frequency.
  • Hello Richard,

    Thank you for your help, i managed to do the current loop currently have a sampling freq of 33 Khz. But my current issue is with the ADCs i donno what is going on the ADC value is not constant and fluctuates a lot for ex if connect the adc to 3V3 (ref) the adc values fluctuate from 3095 to 4095 on one pin and 4010 to 4045 on the other. Could you please tell me why is this happening ?
    sample window is 14 so 15 ADC clock i played around still not much use.
    ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_14_cycles);
  • Srinivasan,

    Glad to know you have the control loop working at this frequency.  Sorry, I don't have any idea why the ADC is behaving this way.  3.3V is the upper limit of the ADC input on this device.  What happens if you apply a fixed mid-range input, say +1.5V, do you still see the same variation?

    I strongly recommend opening a new post on this forum because no-one will connect this thread title with a question about the ADC. 

    Regards,

    Richard

  • Dear Richard,

    Thank you for your reply. Yes I will start a new forum. I've tried everything it behaves that way when i apply from 0 to 3v3 the adc values fluctuate a lot except for gnd it shows good old stable 0 but others it is acting weird.
    but still i am not able to sample 66 KS/s
    can you please tell me which is better changing the hardware platform or trying to code in ASM ?
    i am doing my thesis your inputs are much appreciated. My aim was to run different algorithms atleast pi and 2p2z on piccolo but now i am skeptical about the sampling rate.
  • Hi Srinivasan,

    Since you are working on a research project my suggestion is you go ahead and move to a platform which supports floating-point.  If your sample rate issues are connected with the use of float in the code, they should go away then.  You will also find it easier to code and test your controller.  The Digital Controller Library I mentioned previously will also become feasible. 

    The alternative - re-writing your interrupt code in assembly - will entail more work and likely take a lot longer to get running.

    Regards,

    Richard

  • Hello Richard,

    Thank you for the suggestion, i will move to F28069. I am having an issue again with my current loop and i found the culprit is with triggering the ADC sampling i am really confused with my understanding of the soc pulse sources. Can you please give explain or suggest a material that i can read ?
    PWM_SocPulseSrc_CounterEqualZero ///CTR = Zero ?
    PWM_SocPulseSrc_CounterEqualPeriod // CTR= PRD
    PWM_SocPulseSrc_CounterEqualCmpAIncr // CmpA incr ?
    PWM_SocPulseSrc_CounterEqualCmpADecr // CmpA dec ?
    so could please kindly tell me how do i trigger the soc to sample when CTR= CmpA ?
    this is creating a lot of issue on my current loop and causing hissing noise on the transformer.

  • Hello Srinivasan,

    The CMPA & CMPB comparators are capable of distinguishing between a comparator match when the timer is counting up, and a match when the timer is counting down.  Sampling and/or edge events can be triggered on one or both conditions.  You will have to decide which condition you want to use for sampling.

    For example, the attached timing diagram generates complementary pair duty cycle modulated PWM using CMPA (counting up) for edge positioning, and CMPB (counting up) for ADC SOC.  This approach allows the ADC sampling point to be positioned away from a PWM edge where the reading might be corrupted by glitches.   

    If you want CTR=CmpA among the conditions in your post, and you want counting up, you need:

    PWM_SocPulseSrc_CounterEqualCmpAIncr

    It's a lot of information, but I recommend working through sections 3.2.3 and 3.2.4 in the TRM for this device.

    Regards,

    Richard

    160316.pdf

  • Hello Richard
    thank your reply again. I am having a strange issue not sure if this is the right place to post but i am trying. I am getting consistent values for the current but my current loop isnt working at higher loads. The transformer is making a hissing noise and the output of the current controller pi is fluctuating a lot i am not sure what to do. I tried playing with the pi values of both current and voltage loops no matter what i do i get heavy hissing noise. Also my output voltage ripple increase to beyond 100mV at higher loads. I dont know if it's hardware issue or software ? I suspect the current loop is too slow ! but not sure.
    Could you please give me advice on how to check if the current loop is working ?
    I tried doing some simulations checking out the waveforms at output of voltage pi, input current sense and comparing this to digital control i get nothing like what i see so i am really confused.
    As far as my understanding goes the outer voltage loop should act like a reference to inner current loop whenever the sense current tries to exceed this the output of the current loop should reduce to minimum value.
    The step response of my system is really bad !!! Thank you
  • Hello Richard,

    Thank you for all the help and support you have provided...I have couple of more questions
    1) Currently my current loop is running at approxi 1/5 the switching frequency at 90mhz cpu clock so does that mean current loop is actually working ? as far as i know current loop should immediately account for changes caused by change input voltages and output load.
    2) i am able to increase to the sampling rate of current loop and the controller by over clocking the cpu i get a good sampling rate with 90 mhz clock and 120 mhz clock. do you think it is a good idea/ practice to over clock cpu like this ? if i am not wrong other families of piccolo can run upto 200 mhz but the base hardware should be the same right?
    3) in the lighting example multi dc/dc converter i think they have shown running only voltage loop at switching frequency. Is there a reason why this is done ? I read online and few papers voltage loop is usually a slow loop so a few kS/s is more than enough.
    Thank you so much again !
  • Srinivasan,

    Sorry for my delayed reply - I have been out of the office for some time.  Can you let me know the switching frequency please?

    1) What is your current control strategy?  Are you using the internal comparators to implement peak current control, or is this average current control?

    2) I do not recommend over-clocking the CPU.  You will be operating the device out of spec which means none of the datasheet parameters are guaranteed.  The fastest Piccolo device is the F28075 which runs at 120MHz.  There are faster C2000 devices in the Delfino family.

    3) I'm not familiar with the DC-DC lighting board.  I will ask a colleague to comment.

    Regards,

    Richard

  • Hi Srinivasan,

    3) In the TMDSRGBLEDKIT, the C2000 is running 8 separate control loops.  Each loop is approximately controlling the average current through its corresponding boost/SEPIC stage.  The board assumes that the DC bus voltage being brought into the board is being controlled.
    (It could be feasible for some of the spare cycles in the C2000 device to be used to control this DC bus voltage using an external boost or buck converter.  That was not done here)

    Hopefully this helps.


    Thank you,
    Brett

  • Hello Richard,

    Many thanks for your reply. I tried to implement the voltage mode control first and yes the voltage mode control works very good at no-load and light load conditions. My control loop is running at 25 khz this is the maximum i got with my control scheme. The switching frequency is 150 khz, output is 5 V and vin is from 18 to 36 V. However there are two major problems the transient response of the vmc is about 500 ms which is really high and secondly there is a high hissing noise in the flyback transformer, this is a clear indication that control loop is running slowly or it could be the stability criteria is effected. The simulation yields that the cross over frequency of my flyback design is about 2.5 khz, based on this i calculated the kp and ki but the when reduce the kp and ki (move the cross over frequency) the noise reduces but the transient response is worst. The only good thing about my system is basic vmc and cmc works and efficiency is about 80 %
    even with current loop (average current mode control as suggested in the previous posts) the transient and ripple responses are bad ! i tried doing a frequency sweep with different kp and ki values but nothing helps i am not sure if it is a hardware problem

    I really thank you for all the help

    Regards,

    Srini
  • Hello Brett,

    Many thanks for your email. Are there any examples where the control loop is running in C and not in assembly or any material that helps the user to set the register directly from C and not assembly ? assembly is making really it hard ! also the variables called in assembly are complicated.
    Thank you so much.

    Regards,

    Srini