Search

How to generate a sine wave from arduino or atmega 328

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!

 

In this post we will discuss how to generate a sine wave modulated from different PWM signals. These technique it helps us to make pure sine inverters or to generate sine signals with different frequencyes.

As we know(from previous posts) some pins of arduino can generate PWM signals at high frequencies, so we will utilize this and adapt for sine equation. Let’s assume our frequency is 50Hz mean the time period is 20ms. So 10ms is half cycle period. In those 10ms we need to have many pulses with different duty cycles starting with small duty cycles, in the middle of the signal we have maximum duty cycles and finish also with small duty cycles.

To generate a sine wave we will use two pins one for positive half cycle and one for negative half cycle. In our post for this we use pins 5 and 6 that means Timer 0.

For a smooth signal we choose phase correct pwm at a frequency 31372 Hz-see previous post.

One of the biggest problem is that how we calculate the necessary duty cycle for each pulse.  So, because our frequency is f=31372Hz  the period for each pulse is T=1/31372=31.8 us, so number of pulses for a half cycle is N=10ms/31.8us=314 pulses. Now to calculate the duty cycle for each pulse we have y=sinx, but in this equation wee need degrees so half cycle has 180deg for 314 pulses.

For each pulse we have 180/314=0.57deg/pulse. That means for every pulse we move forward with 0.57deg.

Because it’s unpleasant to calculate each duty cycle by hand below it’s a small program that calculate the duty cycle between 0 and 90 deg( on serial monitor) and between 90 and 180 deg is in the mirror.

The program is:

float x=0;

float y=0;

const float pi=3.14;

int z=0;

float v=0;

int w=0;

void setup() {

Serial.begin(9600);

}

// the loop function runs over and over again forever

void loop() {

if (w==0){

v=x*pi/180; // making deg in radians

y=sin(v);   //calculate sine

z=y*250;    // calculate duty cycle(250 not 255 because will help to turn off transistors)

delay(100);

x=x+0.57;// increase the angle

}

if (x>90){// we stop to calculate we have the duty cycle for angles smaller than 90deg

// the other half is symetric

x=0;

w==1;

}

Serial.println(z);// on the serial monitor will appear duty cycles between 0 and 90 deg

}

Next we put the values in  a vector like:

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,250,250,250,250,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};

First value is 1 because we want to reduce the dead time betwen half cycles of sine signal.

To write the duty cycles we will use OCR0A and OCR0B for timer 0(pins  5 and 6), that means for one half cycle OCR0A will be equal with every component of vector myPWM and for other half cycle OCR0B will do that-see the post with Timer 0.

With the program below we generate phase correct signal at a 31372 Hz and 100 duty cycle(is between 0 and 255 on Timer 0).

void setup() {
pinMode(5, OUTPUT);
pinMode(6,OUTPUT);
TCCR0A=0;//reset the register
TCCR0B=0;//reset tthe register
TCCR0A=0b10100001;// phase correct pwm mode
TCCR0B=0b00000001;// no prescaler
OCR0A=100;//duty cycle
}
void loop() {
// put your main code here, to run repeatedly
}

The result is(only for pin 6, pin 5 is exactly like 6):

phase correct pwm timer 0 for spwm

But we want to alternate pins for each half cycle and make a variable duty cycle for each pulse. For this thing we use another timer(Timer 1) in CTC mode with interrupts. We generate a signal with the same frequency as frequency of  pins 5 and 6 and after each pulse we change the duty cycle(values from the vector) with an interrupt. At the end of the vector  we change pins(half cycle period) and start over.

An interrupt is a part of a program that pause the  loop function and execute another part of a program at a very specific time and after that start from where it was.

For this application we use a interrupt that is enabled when Timer 1 match with the OCR1A value. To change the duty cycle at every pulse on pins 5 and 6 we must generate interrupts with a 31372Hz (to enable one interrupt at the same time with an pulse on pins 5 and 6).

