How to generate three phase spwm signal with arduino

Please let us in the comment zone any suggestions that you think will improve the article!

If you like the article click the follow button  to stay in touch with us!



As you can see in last two post about sine waves (How to generate a sine wave from arduino or atmega 328 and How to generate two phase sine waves with arduino) is not as hard as you think to generate such signals so, in this post i will generate three phase sine wave signals at 120 degrees phase shift.

Because arduino uno has three timers and one of them is used for interrupt it can not be used anymore so i have used an arduino mega.

Arduino mega has an atmega 2560 onboard with five timers and 15 pwm capable pins.

Let’s see the corresponding between timers and pins:

-Timer 0-pin 4 (OC0B) and pin 13(OC0A)

-Timer 1-pin 11(OC1A) and pin 12(OC1B)

-Timer 2-pin 9(OC2B) and pin 10(OC2A)

-Timer 3-pin 2(OC3B), pin 3(OC3C) and pin 5(OC3A)

-Timer 4-pin 6(OC4A), pin 7(OC4B) and pin 8(OC4C)

-Timer 5-pin 44(OC5C), pin 45(OC5B) and pin 46(OC5A)

For this project i use Timer 1 for interrupt like in the previous post Timer 0 for first phase, Timer 2 for the second phase and Timer 3 for the third phase with OCxA for positive half duty cycle and OCxB for the negative half duty cycle like in the picture below:

three phase system

As you can see in the previous post with two phase, if for 180 degrees we have 314 elements , for 120 degrees we have 209 elements so the second signal must start when the first is at 209 pulse and the third must start when the second is at 209 pulse.

So, when the program starts, the interrupt is enabled and first is executed the first signal part(with element i). When i take the 209 value the second signal is enabled(with element j). When j take the 209 value the third signal is enabled. In this way these three signal are at 120 degrees phase shift.

To ensure the phase shift we use an “if” function and  for the second wave is like below:

“if ((i==209) || OK1==1){

When “i” has 209th value the “if” function is enabled  and everything in it is executed. To mantain the execution of that part for the second signal after the value of i(209) is changed we use a variable which enables the “if” function continuously.

For the third signal the if function is like below:

“if ((j==209) || OK3==1){

In this case, the third signal is enabled when  “j” (the element for the second signal)  has the 209th value. After that, the “if” function is executed like for the second signal.

Because i have an oscilloscope with only two channels, next i will present these signals in pairs.

Some signals will be inverted from the oscilloscope software to simulate like they are driving a H bridge on the negative half duty cycle, but reported to arduino GND they still have 5 V.

As you can see in the picture above i have used Timer 0 for first signal, Timer 2 for the second and Timer 3 for the third.

Timer 0-pin 4 (OC0B) and pin 13(OC0A)

Timer 2-pin 9(OC2B) and pin 10(OC2A)

Timer 3-pin 2(OC3B), pin 3(OC3C-not used in this example) and pin 5(OC3A)

First let’s see the first signal.

For that we use OC0A and OC0B pins(13 and 4). On the oscilloscope, the negative half duty cycle(from pin 4) is inverted in order to appear like a negative half duty cycle.

phase one with arduino

In the image below we have the positive half duty cycle of the first and the second signals OCR0A and OCR2A(pin 13 and pin 10)

positive half dutycycle from signal 1 and 2 arduino

The red signal is from pin 13 OCR0A and the yelow one from pin 10. The time delay between them is 6 .640 ms, almost like 6.66 for 120 degrees phase shift.

Next is shown the positive half duty cycle of the first signal(pin 13) and the negative of the second signal(pin 9) inverted:

positive half dutycycle from signal 1 and negative from 2 arduino

The time delay between the start of the positive duty cycle of the first signal  and the negative of the second signal is 16.64ms.

These 16.64ms results from the 6.64ms delay between positive half duty cycles of the first signal and the positive of the second and 10 ms for one half duty cycle(50Hz signal).

The positive duty cycle of the first signal(pin 13) and positive of the third(pin 5) is:

positive half dutycycle from signal 1 and 3 arduino

Time delay between these two is 13.36 ms almost 13.32 for 240 degrees phase shift.

The same duty cycles but from the second(pin 10) and third(pin 5) signal are:

positive half dutycycle from signal 2 and 3 arduino

The results are identical with the results between signal 1 and signal 2 also with 6.640ms delay.


The program for this project is:
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,

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=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=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=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() {




Related posts

16 thoughts on “How to generate three phase spwm signal with arduino

  1. Rv

    you can send me the program for Arduino but in a single phase

  2. Youssef

    thank you a lot, much love

  3. burak

    ı think its broken code , i looked it on my own osiloscobe and it wasnt a sin wave. What is the problem can anyone help me

  4. PimV

    I understand that you are generating a square wave with a duty cycle corresponding to a sine curve (in fact 3 square waves with a 120 degrees phase shift). As far as I can see, the amplitude of these square waves is 5V. What I don’t understand is how you make sinus curves from these square waves.

    1. admin

      hello this 5V is command voltage…to obtain a sine you must use a H bridge…or three if you use three phase code and a low phase filter

  5. Carlos Hernandez

    Hi sir, do you think this code could work for my arduino uno? My project is a 3ph pwm inverter using PC817 optocoupler with a IR2112 as a driver and i was trying to make it work with pins 2,3,4,5,6,7 as an outputs but i have no good results, so my question is if i can use your code in this project?

    1. admin

      the code should work but not with arduino…it hasn’t had enough pin, with a arduino mega should work pretty well
      sorry for late response

      1. carlos hernandez

        Hi there, this a very helpful, can you send me the 3ph code? I tried with this one but something is wrong may be if you send the code ready to put it into the arduino board.

        Carlos Hernandez

      2. Carlos Hernandez

        Carlos Hernandez Hi, i still have problemas with my 3ph 60 hertz arduino inverter project. Can you help with the final code for this? 3ph inverter with arduino mega 2560

        Yhanks a lot:

  6. ERK

    thank you very much

  7. carlos hernandez

    Guy you are some of a kind, i say thank you from my heart for this code, i will work on this immediately it is for a good cause project.

    I`ll let you know how iam doing

    1. admin

      would be great to share your work with us 🙂

  8. Carlos Hernandez

    Hi there, you know iam working with this project and all i get is 4 vac 496hz in each phase, iam using a 24 vac 60 hz as an ac input, can you help me with this? Iam not that sure to move the arduino that is why need your help

  9. Carlos Hernandez

    Hi is me again, in my past comment i made a mistake it is a 49.6 hz instead of 496 hz but voltage still the same 4 vac each phase


  10. carlos hernandez

    Hi,i made some testings and it looks the transistor gate voltage is not enough so i will rise the voltage and see how it works.

    Will let you know the final results, thanks again

Leave a Comment

Show Buttons
Hide Buttons