# 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):

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.

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:

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:

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

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:

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:

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”.

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:

The green signals are the others two combined.

A half sine wave:

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:

## 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.

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}

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 ????

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 …

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…

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

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

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!

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/

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.

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.

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.

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 .

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.

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.

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?

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!

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

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

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.

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!

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?

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?

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

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.

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.

19. Veng

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

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 🙂

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

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?

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?

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.

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.

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.

29. sanyi

How can we get OCR1A=509?

30. Gostei do artigo, muito bom…

31. yam

Hello sir,

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

you need a H bridge for a full sine wave

32. 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.

33. 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

34. VENG

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

Thank you

35. 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() {

}

36. 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 !