TMS320F280037C: TMS320F280037C

Part Number: TMS320F280037C

Tool/software:

pll code 
/*******************************************************************************
 * Includes
 ******************************************************************************/
#include "measurements.h"
#include "protections.h"
#include "pll.h"
#include "stdlib.h"
#include "math.h"
#include "stdlib.h"
#include "IQmathLib.h"
#include "control.h"
#include "isr.h"
#include "state.h"
#include "init.h"
#include "cust_math.h"

/*******************************************************************************
 * Defines
 ******************************************************************************/
#define PI 3.14159265f

#define TWO_PI (2.0f * PI)

#define ANGLE_THRESHOLD_HIGH (4.18879f) // ~240° in radians
#define ANGLE_THRESHOLD_LOW  (2.09439f) // ~120° in radians
/*******************************************************************************
 * Enums
 ******************************************************************************/

/*******************************************************************************
 * Structures
 ******************************************************************************/

/*******************************************************************************
 * Macros
 ******************************************************************************/

/*******************************************************************************
 * Local Function Prototypes
 ******************************************************************************/


/*******************************************************************************
 * Local Variables
 ******************************************************************************/
float32_t uf32_angle;
uint16_t g_ui16_Pll_state = 0;
float32_t FrequencyInHz;
float32_t sampling_frequency = (INIT_mSWITCHING_FREQ * 2.0F);
PLL_tzPLL_REG tzPLLReg;


/*******************************************************************************
 * Local Constants
 ******************************************************************************/

/*=============================================================================
 @brief Write EEPROM Page

 @param void
 @return void
 ============================================================================ */
void PLL_fnGridPLL(void)
{

    if (tzPLLReg.uiGridPhaseSeq == 1)
    {
        tzPLLReg.pll_angle = tzPLLReg.pll_angle+ tzPLLReg.pll_angle_step;

    }
    else
    {
        tzPLLReg.pll_angle = tzPLLReg.pll_angle- tzPLLReg.pll_angle_step;
    }

    if(tzPLLReg.pll_angle>=TWO_PI)tzPLLReg.pll_angle-=TWO_PI;
    if(tzPLLReg.pll_angle<0)tzPLLReg.pll_angle+=TWO_PI;

    tzPLLReg.Sine_theta = sinf( tzPLLReg.pll_angle);

    tzPLLReg.Cos_theta = cosf( tzPLLReg.pll_angle);




    /// clarke's transformation
    voltage.alpha=1.5*tzACDerivedValues.fVrnPhase;
    voltage.beta=(tzACDerivedValues.fVynPhase-tzACDerivedValues.fVbnPhase)*(1.7320508/2.0);
    /// sogi ///

//    if (tzPLLReg.ePLLState == PLL_LOCKED)
//    {
        tzPLLReg.V_alpha_filtered = voltage.alpha;
        tzPLLReg.V_beta_filtered = voltage.beta;
  //}
    //// park's transformation /////
    tzPLLReg.V_daxis=tzPLLReg.V_alpha_filtered* tzPLLReg.Cos_theta+tzPLLReg.V_beta_filtered*tzPLLReg.Sine_theta;
    tzPLLReg.V_qaxis=tzPLLReg.V_beta_filtered*tzPLLReg.Cos_theta-tzPLLReg.V_alpha_filtered*tzPLLReg.Sine_theta;
    tzPLLReg.V_qaxis_filtered = MATH_fnLowPassFilter(
            10, tzPLLReg.V_qaxis, tzPLLReg.V_qaxis_filtered,
            sampling_frequency);
    tzPLLReg.V_daxis_filtered = MATH_fnLowPassFilter(
            10, tzPLLReg.V_daxis, tzPLLReg.V_daxis_filtered,
            sampling_frequency);


    if (tzPLLReg.uiGridPhaseSeq == 1)
    {
        tzPLLLoop.Fbk=-tzPLLReg.V_qaxis;

    }
    else
    {
        tzPLLLoop.Fbk=tzPLLReg.V_qaxis;
    }
    tzPLLReg.Volt_peak =
            sqrtf((tzPLLReg.V_alpha_filtered * tzPLLReg.V_alpha_filtered)
                  + (tzPLLReg.V_beta_filtered * tzPLLReg.V_beta_filtered)) * (0.66667F);


    if (tzPLLReg.Volt_peak < 20)  //50
    {
        PLL_fnResetPLLParams();
    }

    switch (tzPLLReg.ePLLState)
    {
    case PLL_INIT:
    {
        if (tzPLLReg.Volt_peak > 40) //100
        {
            ++tzPLLReg.pll_timer;
            if (tzPLLReg.pll_timer > 100)
            {
                tzPLLReg.ePLLState = FIRST_ZERO_CROSSING;
            }
        }

        break;
    }
    case FIRST_ZERO_CROSSING:

    {
        uf32_angle = atan2f(tzPLLReg.V_beta_filtered,
                            tzPLLReg.V_alpha_filtered);
        if (uf32_angle < 0)
        {
            uf32_angle = (TWO_PI) + uf32_angle;
        }

        if ((tzPLLReg.pll_angle> ANGLE_THRESHOLD_HIGH) && (uf32_angle < ANGLE_THRESHOLD_LOW))
        {
            tzPLLReg.uiGridPhaseSeq = 1;
            tzPLLReg.ePLLState = SECOND_ZERO_CROSSING;
        }
        else if ((uf32_angle > ANGLE_THRESHOLD_HIGH)
                && (tzPLLReg.pll_angle < ANGLE_THRESHOLD_LOW))
        {
            tzPLLReg.uiGridPhaseSeq = 0;
            tzPLLReg.ePLLState = SECOND_ZERO_CROSSING;
        }
        tzPLLReg.pll_angle= uf32_angle;
        tzPLLReg.pll_state_count = 0;

        break;
    }
    case SECOND_ZERO_CROSSING:

    {
        tzPLLReg.pll_state_count++;
        uf32_angle = atan2f(tzPLLReg.V_beta_filtered,
                            tzPLLReg.V_alpha_filtered);
        if (uf32_angle < 0)
        {
            uf32_angle = (TWO_PI) + uf32_angle;
        }

        if (tzPLLReg.uiGridPhaseSeq == 1)
        {
            if ((tzPLLReg.pll_angle > ANGLE_THRESHOLD_HIGH)
                    && (uf32_angle < ANGLE_THRESHOLD_LOW))

            {
                tzPLLReg.frequency = sampling_frequency
                        / tzPLLReg.pll_state_count;
                tzPLLReg.ePLLState = PLL_LOCKED;

            }
            else if ((uf32_angle > ANGLE_THRESHOLD_HIGH)
                    && (tzPLLReg.pll_angle  < ANGLE_THRESHOLD_LOW))
            {
                PLL_fnResetPLLParams();
            }
        }
        else
        {
            if ((uf32_angle > ANGLE_THRESHOLD_HIGH)
                    && (tzPLLReg.pll_angle < ANGLE_THRESHOLD_LOW))
            {
                tzPLLReg.frequency = -(sampling_frequency
                        / tzPLLReg.pll_state_count);
                tzPLLReg.ePLLState = PLL_LOCKED;

            }
            else if ((tzPLLReg.pll_angle > ANGLE_THRESHOLD_HIGH)
                    && (uf32_angle < ANGLE_THRESHOLD_LOW))
            {
                PLL_fnResetPLLParams();
            }
        }
        tzPLLReg.pll_angle = uf32_angle;
        break;
    }
    case PLL_LOCKED:
        {
            CTRL_PI_LOOP(tzPLLLoop); //
            tzPLLReg.pll_angle_step = ((tzPLLLoop.Out * 6.28)
                    / sampling_frequency);
            tzPLLReg.frequency = MATH_fnLowPassFilter(500, tzPLLLoop.Out,
                                                      tzPLLReg.frequency,
                                                      sampling_frequency);

            FrequencyInHz = tzPLLReg.frequency;



            if (abs(tzPLLReg.V_qaxis_filtered) > 25.0F)
            {
                if(tzTimers.ui_pll_sync_timer >= 10000U)
                {
                    tuSWFaults.bit.btPLLSyncError = 1U;
                }
                else
                {
                    tzTimers.ui_pll_sync_timer += 1;
                }
            }
            else if (abs(tzPLLReg.V_qaxis_filtered) < 5.0F)
            {
                if(tzTimers.ui_pll_sync_timer > 0U)
                {
                    tzTimers.ui_pll_sync_timer--;
                }
            }

            break;
        }
        }

    }