To generate that interrupt at every pulse we must set Timer 1 in CTC mode and for that we use TCCR1B register to make WGM12 =1 and CS10=1(no prescaling), OC1A must be set in toggle mode in TCCR1A register(COM1A1,COM1A0,COM1B1,COM1B0)see waveform generation mode bit description for Timer 1.

Now we must calculate the value for OCR1A to generate a 31372Hz signal. For that we use the formula from the datasheet with a smal modification, number 2 dissapear  fOC1A=fclk/N(1+OCR1A). Explication is that the formula with number  2 is for pwm and to have a frequency to a signal, the signal must be high and low and we wait two counts until compare match, one count before signal became low and one count before signal became high again(picture below). At interrupts when timer hits the compare match value the interrupt is generate, so number 2 dissapear.

interrupt frequency2

The value of OCR1A is determined from  OCR1A=(fclk/fOC1A*N)-1 and OCR1A=509.

So Timer 1 start counting until reach OCR1A=509 then activate the interrupt with a frequency 31372Hz.

To enable interrupts we need to set the OCIE1A=1 in TIMSk1 register and use ISR(TIMER1_COMPA_vect) (more details about interrupts here and here).

To be sure there is no problem with interrupts we will use cli() ( stop interrupts) and sei()(enable interrupts).

In ISR function we  set the OCR0A and OCR0B with duty cycle values and change this values according to vector, also at the finish of each crossing of vector we change the enabled pin.

Before sine wave we must see if it is everything ok so we have alternate the pins at a stable duty cycle OCR0A and OCR0B equals with 128.

The program for that is below:

int i=0;
int x=0;
int OK=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};

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

pinMode(5, OUTPUT);
pinMode(6,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
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 and no prescaler

TIMSK1 |=(1 << OCIE1A);

sei();// enable interrupts
}
ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
if(i>313 && OK==0){// final value from vector for pin 6
i=0;// go to first value of vector
OK=1;//enable pin 5
}
if(i>313 && OK==1){// final value from vector for pin 5
i=0;//go to firs value of vector
OK=0;//enable pin 6
}
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
if(OK==0){
OCR0B=0;//make pin 5 0
OCR0A=128;//enable pin 6 to corresponding duty cycle
}
if(OK==1){
OCR0A=0;//make pin 6 0
OCR0B=128;//enable pin 5 to corresponding duty cycle
}
}
void loop() {

}

 


 

As you can see we have in vector 314 elements and the program only 313 because at last we have the transition between pins, and on the oscilloscope we have a better frequency.

The results are:

SPWM with stable duty cycle

This image from oscilloscope has 5ms/div, so you can see that each signal has a 10ms period.

Another thing we can see here is time between switching pins.For that we reduce at 10us/div and the result is below:
SPWM switching time pins1

In the image below is represented the output signal from the two pins:sinus from arduino schematic

As you can see the output signal is a pwm signal with variable duty cycle and after the low pass filter(R=47ohms and C=22uF) appear a half sinus form.

To have a full sine wave you need to use a H bridge and command it with  these  two signals (before filter).

Because we visualise the signal on an oscilloscope we have the posibility to make math operation on signal so, if we apply a “minus operation”

we obtain a full sinus wave like from a H bridge.

The program below use a variable duty cycle:

int i=0;
int x=0;
int OK=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};

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

pinMode(5, OUTPUT);
pinMode(6,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
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 and no prescaler

TIMSK1 |=(1 << OCIE1A);

sei();// enable interrupts
}
ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
if(i>313 && OK==0){// final value from vector for pin 6
i=0;// go to first value of vector
OK=1;//enable pin 5
}
if(i>313 && OK==1){// final value from vector for pin 5
i=0;//go to firs value of vector
OK=0;//enable pin 6
}
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
if(OK==0){
OCR0B=0;//make pin 5 0
OCR0A=x;//enable pin 6 to corresponding duty cycle
}
if(OK==1){
OCR0A=0;//make pin 6 0
OCR0B=x;//enable pin 5 to corresponding duty cycle
}
}
void loop() {

}

