Continue to Site

# PWM duty cycle update for Sinewave UPS

Status
Not open for further replies.

#### UroBoros

I am using a Dspic for doing PWM for a Sinewave inverter.

The sine reference update part I have some problems.

I read the reference value from a sinetable at 104 usec interval. I have the output voltage and current ADC value at that instant in hand. Can anybody suggest a simple method to calculate the duty cycle update value?

Thanks

You forgot to mention, what's your intended algorithm to calculate the PWM duty cycle, e.g. how an ADC is involved.

UroBoros

### UroBoros

Points: 2
The duty-cicle is exacly the sine value recorded at lookup table.
I did it in an UPS firmware and works fine.

+++

UroBoros

### UroBoros

Points: 2
A method to vary the amplitude of a sine wave.

Code:
#define MAXPWM  1000    /* Whatever your max pwm is? */
#define MAXVALUES 359   /* Size of look up table */

#define MAXVOLTS  16500U        /* Maximum pwm amplitude, choose to suit application */
#define MINVOLTS  5000U         /* Minimum pwm amplitude */

extern sinetable[];   /* Your sine table look up values */

unsigned int duty_cycle;
unsigned int amplitude;
unsigned int sine_table_index = 0;

/*--- Set duty cycle using a timer interrupt, change period register for frequency ---*/

duty_cycle = sinetable[sine_table_index];
duty_cycle = ((unsigned long)duty_cycle * (unsigned long)amplitude) >> 15;
duty_cycle = ((unsigned long)duty_cycle * (unsigned long)MAXPWM) >> 15;

if(++sine_table_index > MAXVALUES){
sine_table_index = 0;
}

/*--- Sinewave lookup table, 360 1 degree steps ---*/

const unsigned int sinetable[] = {
32500,33067,33634,34200,34767,35332,35897,36460,37023,37584,
38143,38701,39257,39810,40362,40911,41458,42002,42543,43080,
43615,44146,44674,45198,45718,46235,46747,47254,47757,48256,
48750,49238,49722,50200,50673,51141,51603,52058,52508,52952,
53390,53821,54246,54664,55076,55480,55878,56268,56652,57028,
57396,57757,58110,58455,58793,59122,59443,59756,60061,60357,
60645,60925,61195,61457,61710,61955,62190,62416,62633,62841,
63040,63229,63409,63579,63741,63892,64034,64167,64289,64402,
64506,64599,64683,64757,64821,64876,64920,64955,64980,64995,
65000,64995,64980,64955,64920,64876,64821,64757,64683,64599,
64506,64402,64289,64167,64034,63892,63741,63579,63409,63229,
63040,62841,62633,62416,62190,61955,61710,61457,61195,60925,
60645,60357,60061,59756,59443,59122,58793,58455,58110,57757,
57396,57028,56652,56268,55878,55480,55076,54664,54246,53821,
53390,52952,52508,52058,51603,51141,50673,50200,49722,49238,
48750,48256,47757,47254,46747,46235,45718,45198,44674,44146,
43615,43080,42543,42002,41458,40911,40362,39810,39257,38701,
38143,37584,37023,36460,35897,35332,34767,34200,33634,33067,
32500,31932,31365,30799,30232,29667,29102,28539,27976,27415,
26856,26298,25742,25189,24637,24088,23541,22997,22456,21919,
21384,20853,20325,19801,19281,18764,18252,17745,17242,16743,
16250,15761,15277,14799,14326,13858,13396,12941,12491,12047,
11609,11178,10753,10335,9923,9519,9121,8731,8347,7971,
7603,7242,6889,6544,6206,5877,5556,5243,4938,4642,
4354,4074,3804,3542,3289,3044,2809,2583,2366,2158,
1959,1770,1590,1420,1258,1107,965,832,710,597,
493,400,316,242,178,123,79,44,19,4,
0,4,19,44,79,123,178,242,316,400,
493,597,710,832,965,1107,1258,1420,1590,1770,
1959,2158,2366,2583,2809,3044,3289,3542,3804,4074,
4354,4642,4938,5243,5556,5877,6206,6544,6889,7242,
7603,7971,8347,8731,9121,9519,9923,10335,10753,11178,
11609,12047,12491,12941,13396,13858,14326,14799,15277,15761,
16250,16743,17242,17745,18252,18764,19281,19801,20325,20853,
21384,21919,22456,22997,23541,24088,24637,25189,25742,26298,
26856,27415,27976,28539,29102,29667,30232,30799,31365,31932
};

Last edited:
ismu and UroBoros

Points: 2

Points: 2
UroBoros

### UroBoros

Points: 2
Thanks for all the replays and especially that sin table.
I can generate Sine wave now.Got it.But how to adjust the duty cycle for voltage correction based on inverter load.
I am reading inverter output volt and current using two channel ADC every 104 uS (ON every sinetable update - I have
sinetable with 192 points) to track the waveform. But how to apply PID or any simple method to compensate load changes?

Thanks

If you are using MPLAB C30 compiler, in the \src\include\ directory you will find 'dsp.h'. At the end of that file you will find the function prototypes for a PID controller that is included in the library.
You could use that PID controller to control the amplitude of your sine wave.

ismu and UroBoros

Points: 2

### ismu

Points: 2
Thanks btbass. I will try that file.

Thanks for the help

I think, the multiple table solution provided by andre is good for tiny processor like pic16 or pic18, that has problems to carry out a multiply each PWM cycle. At PIC24 or dsPIC has a fast 16-Bit hardware multiplier and can use a single table, scaling the output. The voltage controller should use a measurement of averaged rectified value or even rms to adjust the duty cycle.

UroBoros

### UroBoros

Points: 2
I think, the multiple table solution provided by andre is good for tiny processor like pic16 or pic18, that has problems to carry out a multiply each PWM cycle. At PIC24 or dsPIC has a fast 16-Bit hardware multiplier and can use a single table, scaling the output. The voltage controller should use a measurement of averaged rectified value or even rms to adjust the duty cycle.

I am trying to implement this in assembly in PIC16F73.
Can you elaborate this method little bit more?
Thanks

My assumption holds that PIC16 has difficulties to multiply table values on the fly during pwm generation. So the multiple table method suggested in post #5 would be a more promising solution.

UroBoros

Points: 2