/*=============================================================================
 @brief Read

 @param void
 @return void
 ============================================================================ */
void PLL_fnResetPLLParams(void)
{

    CTRL_RESET_PI_LOOP(tzPLLLoop);

    tzPLLReg.pll_angle  = 0;
    tzPLLReg.pll_angle_step= 0;
    tzPLLReg.frequency = 0;

    tzPLLReg.ePLLState = PLL_INIT;
    FrequencyInHz = 50.00;

    tzPLLReg.V_qaxis_filtered = 0;
}





/*******************************************************************************
 * End of File
 ******************************************************************************/

Control loop values 
CTRL_tzLOOP_PARAMS tzPLLLoop = {
                              .Fbk = 0, .Ref = 0, .Out = 0,
                              .Kp =0.01,
                              .TsKi = 1.57e-6,
                              .i1 = 0, .ui = 0, .up = 0,
                              .v1 = 0, .w1 = 0,
                              .Umax = 65, .Umin = 45
};

Switching frequency is 20KHz

I am working on an AC-DC converter and currently implementing the PLL logic. When I provide an AC input of 50 V at 50 Hz, the PLL enters the locked state, but the variable tzPLLReg.frequency consistently shows 45 Hz, even though the actual frequency is 50 Hz (from expression window.)

When I change the input frequency to 40 Hz or other values, the PLL still remains in the PLL_LOCKED state. However, if I vary the voltage, the PLL state changes accordingly.

This indicates that the voltage detection is working, but the frequency measurement is inaccurate. I am attaching all related program files for reference. Please help me resolve this issue.

 I need to get frequency as 50 Hz accurately it should not vary from 50Hz (0.1% deviation is fine).