Now the results before the low pass filter are:

variable dcycle pwm

In the image above the red signal is from pin 5 , yellow signal is from pin 6 and the green one is the “minus operation” between the other two.

Now, if we put the oscilloscope probes after filter we have:

arduino sinus oscilloscope

Again, with the program above(with a variable duty cycle) and a mathematichal function we have obtain the signal above but with  a H bridge you can obtain a pure sine wave and you can use it in pure sine inverters.

At last the frequency on this application is between 49.94 and 50.02 Hz, in the image below is only on channel 1 because the software of the oscilloscope can’t display the frequency of the “math signal”.

arduino sinus frequency

To make an update to this post next is a 60Hz signal.

Before the main program below is the program to generate  values for duty cycle(with some differences from the first-it will generate all the values from zero to zero).

The program is:

float x=0;
float y=0;
const float pi=3.14;
int z=0;
float v=0;
int w=0;
boolean OK=true;
void setup() {
Serial.begin(9600);
}
// the loop function runs over and over again forever
void loop() {
if (w==0){
v=x*pi/180; // making deg in radians
y=sin(v); //calculate sinus
z=y*250; // calculate duty cycle(250 not 255 because will help to turn off transistors)
delay(100);
if(OK==true){
x=x+0.689;// increase the angle
}
}
if (x>90){
OK=false;
}
if (OK==false){
x=x-0.689; //decreasing the angle for the other half
}
Serial.println(z);// on the serial monitor will appear duty cycles between 0 and 180 deg
}

Now the main program will consist 260 elements because at last we have the transition between pins, and on the oscilloscope we have a better frequency.

The main program is:

int i=0;
int x=0;
int OK=0;
int sinPWM[]={1,3,6,9,12,15,18,21,24,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,73,76,79,82,85,88,91,93,96,
99,102,104,107,110,112,115,118,120,123,126,128,131,133,136,138,141,143,146,148,151,153,155,158,160,
162,165,167,169,171,173,176,178,180,182,184,186,188,190,192,194,196,197,199,201,203,205,206,208,210,
211,213,214,216,217,219,220,222,223,224,226,227,228,229,230,232,233,234,235,236,237,238,239,239,240,
241,242,243,243,244,244,245,246,246,247,247,247,248,248,248,249,249,249,249,249,249,249,249,249,249,
249,249,248,248,248,247,247,247,246,246,245,244,244,243,243,242,241,240,239,239,238,237,236,235,234,233,
232,230,229,228,227,226,224,223,222,220,219,217,216,214,213,211,210,208,206,205,203,201,199,197,196,194,
192,190,188,186,184,182,180,178,176,173,171,169,167,165,162,160,158,155,153,151,148,146,143,141,138,136,
133,131,128,126,123,120,118,115,112,110,107,104,102,99,96,93,91,88,85,82,79,76,73,71,68,65,62,59,56,53,50,
47,44,41,38,35,32,29,26,24,21,18,15,12,9,6,3,1};

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

pinMode(5, OUTPUT);
pinMode(6,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
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 and no prescaler

TIMSK1 |=(1 << OCIE1A);

sei();// enable interrupts
}
ISR(TIMER1_COMPA_vect){// interrupt when timer 1 match with OCR1A value
if(i>260 && OK==0){// final value from vector for pin 6
i=0;// go to first value of vector
OK=1;//enable pin 5
}
if(i>260 && OK==1){// final value from vector for pin 5
i=0;//go to firs value of vector
OK=0;//enable pin 6
}
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
if(OK==0){
OCR0B=0;//make pin 5 0
OCR0A=x;//enable pin 6 to corresponding duty cycle
}
if(OK==1){
OCR0A=0;//make pin 6 0
OCR0B=x;//enable pin 5 to corresponding duty cycle
}
}
void loop() {

}

The results as pwm signals are:

variable-duty-cycle-at-60hz

The green signals are the others two combined.

A half sine wave:

half-cycle-sine-at-60hz

