How to vary the output frequency of SPWM Inverter

Hi everyone! I am now working on VVVF inverter project. The outputs of the project are variable voltage and variable frequency. It means i have to vary amplitude and frequency. I have solved the amplitude issue, but not for the frequency issue. I don’t know where i should put the frequency formula in the code. So, could anyone tell me or give me some advice about how to make the output frequency of SPWM variable, please? I have read a reference from this link, but when i simulate the code, it didn’t works. Here is my code…

            int i=0;
            int j=0;
            int k=0;

            int x=0;
            int y=0;
            int z=0;

            int OK=0;
            int OK1=0;
            int OK2=0
            int OK3=0;
            int OK4=0;

            int sinPWM[]={1,2,5,7,10,12,15,17,19,22,24,27,30,32,34,37,39,42,
            44,47,49,52,54,57,59,61,64,66,69,71,73,76,78,80,83,85,88,90,92,94,97,99,
            101,103,106,108,110,113,115,117,119,121,124,126,128,130,132,134,136,138,140,142,144,146,
            148,150,152,154,156,158,160,162,164,166,168,169,171,173,175,177,178,180,182,184,185,187,188,190,192,193,
            195,196,198,199,201,202,204,205,207,208,209,211,212,213,215,216,217,219,220,221,222,223,224,225,226,227,
            228,229,230,231,232,233,234,235,236,237,237,238,239,240,240,241,242,242,243,243,244,244,245,245,246,246,
            247,247,247,248,248,248,248,249,249,249,249,249,255,255,255,255,249,249,249,249,249,248,
            248,248,248,247,247,247,246,246,245,245,244,244,243,243,242,242,241,240,240,239,238,237,237,236,235,234,
            233,232,231,230,229,228,227,226,225,224,223,222,221,220,219,217,216,215,213,212,211,209,208,207,205,204,
            202,201,199,198,196,195,193,192,190,188,187,185,184,182,180,178,177,175,173,171,169,168,166,164,162,160,
            158,156,154,152,150,148,146,144,142,140,138,136,134,132,130,128,126,124,121,119,117,115,113,110,108,106,
            103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,66,64,61,59,57,54,52,49,47,44,42,39,37,34,32,30,
            27,24,22,19,17,15,12,10,7,5,2,1};

            int potinput = A1;
            int potfreq = A2;
            float potinputval;
            float potfreqval;
            float A;
            float F;

            void setup() {
            Serial.begin(9600);

            pinMode(4, OUTPUT);
            pinMode(13,OUTPUT);
            pinMode(9,OUTPUT);
            pinMode(10,OUTPUT);
            pinMode(2,OUTPUT);
            pinMode(5,OUTPUT);

            cli();// stop interrupts
            TCCR0A=0;//reset the value
            TCCR0B=0;//reset the value
            TCNT0=0;//reset the value
            //0b allow me to write bits in binary
            TCCR0A=0b10100001;//phase correct pwm mode
            TCCR0B=0b00000001; //no prescaler

            TCCR2A=0;//reset the value
            TCCR2B=0;//reset the value
            TCNT2=0;//reset the value
            //0b allow me to write bits in binary
            TCCR2A=0b10100001;//phase correct pwm mode
            TCCR2B=0b00000001; //no prescaler

            TCCR3A=0;//reset the value
            TCCR3B=0;//reset the value
            TCNT3=0;//reset the value
            //0b allow me to write bits in binary
            TCCR3A=0b10100001;//phase correct pwm mode
            TCCR3B=0b00000001; //no prescaler
            TCCR1A=0;//reset the value
            TCCR1B=0;//reset the value
            TCNT1=0;//reset the value
            OCR1A=509;// compare match value
            TCCR1B=0b00001001; //WGM12 bit is 1 for CTC mode and no prescaler

            TIMSK1 |=(1 << OCIE1A);// enable interrupts

            sei();//stop interrupts
            }
            ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
            if(i>313 && OK==0){// final value from vector for pin 13
            i=0;// go to first value of vector
            OK=1;//enable pin 4
            }
            if(i>313 && OK==1){// final value from vector for pin 4
            i=0;//go to firs value of vector
            OK=0;//enable pin 13
            }
            x = round(A*sinPWM[i]); // x take the value from vector corresponding to position i(i is zero indexed)
            i=i+1;// go to the next position
            if(OK==0){
            OCR0B=0;//make pin 4 0
            OCR0A=x;//enable pin 13 to corresponding duty cycle
            }
            if(OK==1){
            OCR0A=0;//make pin 13 0
            OCR0B=x;//enable pin 4 to corresponding duty cycle
}

            if ((i==209) || OK1==1){//if i equal with 209 enable second signal
            OK1=1;//mantain if function
            if(j>313 && OK2==0){// final value from vector for pin 10
            j=0;// go to first value of vector
            OK2=1;//enable pin 9
            }
            if(j>313 && OK2==1){// final value from vector for pin 9
            j=0;//go to firs value of vector
            OK2=0;//enable pin 10
            }
            y = round(A*sinPWM[j]);// y take the value from vector corresponding to position j(j is zero indexed)
            j=j+1;// go to the next position
            if(OK2==0){
            OCR2B=0;//make pin 9 0
            OCR2A=y;//enable pin 10 to corresponding duty cycle
            }
            if(OK2==1){
            OCR2A=0;//make pin 10 0
            OCR2B=y;//enable pin 9 to corresponding duty cycle
            }
            }
            if ((j==209) || OK3==1){//if j equal with 209 enable third signal
            OK3=1;//mantain if function
            if(k>313 && OK4==0){// final value from vector for pin 5
            k=0;// go to first value of vector
            OK4=1;//enable pin 2
            }
            if(k>313 && OK4==1){// final value from vector for pin 2
            k=0;//go to firs value of vector
            OK4=0;//enable pin 5
            }
            z=round(A*sinPWM[k]);// z take the value from vector corresponding to position k(k is zero indexed)
            k=k+1;// go to the next position
            if(OK4==0){
            OCR3B=0;//make pin 2 0
            OCR3A=z;//enable pin 5 to corresponding duty cycle
            }
            if(OK4==1){
            OCR3A=0;//make pin 5 0
            OCR3B=z;//enable pin 2 to corresponding duty cycle
            }
            }
            }
           void loop() {
 
           potinputval = analogRead(potinput);
           A = potinputval/1023;       

           potfreqval = analogRead(potfreq);
           F = (potfreqval/1023)*100;}

