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.

TIDA-010210: Control concept on three ANPCs

Part Number: TIDA-010210
Other Parts Discussed in Thread: SFRA

Hi Team,

There's an issue from the customer need your help:

Regarding the three phase ANPC reference design, there is a question I would like to ask:

In the sample program, SPLL and dc bus voltage measurement are performed after control calculation and PWM update, such as the program of Lab6 - PFC control below.

It means that the control calculation of this interrupt uses the data in the previous interrupt. Will there be no phase delay problem in this way (especially the SPLL part)? 

What is the reason for adopting this method instead of the general method (update the ADC reading value and phase lock first in the interrupt and then perform the control operation)?

static inline void ANPCINV_runISR1_lab6(void)
{
    //
    // Read ADC sampled voltage and current values
    //
    ANPCINV_readCurrentAndVoltageSignals();

    ANPCINV_iInv_A_filt_sensed_pu = ANPCINV_iInv_A_sensed_pu;
    ANPCINV_iInv_B_filt_sensed_pu = ANPCINV_iInv_B_sensed_pu;
    ANPCINV_iInv_C_filt_sensed_pu = ANPCINV_iInv_C_sensed_pu;

    //
    // Transform the above feedback signals from ABC to DQ axes
    //
    ANPCINV_runTransformOnSensedSignals();

    //
    // Clear the PWM trips when ANPCINV_clearPWMTrip
    // is written to '1' from the watch window
    //
    if(ANPCINV_clearPWMTrip == 1U)
    {
        // Wait for zero-crossing then clear trips and start power stage
        if((ANPCINV_vGrid_A_sensed_pu > 0.0f) &&
                (ANPCINV_vGrid_A_sensed_pu_prev < 0.0f))
        {
            ANPCINV_clearPWMTrip = 0;
            ANPCINV_clearAllPWMTrips();
            ANPCINV_updateDuty = 1U;

        }
    }

    if (ANPCINV_updateDuty)
    {
        //
        // Run the current close loop
        //
        //PFC voltage loop soft-start
        //
        if((ANPCINV_vBus_Ref - ANPCINV_vBus_RefSlewed) > (2.0 * ANPCINV_VOLTS_PER_SECOND_SLEW) *
                                           (1.0 / (float32_t)ANPC_INV_ISR2_FREQUENCY_HZ))
        {
            ANPCINV_vBus_RefSlewed =  ANPCINV_vBus_RefSlewed + (ANPCINV_VOLTS_PER_SECOND_SLEW) *
                                  (1.0 / (float32_t)ANPC_INV_ISR2_FREQUENCY_HZ);
        }
        else if((ANPCINV_vBus_Ref - ANPCINV_vBus_RefSlewed) <
                           - (2.0 * ANPCINV_VOLTS_PER_SECOND_SLEW) *
                                  (1.0 / (float32_t)ANPC_INV_ISR2_FREQUENCY_HZ))
        {
            ANPCINV_vBus_RefSlewed =  ANPCINV_vBus_RefSlewed - (ANPCINV_VOLTS_PER_SECOND_SLEW) *
                                  (1.0 / (float32_t)ANPC_INV_ISR2_FREQUENCY_HZ);
        }
        else
        {
            ANPCINV_vBus_RefSlewed =  ANPCINV_vBus_Ref;
        }
        //End of PFC voltage loop soft-start

        //Voltage control loop
#if     ANPC_INV_SFRA_TYPE == ANPC_INV_SFRA_VOLTAGE

        ANPCINV_idRef = -1.0f * (ANPCINV_GV_RUN(&ANPCINV_gv_vBus,SFRA_F32_inject(ANPCINV_vBus_RefSlewed),ANPCINV_vBus_sensed));
        ANPCINV_gv_vBus_out = -1.0f * ANPCINV_idRef;
        SFRA_F32_collect((float32_t *)&ANPCINV_gv_vBus_out, (float32_t *)&ANPCINV_vBus_sensed);

#else

        ANPCINV_idRef=-1*(ANPCINV_GV_RUN(&ANPCINV_gv_vBus,ANPCINV_vBus_RefSlewed,ANPCINV_vBus_sensed));

#endif

        //Current control loop
        ANPCINV_runCurrentLoop();

        // Middle point voltage control loop
        ANPC_Duty_Offset_Middle_Voltage_Loop=(ANPCINV_GV_RUN(&ANPCINV_gv_vBus_Middle,-ANPC_Delta_Middle_Voltage_AVG,0));

        //
        // Vd and Vq can be directly used
        // for generating 3-phase PWM duty values
        DQ0_ABC_run(&ANPCINV_vInv_dq0,
                    ANPCINV_vdInv_pu, ANPCINV_vqInv_pu, ANPCINV_vzInv_pu,
                    ANPCINV_sine, ANPCINV_cosine);


        //Constant duty has been added in the system in order to perturb the middle point of the converter.

        ANPCINV_duty_A = ANPCINV_vInv_dq0.a+ANPC_Duty_Offset_Middle_Voltage_Loop;
        ANPCINV_duty_B = ANPCINV_vInv_dq0.b+ANPC_Duty_Offset_Middle_Voltage_Loop;
        ANPCINV_duty_C = ANPCINV_vInv_dq0.c+ANPC_Duty_Offset_Middle_Voltage_Loop;


        ANPCINV_update3PHPWM(ANPCINV_duty_A, ANPCINV_duty_B, ANPCINV_duty_C, ANPCINV_duty_A_k_3, ANPCINV_duty_B_k_3, ANPCINV_duty_C_k_3);

        //
        // Update dead-band slew for soft-start of PFC
        //
        if(ANPCINV_deadBandSlew >= ANPC_INV_HIGH_FREQ_PWM_DB_TICKS)
        {
            ANPCINV_HAL_updatePWMDeadBand(ANPCINV_deadBandSlew--);
        }

/*        ANPCINV_duty_A_prev = ANPCINV_duty_A;
        ANPCINV_duty_B_prev = ANPCINV_duty_B;
        ANPCINV_duty_C_prev = ANPCINV_duty_C;

        ANPCINV_duty_A_k_2 = ANPCINV_duty_A_prev;
        ANPCINV_duty_B_k_2 = ANPCINV_duty_B_prev;
        ANPCINV_duty_C_k_2 = ANPCINV_duty_C_prev;

        ANPCINV_duty_A_k_3 = ANPCINV_duty_A_k_2;
        ANPCINV_duty_B_k_3 = ANPCINV_duty_B_k_2;
        ANPCINV_duty_C_k_3 = ANPCINV_duty_C_k_2;*/

    }

    //
    // Run SPLL
    //
    ANPCINV_runSPLL();
    //

    ANPCINV_vBus_sensed_pu=ANPCINV_vBusp_sensed_pu+ANPCINV_vBusn_sensed_pu;
    if(ANPCINV_vBus_sensed_pu<=0) // avoid division by zero
    {
        ANPCINV_vBus_sensed_pu=0.001;
    }
    ANPCINV_vBus_sensed=ANPCINV_vBus_sensed_pu*ANPC_INV_VDCBUS_MAX_SENSE;
    ANPCINV_vBus_sensed_filter=Low_Pass_Filter*(ANPCINV_vBus_sensed_filter-ANPCINV_vBus_sensed)+ANPCINV_vBus_sensed;


    //AVG of the voltage
    ANPC_Delta_Middle_Voltage=(ANPCINV_vBusp_sensed_pu-ANPCINV_vBusn_sensed_pu)*ANPC_INV_VDCBUS_MAX_SENSE;
    ANPC_Delta_Middle_Voltage_AVG=0.9981*( ANPC_Delta_Middle_Voltage_AVG-ANPC_Delta_Middle_Voltage)+ANPC_Delta_Middle_Voltage;

    //
    // Based on theta estimated by SPLL, compute sine and cosine
    //
    ANPCINV_sine = sinf(ANPCINV_angleSPLL_radians);
    ANPCINV_cosine = cosf(ANPCINV_angleSPLL_radians);


    //ANPCINV_Display_Variables_Time_Scaled();

    ANPCINV_HAL_clearPWMInterruptFlag(ANPC_INV_ISR1_TRIG_BASE);
}