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.

TMS320F28335: TMS320F28335: PID Simulation (DCL)

Part Number: TMS320F28335

Dear TI members,

I am attaching a code of my simulation for PID. I need your help to just explain parts of the code:

Firstly: If rk =0.25 is set, then yk was achieved with the help of 12 bit ADC values (0-4095) and from the code line 342:

 yk = ((float) AdcRegs.ADCRESULT0 - 2048.0f) / 2047.0f;

yk could be between 1 and -1 .........if (float) AdcRegs.ADCRESULT0 between (4095 and 0). 

Now, next line 345 : uk = DCL_runPID_C4(&pid1, rk, yk, lk);......for running the PID function. which gives Control effort value u(k).

Question1 : Question is what could be the u(k) value range in numbers??? Please explain this line 345.

Line 348: clampactive = DCL_runClamp_C1(&uk, upperlim, lowerlim); defining the upper and lower limit saturation. 

Question 2: Line 350: lk = (clampactive == 0U) ? 1.0f : 0.0f;.... There is no compulsion for choosing either 1 or 0 for clampactive. and can we choose any of them????

For line 353-354: 

Duty = (uk / 2.0f + 0.5f) * (float) EPwm1Regs.TBPRD;
EPwm1Regs.CMPA.half.CMPA = (Uint16) Duty;

Question3: 

From above line, if u(k) is known from Question 1, then why are we dividing by 2.5 (2.0f+0.5f) and then it multiply with EPwm1Regs.TBPRD ? This Epwm is the one at which we are sampling the ADC at line 286 (EPwm1Regs.TBPRD = 0xFFFF)??? If yes then how this above duty cycle changes if suppose your y(k) changes dues to ADC values? I think I should remove line 309 and then check GPIO0 or GPIO1 to see the change of duty cycle if  y(k) changes.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//###########################################################################
//
// FILE: Example_2833xAdcSoc.c
//
// TITLE: ADC Start of Conversion Example
//
//! \addtogroup f2833x_example_list
//! <h1> ADC Start of Conversion (adc_soc)</h1>
//!
//! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
//! Two channels are converted, ADCINA3 and ADCINA2.
//!
//! \b Watch \b Variables \n
//! - Voltage1[10] - Last 10 ADCRESULT0 values
//! - Voltage2[10] - Last 10 ADCRESULT1 values
//! - ConversionCount - Current result number 0-9
//! - LoopCount - Idle loop counter
//
//###########################################################################
// $TI Release: $
// $Release Date: $
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Please explain all the questions step by step. Sorry I am new to using DCL PID simulation.

Thanks

Regards