I could not find your frequency related code in your horribly readable unstructured listing.

The linked code shows how the FREQ_POT is used to control the frequency.

DrDiettrich:
I could not find your frequency related code in your horribly readable unstructured listing.

I am so sorry for my unstructured code. I haven't put the frequency formula to the main code yet, because i don't know where i should put it.

DrDiettrich:
The linked code shows how the FREQ_POT is used to control the frequency.

Yes, but i don't really understand how it works. And when i simulate the code, the potmeter takes no effect. Hope you could help me

You have to modify the interrupt frequency. Where do you actually set the timer frequency, to which value?

Actually, i get the code from this article and this article. The author explained that he generates 50hz sine table with PWM frequency set to 31372Hz . And he explained in another post about frequency control value. Here is the value

OCR1A=509;// compare match value

DrDiettrich:
You have to modify the interrupt frequency.

So, is that still possible to modify the interrupt frequency? or maybe i should make another sine lookup table for 100Hz? (because this lookup table’s for 50hz).

Hi,
Can you tell us the hardware you are using please?

Thanks... Tom.. :slight_smile:

Hi Tom,
I am using an Arduino Mega, a custom-made gate driver (but i think gate driver IC is OK too), 3 Phase Bridge with 6 IRFP460 MOSFET, and 3 Phase LC low pass filter.

A Mega allows to generate 3 PWM signals of the same frequency from a single timer. You set the PWM frequency as appropriate, e.g. 31372Hz, and vary the duty cycles according to the sine wave table, so that you output each table entry once per output period. If the table has e.g. 50 entries, and you want an output frequency of 100Hz, you need a step (interrupt) rate of 50*100Hz.

To go from 50 Hz to 100 Hz change in the PWM values try using every other data point.

1,2,5,7,10,12,15,17,19,22,24,27,30,32....

1,5,10,15,19,24,30.... changes twice as fast

BTW, you only need half of those sine analog values, when you get from 1 to the second 255 you only need to count backwards to get the rest of your table.

@DrDiettrich, @GoForSmoke,

I am so sorry. I haven't explain this project clearly. And i also changed the topic. I need to vary the output frequency of this project, it means the output inverter can be vary from range 0 to 100Hz. The MEGA's output are 6 SPWMs at 31372 Hz. So, there are 3 phase output. The reason why PWM frequency at 31372 Hz used is for smooth sine inverter output. There are 314 sine table vector, which is using for half cycle periode at 25 Hz for the inverter output.

  1. R phase (pin 4 as half high-signal and pin 13 as half-low signal at 31372 Hz PWM frequency, which are made for 1 sine period and outputting 50 Hz frequency after filtered with LC filter)

  2. S phase (pin 9 as half high-signal and pin 10 as half-low signal at 31372 Hz PWM frequency, which are made for 1 sine period and outputting 50 Hz frequency after filtered with LC filter)

  3. T phase (pin 2 as half high-signal and pin 5 as half-low signal at 31372 Hz PWM frequency, which are made for 1 sine period and outputting 50 Hz frequency after filtered with LC filter).

The thing is, i can't vary the inverter output frequency at range 0 - 100 Hz. I think i should update the table to 50 Hz sine table ( half cycle, 25 Hz before ). Could you help me?

Have you by any chance seen what the audio-quality DACs on a Due can do?
Oh wait, only 2 channels.

The thing is, you even don't know how to achieve 50 Hz output frequency :frowning:

This frequency is determined by the timer1 interrupt rate. Modify the timer frequency to achieve other output frequencies.

50 Hz has a 20ms period to go 1 full wave LOW-->HIGH-->LOW as average ON% across a number of segments.

With default 2ms PWM there would be 10 steps, 18 degrees each. 100Hz would only get 5 steps, 36 degrees each.

With more steps the output gets smoother, the desired step length (PWM period) will be a small part of the output frequency.

With 32 steps per ms you make wavelengths over as many steps as it takes, hundreds for 50 Hz.