In this picture is presented only a half cycle because i have used only one low pass filter(i had only one capacitor) and you can see that the resulting frequency is 60.02 Hz.

The result are better than in the previous example because i have used film capacitor(1uF) and not electrolitic for the low pass filter  ( R=220 ohms).

Because someone ask me how to generate such a signal on pins 9 and 10 next is a program that generate a sine wave at 50Hz on pins 9 and 10:

int i=0;
int x=0;
int OK=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};

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

pinMode(9, OUTPUT);
pinMode(10,OUTPUT);

cli();// stop interrupts
TCCR1A=0;//reset the value
TCCR1B=0;//reset the value
TCNT1=0;//reset the value
//0b allow me to write bits in binary
TCCR1A=0b10100001;//phase correct pwm mode on 8 bits
TCCR1B=0b00000001; //no prescaler
TCCR0A=0b1000010;//WGM01 bit is 1 to put timer 0 in ctc mode
TCCR0B=0;//reset the value
TCNT0=0;//reset the value
OCR0A=63;// compare match value
TCCR0B=0b00000010; // prescaler 8

TIMSK0 |=(1 << OCIE0A);

sei();//enable interrupts
}
ISR(TIMER0_COMPA_vect){// interrupt when timer 0 match with OCR0A value
if(i>313 && OK==0){// final value from vector for pin 9
i=0;// go to first value of vector
OK=1;//enable pin 10
}
if(i>313 && OK==1){// final value from vector for pin 10
i=0;//go to firs value of vector
OK=0;//enable pin 9
}
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
if(OK==0){
OCR1B=0;//make pin 10 0
OCR1A=x;//enable pin 9 to corresponding duty cycle
}
if(OK==1){
OCR1A=0;//make pin 9 0
OCR1B=x;//enable pin 10 to corresponding duty cycle
}
}
void loop() {

}

On my oscilloscope i have obtained a frequency at 49.9 Hz.

A short video:

Facebooktwitterpinterest

Related posts