Arsalan 

  • Hi Arsalan,

    For Q1, PID controllers also have an internal clamp that is set on line 122&123, therefore, your output ranges will be clamped to 1.0 ~ -1.0

    For Q2, I'm not exactly sure what you meant by "no compulsion for choosing either 1 or 0 for clampactive". The purpose of this external clamp was to make sure that the controller won't be overdamped due to the saturated response (if control effort is clamped) and thus can't be recovered due to the influence of feedback loop. Our example only implemented rudimentary responses to either allow 100% of feedback or 0% of feedback, as shown in this diagram, lk dictates the ratio of the feedback into the controller:

    Feel free to change the values around, and as a matter of fact, this external clamp is unnecessary as PID controller also includes an internal clamp. I believe the purpose of this clamp is only to showcase when lk is clamped. Referring to the code implementation of DCL_PID_C3, which is the inline C version of asm C4.

    For Q3, I would have to reach out to our C2000 PWM export to give you a concrete answer on why are we dividing it by 2.5. But I believe you have some clean up to do as you have multiple instances of EPwm1Regs initialization. Will get to back you later once I received feedback from our internal export.

    Best,

    Sen Wang

  • Hi Seng,

    Thanks for the background information that you have provided. It has been very helpful for me. I will wait for further feedback from you for 2.5 division.

    Yesterday I tested the code on hardware. I am summarizing the results here: Signal is applied at ADCINA3 as input from 0 - 3V setup (see Picture1)

    So here I plotted Voltage 1 graph: that gives a value around 243. at 0.1V ADCINA3 as input voltage and  TBPRD 0xFFFF (see Picture2).

    Picture3 shows all dcl values parameters (Kp,ki,kd,c1,c2,d1,d2.,vmax,vmin...etc). Here rk = 0.25,lk =0,yk=0.9,uk = 0.05 and duty cycle = 34405.875 at 0.1V ADCINA3 as input voltage

    Picture1 :

    Picture 2:  

    Picture 3:

    After increasing the  input voltage ADCINA3 slowly from 0.1V  to 3V, the results are tabulated here in Picture 4 & Picture 5.

    Voltage 1 graph: that gives a value around 4095 in Picture 4. And  rk = 0.25,lk =0,yk=30.9,uk = 0.05 and duty cycle = 34405.875 in Picture5 at 3V ADCINA3 as input voltage

    Picture 4:

    Picture 5:

    Question1: 

    When there is no Power. All ground then, Duty cycle 2.4% at oscilloscope. When Power is up, then Duty cycle 48% . As the input voltage ADCINA3 increases, there is no change in duty cycle number 34405.875 (Picture 5). it remains same and why?  I guess it should change the duty cycle according to the applied voltage change. because I will send this duty cycle to one of ePwm Gpio port to watch the result through oscilloscope to check either the duty cycle changes how much depending upon increasing the applied input voltage. Please explain this. I am following this setup to build on my hardware:

      

    Question 2: 

    As you see above in above pictures, y(k) is increased from 0.9 to 30.9 when increasing voltage from 0V to 3V ADCINA3 as input voltage.

    In the DCL guide of ''Example 5: PID Controller Running on FPU32'', the y(k) must be equal to r(k) after settling. So here after increasing the input ADCINA3 voltage, the Picture 5 shows the settling output after little delay but y(k) doesn't become equal to reference voltage r(k). Please explain.

    Question3 : 

    c1 and c2 are filter coefficients but d2 and d3 are same as i10 and i14 ? can we say them a coefficient factor after delay? here in above pictures only d2 and d3 are changing when increasing voltage, and why? Please explain.

    Code is attached here: (This time the multiple EPwm1Regs initialization is removed here)

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //###########################################################################
    //
    // FILE: Example_2833xAdcSoc.c
    //
    // TITLE: ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10] - Last 10 ADCRESULT0 values
    //! - Voltage2[10] - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Thanks

    Regards

    Arsalan  

  • I will wait for further feedback from you for 2.5 division.

    Hi Arsalan,

    This is line is NOT dividing by 2.5f. Instead it's explained by this thread: e2e.ti.com/.../ccs-tms320f28379d-dcl-c200-motorware

    "In response to the first question, the assumption in the example was that the controller output was normalised to +/-1.0f. The code line scales and then offsets the controller output to bring it in the 0 - 1.0f range, which is multiplied by the PWM period to get the duty cycle. It's just a code example."

    Best regards,

    Ryan Ma

  • Hi Arsalan, I apologize for the delay.

    Like Ryan said, uk/2.0f + 0.5f was an attempt to normalize the control output range from -1.0~1.0f to 0~1.0f, representing 0% to 100% of the duty cycle.

    And judging from your code, you've setup ADCINA2, ADCINA3 on F28335 but the ISR is still reading ADCRESULT0 from the F28069 DCL example, providing the signal to ADCINA3 shouldn't have any effect on ADCRESULT0 and all subsequent changes in ADCRESULT0 and PID is probably due to floating voltages. 

    One thing I forgot to mention is that there's also an external saturation that is included to further clamp the saturation range to 0.05f~0.95f instead of +/-1.0f. So you could comment out the runClamp_C1 in line 315 if you don't need additional saturation.

    Best,

    Sen Wang

  • Hi Ryan,

    Thanks for your reply. I will get back to you soon after implementing your suggestion. I will let you know the results soon.

    Regards

    Arsalan

  • Hi Sen,

    Thanks for your reply. I will get back to you soon after implementing your suggestion. I will let you know the results soon.

    Regards

    Arsalan

  • We will await your results.

    Best,

    Ryan Ma

  • Hi Sen & Ryan,

    Thanks for your comprehensive replies. Quite Helpful

    And judging from your code, you've setup ADCINA2, ADCINA3 on F28335 but the ISR is still reading ADCRESULT0 from the F28069 DCL example, providing the signal to ADCINA3 shouldn't have any effect on ADCRESULT0 and all subsequent changes in ADCRESULT0 and PID is probably due to floating voltages. 

    As suggested, I fixed that issue, Now I am applying at ADCINA0 and ISR is reading ADCRESULT. and it is reading the duty cycle only at 2 values. (65553 or 0) at 0V and 3V respectively on watch window. There is no middle value it gives when i set the voltage suppose 1.2V and the duty cycle is 0 (no middle value around). see Picture. below:

    At 0V(ground) applied on ADCINA0, the output Voltage1 = 0 approx on watch window, The Duty is 65535.(because TBPRD = FFFF) see Picture 1,2 and when 3V applied, the Duty cycle shows 0 Picture 3,4.

    Picture 5 shows that when i applied a voltage of 1.2 approx at  ADCINA0, the Duty cycle doesn't show around a middle value. it stays at 0. The Duty cycle must be change depending upon the whatever the voltage is applied accordingly.

    Picture1 (at 0 V)

    Picture2 (at 0V)--Duty cycle = 65535

     

    Picture3 (at 3 V)

    Picture4 (at 3V)--Duty cycle = 0

    Picture 5 (at 1.2V approx)... Duty cycle has no middle value. it stays at 0.

    Updated code is attached here

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //###########################################################################
    //
    // FILE: Example_2833xAdcSoc.c
    //
    // TITLE: ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10] - Last 10 ADCRESULT0 values
    //! - Voltage2[10] - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Please suggest this issue accordingly

    Thanks

    Regards

    Arsalan

  • Hi Sen & Ryan,

    Thanks for your comprehensive replies. Quite Helpful

    And judging from your code, you've setup ADCINA2, ADCINA3 on F28335 but the ISR is still reading ADCRESULT0 from the F28069 DCL example, providing the signal to ADCINA3 shouldn't have any effect on ADCRESULT0 and all subsequent changes in ADCRESULT0 and PID is probably due to floating voltages. 

    As suggested, I fixed that issue, Now I am applying at ADCINA0 and ISR is reading ADCRESULT. and it is reading the duty cycle only at 2 values. (65553 or 0) at 0V and 3V respectively on watch window. There is no middle value it gives when i set the voltage suppose 1.2V and the duty cycle is 0 (no middle value around). see Picture. below:

    At 0V(ground) applied on ADCINA0, the output Voltage1 = 0 approx on watch window, The Duty is 65535.(because TBPRD = FFFF) see Picture 1,2 and when 3V applied, the Duty cycle shows 0 Picture 3,4.

    Picture 5 shows that when i applied a voltage of 1.2 approx at  ADCINA0, the Duty cycle doesn't show around a middle value. it stays at 0. The Duty cycle must be change depending upon the whatever the voltage is applied accordingly.

    Picture1 (at 0 V)

    Picture2 (at 0V)--Duty cycle = 65535

     

    Picture3 (at 3 V)

    Picture4 (at 3V)--Duty cycle = 0

    Picture 5 (at 1.2V approx)... Duty cycle has no middle value. it stays at 0.

    Updated code is attached here

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //###########################################################################
    //
    // FILE: Example_2833xAdcSoc.c
    //
    // TITLE: ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10] - Last 10 ADCRESULT0 values
    //! - Voltage2[10] - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Please suggest this issue accordingly

    Thanks

    Regards

    Arsalan

  • Hi Arsalan,

    You're seeing the correct ADC samples now, correct? It seems when voltage is at 1.2V, uk is -1 which is incorrect and I believe should be 0? That way duty is 50% of the TBPRD. Why is it that when you're at 1.2V, uk is -1V, I believe uk is returning an incorrect floating point value. Is there something missing here?

    Best,

    Ryan Ma

  • Hi Arsalan,

    Yes, for one the value of yk should be bounded to +/-1 due to line 309, but in picture 5 you have 12.8. With Kp being 9.0f, the controller would return a maximum control effort, which is bounded to +/-1, which may explain why you only see duty cycle being either 0 or 100%. The controller is overreacting to the larger/smaller than expected input and thus is outputting an maximum control effort.

    Best, 

    Sen Wang

  • Hi Seng,

    Thanks for your reply.

    for one the value of yk should be bounded to +/-1

    As you said, the yk value should be either 1 or -1. But according this formula line 309, this value should be in between -1 to +1 with +1 & -1 inclusion. It can be any value between them depending upon my adc input ADCINA0 from 0 -3V.

    With Kp being 9.0f, the controller would return a maximum control effort, which is bounded to +/-1, which may explain why you only see duty cycle being either 0 or 100%

    Should i change Kp  so that i can have a duty cycle change in between (0 to 100%) ?? not exactly either 0 or 100%. Because here the purpose is generate varying duty cycle depending upon my ADC input.  As Ryan said that, if i am applying 1.2V then I must have duty near around 50%. Could you please how i can generate varying duty cycle like 10, 20 ,50 55,68,77,90 % etc ??? should i set other parameters in the program

    The code is attached here

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //###########################################################################
    //
    // FILE: Example_2833xAdcSoc.c
    //
    // TITLE: ADC Start of Conversion Example
    //
    //! \addtogroup f2833x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //!
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC on SEQ1.
    //! Two channels are converted, ADCINA3 and ADCINA2.
    //!
    //! \b Watch \b Variables \n
    //! - Voltage1[10] - Last 10 ADCRESULT0 values
    //! - Voltage2[10] - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount - Idle loop counter
    //
    //###########################################################################
    // $TI Release: $
    // $Release Date: $
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

     Thanks

    Regards

    Arsalan

  • Hi Arsalan,

    My concern was that yk is well outside of the range of +/-1, it was showing 12.9f on image 5 and it shouldn't be the case. If we do a quick calculation, P-path's control effort would be abs(yk - rk) * Kp = (12.9 - 0.25) * 9  =  113.85, which would be clamped to 1.

    Could you please how i can generate varying duty cycle like 10, 20 ,50 55,68,77,90 % etc ???

    Currently, do you have any feedback mechanism that allows you to use the duty cycle and influence your adc input? If there isn't any feedback, PID controller will never be able to reach the target voltage and its I-path would eventually saturate the feedback. And if you don't have a consistent input influence, the controller would eventually settle at 0% as it reaches the target value. The only way for a controller to constantly provide a control effort is if you have an constantly applied influence to begin with.

    if i am applying 1.2V then I must have duty near around 50%

    If you just need proportional duty cycles based on ADC readings, you don't need a PID to achieve that, directly assigning ADC reading to the duty cycle register would suffice, provided no external influence to the system.

    Best,

    Sen Wang