I am now on a 3 Phase SPWM inverter project, and i got this code from this article. It works perfectly on simulation. But the problem is, i can't make the output frequency variable. I intend to vary the frequency at range 0 to 100 Hz and use it to control the speed of 3 phase induction motor. Could anyone help me, please? Any advice or maybe you got a code that works perfectly in controlling spwm inverter frequency. Here is the code of 3 phase spwm inverter. Oh, i am using Arduino Mega by the way.

            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,

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

            void setup() {

            pinMode(4, 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
            OCR0B=0;//make pin 4 0
            OCR0A=x;//enable pin 13 to corresponding duty cycle
            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
            OCR2B=0;//make pin 9 0
            OCR2A=y;//enable pin 10 to corresponding duty cycle
            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
            OCR3B=0;//make pin 2 0
            OCR3A=z;//enable pin 5 to corresponding duty cycle
            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 = map(potfreqval,1023,0,0,50);}

In this sketch the PWM values, matching a sampled sine curve, are stored in integer array sinPWM[]. The values from sinPWM (1 - 255) are used unmodified (via intermediate variables x, y and z) to set the various timing registers (OCR0A/B, OCR2A/B and OCR3A/B) which control the pulse width modulation. In this way the amplitude(s) of the generated sine wave(s) will be constant.

If you want to control the speed of the motor you have to multiply the values from sinPWM with a factor between 0 and 1. The most logical place is to do that when the values from sinPWM are transferred to the intermediate variables x, y and z. Example: x=round(0.8 * sinPWM[i]). The factor, 0.8 in this example, you can of course replace by a variable which value is derived from an analogRead() of a pin connected to a potmeter or some sensor. But make sure to convert it to a value in the range 0-1 before you use it in the calculation.

| improve this answer | |
  • Ok.. I will try it. But could you tell me why I should multiply the value with a factor between 0 and 1, please? – Fitrah Hidayat Dec 24 '18 at 1:01
  • You feed the motor with three sine waves with a mutual phase difference of 120 degrees. The amplitude of the sine wave (= half of the top-top value) determines the speed of the motor. I say this with some reservation because there are many different types of electro motor. I assume you use a three phase motor with a squirrel-cage rotor. – PimV Dec 25 '18 at 9:10
  • Thanks for your reply. So i've tried the formula you've mentioned above without potmeter first ( i multiplied the sinPWM with value between 0-1), and it takes effect on duty cycle values. But when i connect the potmeter and improve the code, it didn't work. I think something's wrong with my analog converting formula. Would you mind to take a look to my code above, please? – Fitrah Hidayat Dec 26 '18 at 14:22
  • I will try. But could you first tell me the details about the motor you are using (do you have a datasheet, or manufacturer plus part number)? – PimV Dec 26 '18 at 16:06
  • I only have these 2 pictures. Please take a look. Image1 Image2 – Fitrah Hidayat Dec 27 '18 at 13:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.