Current control Algorithm porting to LF inverter

Author
Serpent
Senior Member
  • Total Posts : 141
  • Reward points : 0
  • Joined: 2007/02/03 06:42:28
  • Location: INDIA
  • Status: offline
2018/01/11 00:38:43 (permalink)
0

Current control Algorithm porting to LF inverter

Hi This is about the application note of Offline UPS
http://www.microchip.com/....aspx?appnote=en543189
This is a Double conversion HF inverter. First the DC voltage is stepped up to 330 V DC using a pushpull stage operating at 100Khz and then a full bridge inverter stage converts this 300V DC to 230VAV at 50khz PWM.

I am trying to to a LF inverter using this code only using the inverter current control algorithm used in this where output voltage and load current is passed through a series of calculation steps (Derived from MATLAB simulations, I think) and a feed back (control output) is produced to maintain the voltage and current in limits.

So in my case the lower DC voltage say 24 volt will be fed to a Normal CRGO transformer using full bridge MOSFET switching which steps upto 230V. I have reduced the pwm frequency to 12.8khz by skipping samples to match the core which cannot work on 50khz.

So my doubt is weather this change in frequency and conversion type will match with the algorithm of current mode control which reads out put current and voltage and apply algorithm on each cycle?

There are many constants used in this algorithm .




Roy Thomas
“Give a man a program, frustrate him for a day.
Teach a man to program, frustrate him for a lifetime.”
Muhammad Waseem
#1