73 thoughts on “How to generate a sine wave from arduino or atmega 328

  1. matt lander

    Hi , thank you for this very very good tutorial , if I want to put the frequency of 60 Hz which should be the value of OCR2A ?? Thank you in advance.

    1. admin

      When we calculate the number of pulses we have N=10ms/31.8us=314pulses for 50Hz.For 60 Hz the period of this signal is 16.6ms and for half duty cycle is 8.3ms.
      Now N=8.3ms/31.8us=261pulses, so the only thing you need to change is the number of pulses and the duty cycle of them. In the vector you should have 261 elements(with different values from the our example) and in the ISR where appear 313 you must have 261(or 260 if give you an more precise frequency).

      1. matt lander

        Thank you sir for your reply, is what it is inside of these braces I have to put the 261 Elements ??
        float sinPWM[]={1,2,5,….1,2,5}

        1. admin

          Yes but i repead with your values. You can use the first program and change x=x+0.57; with x=x+0.83; because 180/216=0.83 and from serial monitor obtain the half of this values other half is in mirror.

          1. mattlander

            Sir if I make a UPS 120V 50 Hz, is that the 50 Hz will be a problem because the frequency is 60 Hz for 120 v and 50 Hz for 240V ????

          2. admin

            Yes you must have the same specification as the machines you want to power or the grid. Be aware that is a danger voltage i don’t have any responsibility if something go wrong!!!
            Try to understand all the aspects of the project.

  2. matt lander

    Hello sir, please can you make a tutorial where the frequency is 60 Hz? For weeks I try to do it but I can not .. thank you in advance sir…

  3. mattlander

    Hi Sir, right now I’m building a pure sine wave inverter for my house, your tutorial very well for me, but the only problem is the frequency, please sir can you help me find 60Hz, because I can not do it myself …

    1. admin

      I’ve uptated the article and in the bottom you will find the program for 60Hz(at results is only a half cycle because i have had only one low pass filter).
      If you want a good article for topology with mosfets here is something that look good(i haven’t build a h bridge for now so i can’t confirm the schematic)
      h bridge with mosfets
      Again i have no responsability if something go wrong!!!

  4. mattlander

    1000 thanks for your help Sir…1000 thanks…

    1. admin

      Glad i could help!
      When you finish the project maybe you’ll share the experience and the results.

  5. mattlander

    Yes Sir, i will share my projet when i finish…Sir what is the value of the film capacitor you use for the low-pass filter still 22 uf ?? Thanks

    1. admin

      Around 1uF(i have had three in paralel with small capacities(total 1.02 uF)) and a 220 ohms resistor.
      Be aware that for transistors you should use the pwm signal not filtered!

  6. matt lander

    Why, I should not filter the signal? I will use two IR2110 and IR3205 MOSFET for an H-bridge …
    http://4.bp.blogspot.com/-Lld4HStSKlw/UPvns0ckrZI/AAAAAAAAAaA/RFqfmsuv7bM/s1600/IR2110+-+7.png
    Thanks

    1. admin

      In the H bridge the input signal must be pwm, the filter is mounted after the H bridge, i repeat i haven’t build such a device, search more information about SPWM inverters!

    2. admin

      And for this project is more suitable a LC low pass filter.

  7. mattlander

    Hello sir how are you ? I think I’ll try the filtering technical where the filter capacitor is on the output of 220 volts transformer. … Link == >> http://www.instructables.com/id/Adaptable-24vDC220vAC-Pure-Sinewave-Inverter-1/

    1. admin

      Why not, i see it work for that project.

  8. Ariel

    Hello sir. thank you for share this knowledge. I try this soft with an arduino mega 2560 and only work using the pins 4 and 13. I try also with a attiny85 but it does not compile. Can it work with the attiny85? or just can’t? Thanks.

    1. admin

      I haven’t worked with attiny but from specifications it has the Timer 1 with just 8 bit and OCR1A in the program has a 509 value a lot higher than 255 max value for a 8 bit timer, so i don’t think it will work on attiny.

    2. admin

      Recently i have updated the post with a program for pins 9 and 10 which use OCR0A=63. You can try this program for your attiny85 to see if it is working.
      Hope that help!

  9. raheeel

    Hi sir i can try to upload this coding in ARDUINI UNO.campiling is good but not upload in aurduino.
    2:
    i can simulate arduino uno with coding in proteous but no any change in pin5, and pin 6 both pin still neutral and pin 12 change only.

    1. admin

      so you can’t upload the program to arduino uno???
      and for proteus i’ve an oscilloscope on pins 5 and 6 and they work perfectly.
      make sure you have complete program

  10. Hi Sir,
    Thank You very much for a helpfull toturial!
    To create 1*KHz sine wave , Which capasitor and resister can be used in the LP. filter .
    I can now create the PWM pulse put can’t get a fine sine wave! How can we know which RC Circuit is the best to the frequency.

    Best regards .

    1. admin

      For the capacitor and resistors values i used an online RC low pass filter calculator or, there are formulas for this kind of filters.
      Hope that help and sory for late response!

      1. Jaky lu

        Thanks a lot for sharing this with us.I need a 1KHZ sine wave with Arduino.How can I do this? Thanks in advance.

        1. admin

          First of all sorry for late response.
          In the second for this frequency arduino is a little to slow and maybe you will not be satisfied by result.
          If in the program from post i’ve used phase correct pwm here i’ve used fast pwm for 62500Hz. Also the array contain only 31 elements so the resolution is not great.
          The program is:
          int i=0;
          int x=0;
          int OK=0;
          float sinPWM[]={1,25,49,74,97,120,141,161,180,196,211,223,233,241,246,249,246,241,233,223,211,196,180,161,141,120,97,74,49,25,1};

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

          pinMode(5, OUTPUT);
          pinMode(6,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=0b10100011;//fast pwm mode
          TCCR0B=0b00000001; //no prescaler

          TCCR1A=0;//reset the value
          TCCR1B=0;//reset the value
          TCNT1=0;//reset the value
          OCR1A=255;// compare match value
          TCCR1B=0b00001001; //WGM12 bit is 1 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>30 && OK==0){// final value from vector for pin 6
          i=0;// go to first value of vector
          OK=1;//enable pin 5
          }
          if(i>30 && OK==1){// final value from vector for pin 5
          i=0;//go to firs value of vector
          OK=0;//enable pin 6
          }
          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
          if(OK==0){
          OCR0B=0;//make pin 5 0
          OCR0A=x;//enable pin 6 to corresponding duty cycle
          }
          if(OK==1){
          OCR0A=0;//make pin 6 0
          OCR0B=x;//enable pin 5 to corresponding duty cycle
          }
          }
          void loop() {

          }

          The results are:
          1 kHz sine unfiltered

          1 kHz sine filtered

          Also beacause arduino can’t generate negative voltage you must know that, with this signals you must enter in a hbridge to obtain a sine wave.
          The filter in this case is a RC with R=470ohms and C=0.1uF polyester.
          Hope that help!

          1. Jaky lu

            Hello, thanks for the last help, now I am doing plasma power, need 10kHz sine wave with Arduino, can you help out the design, thank you again in advance

  11. mark

    i am making dc to ac inverter. am is this sinewave is ok to fed to the gate of h bridge.

    1. admin

      Yes, but you must move the filter after the h bridge. In the bridge must enter an pwm signal.

  12. nuh

    Sir, How to generate on pin 9 and 10?

    1. admin

      At the end of the article i have posted (before the video) a program with a sine wave at 50Hz from pins 9 and 10.
      Hope that help!

  13. Mohammad

    Hi. How can you control the output voltage in case of using look up table? Can you write this software using flowcode

    1. admin

      What you mean “to control the voltage”???
      Amplitude or how???

      1. Mohammad

        I mean that, if the DC input voltage decrease or increase this will lead to decrease or increase the RMS output voltage of the inverter and also if the output Load decrease or increase this will lead to increase or decrease the RMS output voltage of the inverter because the look up table only at one case. May question is that how can you adjust or regulate the output voltage regardless the input voltage and load variation.

        1. admin

          It is a very good question but i don’t have the answer(i don’t know). I would let the sine part unmodified and on the input of the inverter you can mount an regulated dc-dc convertor or if you use the pull-push technology maibe there you can control the output voltage(again i don’t know about push-pull technology).
          sorry i couldn’t help!

  14. Mohammad

    Thank You very much .But I need just one stage (Inverter) to produce sinusoidal output voltage for reducing the size and cost.
    1) Is it possible to use multi look up table.Each table for one case. Such that:
    a) look up table 1 for output voltage 180V to 190V.
    b) look up table 2 for output voltage 190V to 200V.
    c) look up table 1 for output voltage 200V to 210V. And so on…
    2) Is it possible to use sine function instead of using look up table especially when using Atmega such as Atmega238p (Arduino Uno) or Atmega2560 (Arduino Mega).

  15. ed

    can this work on digispark? can it have variable frequency 25-100hz?

    1. admin

      I see that this digispark use attiny85 and i have never use this device. I know that attiny has only 8 bit register(OCR1A=509 and 8 bits=255) so with the first program won’t work, but i have updated the post with a program for pins 9 and 10(on arduino uno) which use OCR0A=63 and this maybe will work on attiny.
      Hope that help!
      Sorry for late response!

  16. ThaiLam

    I have created a single phase sine wave. But how to feedback output 220v used adc. Can you help me? Send me sample code?

    1. admin

      From what you wrote i don’t understand what you want.
      Please give me more details about what you want to do to see if i can help you!

      1. ThaiLam

        I used H bridge PWM to generate sine waves. I want to change the amplitude of the sine wave (50hz constant frequency). How do I change the ?

  17. veng

    Thanks for your post!

    i am not doing the H-Bridge, i like have a full sine wave PWM modulation at the one pin reference GND, How does this code modify to?

  18. veng

    Admin,
    Keep the circuit configuration as same as what you did. Could you modify the CODE make both of PIN 5, PIN6 as full sine wave instead of half wave, one of them has 90 degree phase shift?

    Thank you again.

    1. admin

      Hello!
      To generate a full sine wave on a pin you must generate a negative voltage for the negative half duty cycle of the sine wave.
      I don’t know if something like that is possibile with arduino.
      Sorry i couldn’t help you!

  19. Veng

    Admin,
    Could you move X Axis from 0 to middle of 5V, cycle positive from 2.5V to 5.0V, negative from 2.5V to 0V, this whole picture will be full wave.

    Sorry, I am afraid this topic is suitable here. However I did read your ?site, the technology and your skill seems fully opening.
    May I ask you? Is this site representing research agency? School? Manufacturing? forum?

    Thanks again

    1. admin

      Thank you for advices!
      It’s a small blog with electronic projects that are in my area of ​​knowledge.

  20. azam

    hi there..
    there a line in 50 Hz source code “OCR0A=63; // compare match value

    can you explain where does the “63” come from?
    much appreciated 🙂

    1. admin

      Like in the first example when the interrupt is triggered by timer 1 and it has a 31372Hz frequency, OCR1A is 509.
      For the example where timer0 is for interrupt i have used the same formula OCR1A=(fclk/fOC1A*N)-1, where instead of OCR1A appear OCR0A.If the OCR1A was equal with 509, beacause the timer 0 has only 8 bits it’s maximum is 255 so i have used a prescaler N=8.
      So if you make in the formula OCR0A=63 and N=8 the frequency obtain is 31372 as we want.
      Hope that help!

      1. azam

        thanks for your response.. 🙂
        one more question. in SPWM theory there is an index called amplitude modulations comes with equation :
        ma = Ar/Ac = Vm ref / Vm carrier ;
        does this equation is mentioned in the source code? or can we calculate it with the code above?
        sorry for being a newbie here..
        much appreciated 🙂

  21. Veng

    Thanks for the posting, it was awesome!
    Could you add another code which is soft start. In other word the sine wave frequency increases slowly from 1Hz to 50Hz(60Hz) few seconds?

  22. nerdBishop

    please why doesnt any of the code go in void loop()

    1. admin

      Because the loop is used for the part for the program used for processing and control and the program presented is like setting the arduino. With this code the outputs are set tho generate a specific waveform something like bios for a pc right in the registers and so you have more speed in processing- i hope you understand what i want to say

  23. jack

    sir, i wat to make the frequecy adjustable by plugin in variable potensio meter(analogread)..how to modify this code?

    1. admin

      For the moment i can’t help, and i say tht because i have tried to do this but the result are not good enough. To modify the frequency is necessary to modify the values from the array and this will affect the output sine wave. Sorry this thing is over my knowledge.

  24. jack

    much appreciate sir, so code part that influence frequency is the array, right..thats answer my question..ill figure something else then also by adding active low pass filter at the output of my arduino. thx again

  25. Christian Egbekoba

    Hi, I implemented the 50hz code and a got a sweet output with no noise on my transformer.thanks

    Just one, how do I stabilizer the output to be a constant voltage. I.e, when I add a load, the output voltage goes up.(e.g from 220 to 230)

    Is there a way code can maintain output supply for a given battery voltage range?

    1. admin

      Hi, i’m glad to hear that it’s worked. And for the voltage stalizer i can’t help you, because i haven’t try to do such things….sorry 🙁

  26. Stan

    Can anyone please help me, with what I have to change, if I want a 10 Hz, sine?
    I`ve calculated the new sine values (and these are a lot).

  27. Markus

    Hi. As I understand your concept is working with fixed tables for generating the frequency – as explained above, e.g. 261 elements for 50Hz, 314 elements for 60Hz. Do you see a chance to work with variable freqencies, and in doing so having the possibility to fine tune the frequency lateron (e.g. with a potentiometer)? I would very much appreciate your comments and / or some example code.

    1. admin

      Hi!
      To create such a project arduino must calculate the values from array very fast and i’m afraid that uno is a bit slow for that and also generate the pulses. I don’t know if an arduino due can do this.
      Sorry i couldn’t help you because it is a bit hard that it seems.

  28. bashir

    hello sir, your articles really helps me a lot.
    but whenever i tried to simulate all the codes that uses pin 5 and 6 output in proteus, i get no single pulse other than a straght line, except the code that uses pin 9 and 10 as output that gave me the half sine pulse. pls what can i do sir? as it needs to work before i can place it in pcb layout.

    1. admin

      i don’t know what is the problem in proteus but the images from the post are from an oscilloscope and in my case worked very well.
      sorry couldn’t help you

  29. sanyi

    How can we get OCR1A=509?

  30. yam

    Hello sir,

    could you please help to generate a full sine wave,i did half sine wave

    1. admin

      you need a H bridge for a full sine wave

  31. Abdullah

    Hey Man, thank you for the good work this is really helpful. I am having a problem though with using this code on the Arduino Mega 2560 (ATmega2560). I tried the same code as the one above but I can’t see anything on the oscillioscope.

  32. Jason

    Hello! First, I love your post!

    Second, I have designed and built a tripple H-Bridge circuit which is controlled by an Arduino Nano. (Atmega328) I use all the PWM pins – 3, 5, 6, 9, 10, 11 to control hi & low of each phase. I can vary the frequency, but outputting a square wave makes the motor very choppy.

    Now I would like to adapt your code to generate the sin waves exactly as you have above, but with three phases that are 120 deg apart from each other. I’m not expecting to vary the frequency at this point. 50 or 60 Hz is fine initially. I’m just wondering if there’s an easy way to generate the same signal 120 deg and 240 deg offset from the signal you’ve already created on two of the PWM pins.

    Any suggestions?

    Thanks!

    -Jason

  33. VENG

    I did the full sine wave output on one pin with this code!
    Can this code upload to ATTiny44?

    Thank you

  34. baruti

    this is good code

    int i=0;
    int x=0;
    int OK=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};

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

    pinMode(9, OUTPUT);
    pinMode(10,OUTPUT);

    cli();// stop interrupts
    TCCR1A=0;//reset the value
    TCCR1B=0;//reset the value
    TCNT1=0;//reset the value
    //0b allow me to write bits in binary
    TCCR1A=0b10100001;//phase correct pwm mode on 8 bits
    TCCR1B=0b00000001; //no prescaler
    TCCR0A=0b1000010;//WGM01 bit is 1 to put timer 0 in ctc mode
    TCCR0B=0;//reset the value
    TCNT0=0;//reset the value
    OCR0A=63;// compare match value
    TCCR0B=0b00000010; // prescaler 8

    TIMSK0 |=(1 <313 && OK==0){// final value from vector for pin 9
    i=0;// go to first value of vector
    OK=1;//enable pin 10
    }
    if(i>313 && OK==1){// final value from vector for pin 10
    i=0;//go to firs value of vector
    OK=0;//enable pin 9
    }
    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
    if(OK==0){
    OCR1B=0;//make pin 10 0
    OCR1A=x;//enable pin 9 to corresponding duty cycle
    }
    if(OK==1){
    OCR1A=0;//make pin 9 0
    OCR1B=x;//enable pin 10 to corresponding duty cycle
    }
    }
    void loop() {

    }

  35. Michael

    Hello sir, thank you for sharing this article.

    Is there any way in which you can control when to start the generation of pulses. I am doing an inverter and I need to adjust the phase of the grid to the phase of my inverter therefore the best way to it is to start the PWM parallely with the grid .

    Thank you !

    1. admin

      i think that to adjust the phase from the inverter with the grid is a little bit above the arduino power…i know this parallel from a source with a grid are made with synchronscopes and other specialized relays…be carefull i’m not responding if something goes wrong especialy if you work with high voltage

Leave a Comment

Show Buttons
Hide Buttons