• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes

### 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
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.”

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;`

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