2 Replies Related Threads

    Serpent
    Senior Member
    • Total Posts : 141
    • Reward points : 0
    • Joined: 2007/02/03 06:42:28
    • Location: INDIA
    • Status: offline
    Re: Current control Algorithm porting to LF inverter 2018/01/11 00:43:00 (permalink)
    0



    /coeffs for current mode control
    #define InvCMvoltageKp Q15(0.51)//Q15(0.51)
    #define InvCMvoltageKi Q15(0.035)//Q15(0.035)
    #define InvCMcurrentRa Q15(0.91)//Q15(0.91)
    #define InvVMvoltagedecouple Q15(0.92)
    #define InvRp Q15(0.17/2.0)
    #define InvCMALPHA Q15(0.7)
    #define InvCMBETA Q15(0.3)
    #define InvCbydt Q15(0.57) //this is prescaled by 1/4
    #define InvSafetyfactor Q15(0.99)

    #define MAXCURRENTREF Q15(0.5)
    --------------------------------------------------------------------------------------------
    int inverterFreqAdjustment;
     /* Update reference for inverter output from sine lookup table */
        if ((sampleCount >= 0) && (sampleCount < 128))
        {
            inverterVoltageRef = (SineTable_50Hz[sampleCount] >> OUTPUT_VOLTAGE_SETTING);// setting is 0 for 220V
            if ((mainsState == MAINS_OK) && (_Q15abs(mainsBufferSize - SINE_TABLE_SIZE/2) <= 10))
            {
                if (sampleCount == 120 && inverterInterruptCount == 0)
                {
                    sampleCount = 136;
                }
            }
        }
        else if ((sampleCount >= 128) && (sampleCount < 256))
        {
            inverterVoltageRef = (SineTable_50Hz[255 - sampleCount] >> OUTPUT_VOLTAGE_SETTING);
        }
        else if ((sampleCount >= 256) && (sampleCount < 384))
        {
            inverterVoltageRef = - (SineTable_50Hz[sampleCount - 256] >> OUTPUT_VOLTAGE_SETTING);
            if ((mainsState == MAINS_OK) && (_Q15abs(mainsBufferSize - SINE_TABLE_SIZE/2) <= 10))
            {
                if (sampleCount == 376 && inverterInterruptCount == 0)
                {
                    sampleCount = 392;
                }
            }
        }
        else
        {
            inverterVoltageRef = - (SineTable_50Hz[511 - sampleCount] >> OUTPUT_VOLTAGE_SETTING);
        }
      Nop();
     #ifdef BuildFor12_8KhzPWM_Inverter
      sampleCount++; // Here we are skipping one entrie to compensate for
      sampleCount++; // the reduction in PWM frequency
     #else

        if (inverterInterruptCount == 0)
        {
            inverterInterruptCount++;
        }
        else
        {
            sampleCount++;
            inverterInterruptCount = 0;
        }
     #endif
        
        /* Measured Inverter Output Voltage in Q15 format */
        inverterOutputVoltage = (ADCBUF1_Dupe << 5) - DC_OFFSET - inverterOffsetAdjustment; //DC_OFFSET =0x3FF0(16368)
        
        /* Measured Inverter Output Current in Q15 format */
        inverterOutputCurrent = (ADCBUF0_Dupe << 5) - DC_OFFSET;

        #ifndef SkipVtgAndCur_PID_Calculations

        inverterVoltageError = (inverterVoltageRef - inverterOutputVoltage);
        temp4 = temp4 + ((__builtin_mulss((int)InvCMvoltageKi,inverterVoltageError))>>15); //calculate I term
            
        if(temp4 > 32767)
        {
            temp4 = 32767;
        }
        else if(temp4 < -32767)
        {
            temp4 = -32767;
        }

        if (inverterOutputCurrent > INVERTER_CURRENT_MAX_PEAK)//6000
        {
            fInverterCurrentLimit = CURRENT_LIMIT_ACTIVE;
            temp4 = 0;
        }
        else if (inverterOutputCurrent < -INVERTER_CURRENT_MAX_PEAK)//max peak - 6000
        {
            fInverterCurrentLimit = CURRENT_LIMIT_ACTIVE;
            temp4 = 0;
        }
        
        temp1 = ((__builtin_mulss((int)InvCMvoltageKp,inverterVoltageError))>>15);
                    
        FilteredVo = ((__builtin_mulss((int)InvCMALPHA,prevFilteredVo))>>15) + \
             ((__builtin_mulss((int)InvCMBETA,inverterOutputVoltage))>>15) ;

        delVo = FilteredVo - prevFilteredVo;

        CapCurrent = ((__builtin_mulss(delVo,InvCbydt))>>13);
        
        LoadCurrent = (__builtin_mulss((int)((inverterOutputCurrent - (int)CapCurrent)), InvSafetyfactor) >>15);
        inverterCurrentRef = (long)temp1 + temp4 + LoadCurrent;

        if(inverterCurrentRef > INVERTER_CURRENT_MAX_PEAK)
        {
            inverterCurrentRef = INVERTER_CURRENT_MAX_PEAK;
        }
        if(inverterCurrentRef < -INVERTER_CURRENT_MAX_PEAK)
        {
            inverterCurrentRef = -INVERTER_CURRENT_MAX_PEAK;
        }

        inverterCurrentError = (inverterCurrentRef - inverterOutputCurrent);

        VoltageCmd = ((__builtin_mulss((int)InvCMcurrentRa,(int)inverterCurrentError))>>15)+ ((__builtin_mulss((int)InvRp,(int)inverterOutputCurrent))>>15); //current P
        
        temp3 = ((__builtin_mulss((int)InvVMvoltagedecouple,(int)inverterOutputVoltage))>>15) ; //for 200 V //including scale factor

        temp5 = temp3 + VoltageCmd;
      Nop();
        if (OUTPUT_VOLTAGE_SETTING == 0)
        {
        Oneover_fourdclinkvoltage = 9000; //choose value based on min bus voltage
                                                        //for ~ 120 V bus ~ 32000
                                                            //for ~ 200 V bus ~ 18000
                                                        //for ~ 400 V bus ~ 9000
        }
        else if (OUTPUT_VOLTAGE_SETTING == 1)
        {
            Oneover_fourdclinkvoltage = 18000;
        }
        else if (OUTPUT_VOLTAGE_SETTING == 2)
        {
            Oneover_fourdclinkvoltage = 32000;
        }
        if(temp5 > 32767)
        {
            temp5 =32767;
        }
        else if(temp5 < -32767)
        {
            temp5 = -32767;
        }
        
        temp5 = (__builtin_mulss((int)temp5,Oneover_fourdclinkvoltage)>>13);
    #ifdef BuildFor12_8KhzPWM_Inverter
        if(temp5 > UB_InvMAXSCALED_DUTY) //1/16 scaling artefacts and clampling between values that will give
        {
            temp5 = UB_InvMAXSCALED_DUTY;
        }
        else if(temp5 < -UB_InvMAXSCALED_DUTY)
        {
            temp5 = -UB_InvMAXSCALED_DUTY;
        }
    #else
      if(temp5 > InvMAXSCALED_DUTY) //1/16 scaling artefacts and clampling between values that will give
        {
            temp5 = InvMAXSCALED_DUTY;
        }
        else if(temp5 < -InvMAXSCALED_DUTY)
        {
            temp5 = -InvMAXSCALED_DUTY;
        }
    #endif
        if (fInverterDriverFault == DRIVER_FAULT_ACTIVE)
        {
            // clear driver fault
            LATBbits.LATB7 = 1;
            
            // routine to recover from driver fault
            // if driver fault has occurred configure duty cycles to recover from fault
            if (sampleCount <= 255)
            {
                if (inverterOutputVoltage > inverterVoltageRef)
                {
                    fInverterDriverFault = DRIVER_FAULT_CLEARED;
                    LATBbits.LATB7 = 0;
                    temp4 = 0;
                }
                else
                {
     #ifdef BuildFor12_8KhzPWM_Inverter
                    inverterCurrentControlOutput += 10; // This also may need to change
                    if(inverterCurrentControlOutput > UB_INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = UB_INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #else
            inverterCurrentControlOutput += 10;
                    if(inverterCurrentControlOutput > INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #endif
                }
            }
            else
            {
                if (inverterOutputVoltage < inverterVoltageRef)
                {
                    fInverterDriverFault = DRIVER_FAULT_CLEARED;
                    LATBbits.LATB7 = 0;
                    temp4 = 0;
                }
                else
                {
     #ifdef BuildFor12_8KhzPWM_Inverter
                    inverterCurrentControlOutput -= 10;
                    if(inverterCurrentControlOutput < -UB_INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = -UB_INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #else
            inverterCurrentControlOutput -= 10;
                    if(inverterCurrentControlOutput < -UB_INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = -UB_INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #endif
                }
            }
        }
        else if (fInverterCurrentLimit == CURRENT_LIMIT_ACTIVE)
        {
            if (sampleCount <= 255)
            {
                if ((inverterOutputCurrent < INVERTER_CURRENT_MAX_PEAK) ||(inverterOutputVoltage > inverterVoltageRef) )
                {
                    fInverterCurrentLimit = CURRENT_LIMIT_CLEARED;
                }
                else
                {
     #ifdef BuildFor12_8KhzPWM_Inverter
                    inverterCurrentControlOutput += 2;
                    if(inverterCurrentControlOutput > UB_INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = UB_INVERTER_MAX_CONTROL_OUTPUT;//( is INVERTER_PDC_NOMINAL_VALUE)
                    }
     #else
            inverterCurrentControlOutput += 2;
                    if(inverterCurrentControlOutput > INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = INVERTER_MAX_CONTROL_OUTPUT;//( is INVERTER_PDC_NOMINAL_VALUE)
                    }
     #endif
                }
            }
            else
            {
               if((inverterOutputCurrent > -INVERTER_CURRENT_MAX_PEAK) ||(inverterOutputVoltage < inverterVoltageRef))
           {
                    fInverterCurrentLimit = CURRENT_LIMIT_CLEARED;
                }
                else
                {
     #ifdef BuildFor12_8KhzPWM_Inverter
                    inverterCurrentControlOutput -= 2;
                    if(inverterCurrentControlOutput < -UB_INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = -UB_INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #else
            inverterCurrentControlOutput -= 2;
                    if(inverterCurrentControlOutput < -INVERTER_MAX_CONTROL_OUTPUT)
                    {
                        inverterCurrentControlOutput = -INVERTER_MAX_CONTROL_OUTPUT;
                    }
     #endif
                }
            }
        }
        else
        {
            // if no driver fault present then use output of control loop for duty cycle
     #ifdef BuildFor12_8KhzPWM_Inverter
            inverterCurrentControlOutput = (int)((__builtin_mulss((int)temp5,(int)UB_InvPERIOD))>>15);
     #else
        inverterCurrentControlOutput = (int)((__builtin_mulss((int)temp5,(int)InvPERIOD))>>15);
     #endif
        }
        #endif

        #ifndef INVERTER_OPEN_LOOP
            /* Update PWM duty cycle for PWM1 and PWM2 */
     #ifdef BuildFor12_8KhzPWM_Inverter
            PDC1 = UB_InvHALF_PERIOD + inverterCurrentControlOutput;
            PDC2 = UB_InvHALF_PERIOD - inverterCurrentControlOutput;
     #else
      PDC1 = InvHALF_PERIOD + inverterCurrentControlOutput;
         PDC2 = InvHALF_PERIOD - inverterCurrentControlOutput;
     #endif
        #else
     #ifdef BuildFor12_8KhzPWM_Inverter
            PDC1 = UB_INVERTER_PDC_NOMINAL_VALUE + cmdInverterOpenLoop;
            PDC2 = UB_INVERTER_PDC_NOMINAL_VALUE - cmdInverterOpenLoop;
     #else
      PDC1 = INVERTER_PDC_NOMINAL_VALUE + cmdInverterOpenLoop;
            PDC2 = INVERTER_PDC_NOMINAL_VALUE - cmdInverterOpenLoop;
     #endif
        #endif

        if (sampleCount == SINE_TABLE_SIZE) //sine table size is 512
        {
            sampleCount = 0; /* Start from first data point on
                                                   sine lookup table after reaching
                                                   the end */
            if (fRMSCalculation == CALCULATION_DONE)
            {
                fRMSCalculation = READY_TO_COLLECT_DATA;
            }
        }
     #ifndef SkipFreqAdjustmentAndRelayActivation
        if ((mainsSampleCount == (mainsBufferSize - 125)))
        {
            if ((mainsState == MAINS_OK) && (_Q15abs(mainsBufferSize - SINE_TABLE_SIZE/2) <= 10))
            {
                inverterFreqAdjustment = 32;
            }
            else
            {
                inverterFreqAdjustment = 0;
            }

            if ((sampleCount >= (255 - inverterFreqAdjustment)) && (sampleCount < (269 - inverterFreqAdjustment)) )
            {
                fSwitchRelay = READY_TO_SWITCH;
                                                /* sampleCount = 410 means there are
                                                   4ms remaining for the end of sine
                                                   wave cycle. Begin switching relay
                                                   now so that total switch-over
                                                   time will be within specification
                                                   of 10ms. */
            }
        }
        #endif
        /* Save measured voltage and current values in buffers to calculate RMS
           values. Buffer size is only 128 so save once in 4 inverter interrupts
           to cover entire sine wave cycle */
        if (fRMSCalculation == READY_TO_COLLECT_DATA)
        {
            if ((sampleCount % 4 == 0) && (inverterInterruptCount == 0))
            {
                /* Save Measured Voltage */
                voltageRMSBuffer[RMSBufferCount] = inverterOutputVoltage;
                /* Save Measured Current */
                currentRMSBuffer[RMSBufferCount++] = inverterOutputCurrent;
            }
        }
        if (RMSBufferCount >= RMS_BUFFER_SIZE)//RMS buffer size 128
        {
            fRMSCalculation = READY_TO_CALCULATE;
            RMSBufferCount = 0;
        }
        
        /* Save previous filtered output voltage */
        prevFilteredVo = FilteredVo;

        /* Save previous output of voltage loop */
        //prevVoltageCmd = VoltageCmd;

        /* Save previous measured current */
        //prevInverterCurrent = inverterOutputCurrent;



    Thanks for reading



    Roy Thomas
    “Give a man a program, frustrate him for a day.
    Teach a man to program, frustrate him for a lifetime.”
    Muhammad Waseem
    #2
    Nikolay_Po
    Super Member
    • Total Posts : 1667
    • Reward points : 0
    • Joined: 2012/04/01 13:49:27
    • Location: Russia, Novorossiysk
    • Status: offline
    Re: Current control Algorithm porting to LF inverter 2018/01/13 10:10:32 (permalink)
    0
    Actually, your inverter is high frequency, not LF. You're use an LF transformer to eliminate DC/DC converter part. But the output voltage is creating by high frequency (not 50 or 60Hz).
    The problem is LF transformer phase delay. It will delaying the feedback. You need to simulate or experiment to tune the regulation.
    #3
    Jump to:
    © 2018 APG vNext Commercial Version 4.5