₦airaland Forum

Welcome, Guest: Join Nairaland / LOGIN! / Trending / Recent / New
Stats: 1,929,448 members, 3,975,308 topics. Date: Monday, 18 December 2017 at 08:09 AM

Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) - Career - Nairaland

Nairaland Forum / Nairaland / General / Career / Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) (638 Views)

Apply Now For The Wave 6 Microsoft Graduate Internships In Lagos, Nigeria / Career Tips By WAVE Academies / How Do I Start Up A Pure Water Production Company (1) (2) (3) (4)

(0) (Reply) (Go Down)

Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:39am On Nov 21
I teach you how to build a pure sine wave inverter with arduino or (atmega328), in one month.
The tutorial is in two stage, namely; the programming stage and the hardware build stage.
In the programming stage, I will teach you the art of programming an Arduino so as to produce a sine wave signal.
In the second stage, I will tech you how to build the electronic circuit for switching the low voltages and stepping it up to the required high voltage vise versa..
Be you a novice, beginner or intermediary in the field.
Owing to the fact that the programming of an Arduino is so vast and broad a topic. I have put down a well laid down curriculum which chiefly selects the relevant topics which are instrumental to the successful programming of an Arduino to generate sine wave.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:40am On Nov 21
At the end of the tutorial, you will be able to master the coding or programming of an Arduino to produce pure sine wave, also called; sinusoidal pulse width modulation (sPWM), to run on frequencies of your choice.

In a nutshell, I will be discussing in this post, how to generate a sine wave modulated from different PWM signals.
With these technique, we can make pure sine inverters or generate sine signals with different frequencyes.
As with anything programming, there are several methods which can be used to generate sinusoidal pulse width modulated signals using Arduino. But I shall settle for the method which I am going to explain in this post.
Mind you, it does not really matter which method you use. What really matters most is the generation of the sinusoidal pulse width modulated signals at the output if the Arduino pins.
The smart ones out there might end up successfully putting the piece of codes presented here together and have a working prototype. Some might want a thorough tutorial on it..
Any interested persons should contact me through the above number or email.
I offer online tutorial or live tutorial.. I also sell E-book on the topic..
I will answer any questions you throw at me. But try and read through the explanations carefully so that you will ask a better question. By doing so, everyone will learn from it when I answer your questions.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:41am On Nov 21
WHAT IS AN ARDUINO?
Arduino is an open source computer hardware and software company. it is also a project and user community that designs and manufactures
single-board microcontrollers and
microcontroller kits for building digital devices and interactive objects that can sense and control objects in the physical world.
The project's products are distributed as open-source hardware and software , which are licensed under the GNU Lesser General Public License (LGPL) or the GNU General Public License (GPL). This License permits the manufacture of Arduino boards and software distribution by anyone.
Arduino boards are available commercially in preassembled form, or as do-it-yourself (DIY) kits.
The picture below is an Arduino Uno board.

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:41am On Nov 21
Arduino board designs use a variety of microprocessors and controllers. The boards are equipped with sets of digital and analog, input/output (I/O) pins that may be interfaced to various expansion boards (shields ) and other circuits. The boards feature serial communications interfaces, including Universal Serial Bus (USB) on some models, which are also used for loading programs from personal computers. The microcontrollers are typically programmed using a dialect of features from the programming languages C and C++ . In addition to using traditional compiler toolchains, the Arduino project provides an integrated development environment (IDE) based on the Processing language project.
The Arduino project started in 2003 as a program for students at the Interaction Design Institute Ivrea in Ivrea, Italy, aiming to provide a low-cost and easy way for novices and professionals to create devices that interact with their environment using sensors and actuators..
Common examples of such devices intended for beginner hobbyists include; simple robots, thermostats, led display, security alarm and motion detectors etc .
The name Arduino comes from a bar in Ivrea, Italy, where some of the founders of the project used to meet. The bar was named after Arduin of Ivrea, who was the margrave of the March of Ivrea and King of Italy from 1002 to 1014.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:42am On Nov 21
ARDUINO PWM PIN.
As has been explained in the data sheet, some pins of the arduino can generate PWM signals at high frequencies, so we will utilize this and adapt it for sine equation.
Let’s assume our frequency is 50Hz; meaning the time period is 20ms. So 10ms should be the half cycle period.
In these 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 this tutorial, we use pins 5 and 6. That means Timer 0 .
For a smooth signal we choose phase correct pwm at a frequency 31372 Hz..
One of the biggest problem is how to 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 we need degrees..
So half cycle has 180deg for 314 pulses.
So, 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 is a small program that calculate the duty cycle between 0 and 90 deg( on serial monitor) and between 90 and 180 deg, which is the mirror of the first 0-90 deg.
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
}
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:43am On Nov 21
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,
195,196,198,199,201,202,204,205,207,208,209,211,
228,229,230,231,232,233,234,235,236,237,237,238,
247,247,247,248,248,248,248,249,249,249,249,249,
248,248,248,247,247,247,246,246,245,245,244,244,
233,232,231,230,229,228,227,226,225,224,223,222,
202,201,199,198,196,195,193,192,190,188,187,185,
158,156,154,152,150,148,146,144,142,140,138,136,
103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,
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.
With the program below we generate phase correct signal at a 31372 Hz and 100 duty cycle
(this 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 picture below is a scope shot of the signal emanating from pin 6. So the result is only for pin 6, pin 5 is exactly like 6, but out of phase. Lagging with a degree of 180 deg:

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:44am On Nov 21
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 f =f /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.

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:45am On Nov 21
The value of OCR1A is determined from OCR1A=(f /f *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
101,103,106,108,110,113,115,117,119,121,124,126,
148,150,152,154,156,158,160,162,164,166,168,169,
195,196,198,199,201,202,204,205,207,208,209,211,
228,229,230,231,232,233,234,235,236,237,237,238,
247,247,247,248,248,248,248,249,249,249,249,249,
248,248,248,247,247,247,246,246,245,245,244,244,
233,232,231,230,229,228,227,226,225,224,223,222,
202,201,199,198,196,195,193,192,190,188,187,185,
158,156,154,152,150,148,146,144,142,140,138,136,
103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,
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() {
}
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:46am On Nov 21
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:

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:47am On Nov 21
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:

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:47am On Nov 21
In the image below is represented the output signal from the two pins:

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:48am On Nov 21
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
101,103,106,108,110,113,115,117,119,121,124,126,
148,150,152,154,156,158,160,162,164,166,168,169,
195,196,198,199,201,202,204,205,207,208,209,211,
228,229,230,231,232,233,234,235,236,237,237,238,
247,247,247,248,248,248,248,249,249,249,249,249,
248,248,248,247,247,247,246,246,245,245,244,244,
233,232,231,230,229,228,227,226,225,224,223,222,
202,201,199,198,196,195,193,192,190,188,187,185,
158,156,154,152,150,148,146,144,142,140,138,136,
103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,
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() {
}
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:50am On Nov 21
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
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,
99,102,104,107,110,112,115,118,120,123,126,128,1
162,165,167,169,171,173,176,178,180,182,184,186,
211,213,214,216,217,219,220,222,223,224,226,227,
241,242,243,243,244,244,245,246,246,247,247,247,
249,249,248,248,248,247,247,247,246,246,245,244,
232,230,229,228,227,226,224,223,222,220,219,217,
192,190,188,186,184,182,180,178,176,173,171,169,
133,131,128,126,123,120,118,115,112,110,107,104,
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() {
}
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:53am On Nov 21
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
101,103,106,108,110,113,115,117,119,121,124,126,
148,150,152,154,156,158,160,162,164,166,168,169,
195,196,198,199,201,202,204,205,207,208,209,211,
228,229,230,231,232,233,234,235,236,237,237,238,
247,247,247,248,248,248,248,249,249,249,249,249,
248,248,248,247,247,247,246,246,245,245,244,244,
233,232,231,230,229,228,227,226,225,224,223,222,
202,201,199,198,196,195,193,192,190,188,187,185,
158,156,154,152,150,148,146,144,142,140,138,136,
103,101,99,97,94,92,90,88,85,83,80,78,76,73,71,69,
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() {
}
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 2:00am On Nov 21
You can reach me through my details below.

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 10:43pm On Nov 23
HOW TO GENERATE SPWM SIGNALS WITH ATMEGA16
The microcontroller I’ve chosen is the ATMEGA16. However, the concept can be used on any AVR that has a PWM module. The output sine wave is to have a frequency of 50Hz. I have chosen to use a switching frequency of 16kHz for SPWM.
So, here I talk about how to generate sine wave using sinusoidal pulse width modulation (SPWM) signals using the PWM module as can be commonly found on most Atmel AVR microcontrollers.
Now let's move on to sine wave generation using ATMEGA16.
Let’s take a look at the code first:
//---------------------------------------------------------------------------------
//Programmer: Pakingzzzzz
//Target Microcontroller: ATMEGA16
//Compiler: mikroC PRO for AVR (Can easily port to any other compiler)
//---------------------------------------------------------------------------------
unsigned int sin_table[32]={0, 100, 199, 296, 390, 480, 566, 645, 718,
783, 840, 889, 928, 958, 979, 989, 989, 979, 958, 928, 889, 840, 783,
718, 645, 566, 480, 390, 296, 199, 100,0};
#define MOSA PORTD0_bit
#define MOSB PORTD1_bit
#define MOSC PORTD2_bit
#define MOSD PORTD3_bit
unsigned char FlagReg;
#define Direction FlagReg.B0
//0 -> MOS A + D
//1 -> MOS B + C
unsigned int TBL_POINTER_NEW, TBL_POINTER_OLD, TBL_POINTER_SHIFT, SET_FREQ;
unsigned int TBL_temp;
unsigned char DUTY_CYCLE;
void interrupt() org IVT_ADDR_TIMER1_OVF{
TBL_POINTER_NEW = TBL_POINTER_NEW + SET_FREQ;
if (TBL_POINTER_NEW < TBL_POINTER_OLD){
if (Direction == 0){
MOSA = 0;
MOSD = 0;
MOSB = 1;
MOSC = 1;
Direction = 1;
}
else{
MOSB = 0;
MOSC = 0;
MOSA = 1;
MOSD = 1;
Direction = 0;
}
}
TBL_POINTER_SHIFT = TBL_POINTER_NEW >> 11;
DUTY_CYCLE = TBL_POINTER_SHIFT;
TBL_POINTER_SHIFT = sin_table[DUTY_CYCLE];
OCR1AH = TBL_POINTER_SHIFT >> 8;
OCR1AL = TBL_POINTER_SHIFT & 0x0F;
TBL_POINTER_OLD = TBL_POINTER_NEW;
}
void main() {
SET_FREQ = 410;
TBL_POINTER_SHIFT = 0;
TBL_POINTER_NEW = 0;
TBL_POINTER_OLD = 0;
DUTY_CYCLE = 0;
DDRC = 0xFF;
DDRD = 0XFF;
OCR1AH = 0;
OCR1AL = 0;
TCCR1A = 0x82;
ICR1H = 0x03;
ICR1L = 0xE7;
//ICR1 = 999 -> TOP -> 16kHz
TIMSK = 0x04;
TCCR1B = 0x19;
SREG_I_bit = 1;
while(1);
}
That’s the code. Quite simple really. And pretty short!
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 10:43pm On Nov 23
Now let's analyze the code and see what I've done.
Here, I’ve used the Fast PWM mode. I chose to use an oscillator frequency (for ATMEGA16) of 16MHz and an SPWM switching frequency of 16kHz. For this, I selected ICR1 as the TOP and assigned 999 to ICR1. I used a prescaler divider (N) = 1. I used PWM mode 14. So that gives a switching frequency of:

Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 10:44pm On Nov 23
In PWM mode 14, ICR1 sets TOP and OCR1 sets the duty cycle.
I’ve assigned 0x82 to TCCR1A and 0x19 to TCCR1B. This sets PWM mode to mode 14. This also sets Compare Output mode for OCR1A to non-inverting mode: Clear OCR1A on compare match, clear at BOTTOM. I have selected the sine table such that the peak value is smaller than TOP. To generate the sine table, I used my software “Smart Sine” with a peak value of 990. Also notice how there’s a zero at the beginning and ending of the sine table. These act to create a “deadtime” so that there isn’t a short circuit due to cross-conduction between the MOSFETs in the same leg being driven. I did this by generating a sine table with 31 values and a peak of 990 and then adding a zero at the end.
The SPWM generation is done by the single PWM module and which MOSFETs to send the signals to is set by the "Direction" bit and the hardware trick employing the AND gates. When "Direction" is equal to 0, the high side MOSFET A is kept on for 10ms during which time the SPWM signals on PWM (OC1A) output (PORTD5) are sent to low side MOSFET D by sending a "1" to PORTD3, which, with the help of the AND gate "diverts" the OC1A signal to the low side MOSFET D (see Fig. 1 above). The same thing is achieved when "Direction" is equal to 1, just with high side MOSFET C and low side MOSFET B. When MOSFETs A and D are operated, MOSFETs B and C are kept off and vice versa. For MOSFET drive, we need 4 pins for the 4 drive signals and I’ve chosen PORTD bits 0 to 3. I’ve arbitrarily chosen these four pins but you can choose any four pins really. The MOSFETs are first turned off before the other two are turned on, as can be seen in the code block:
if (Direction == 0){
MOSA = 0;
MOSD = 0;
MOSB = 1;
MOSC = 1;
Direction = 1;
}
else{
MOSB = 0;
MOSC = 0;
MOSA = 1;
MOSD = 1;
Direction = 0;
}
Use of the table pointer in the interrupt:
When Timer/Counter 1 reaches TOP, TOV1 flag is set and since interrupt is enabled, the ISR in the corresponding interrupt vector is served. There table pointer is made use of to retrieve the required values off the sine table and assign them to OCR1AH and OCR1AL – the 16-bit resultant in OCR1A sets the duty cycle. The sine table stores the duty cycle in such a way that when these are subsequently sent to the MOSFETs in the specific order in which they are set, at the required frequency, the output, when filtered, will produce a sine wave.
Every 62.5us the ISR is served – 62.5us because the SPWM frequency was set to 16kHz. Time period for a 16kHz frequency is 62.5us as time period = 1 / freqeuncy.
In the main() function, I had assigned the value of 410 to SET_FREQ . SET_FREQ determines the output frequency of the sine wave, which in our case here is 50Hz. You’ll soon see how.
In the interrupt, the variable TBL_POINTER_NEW is updated – every 62.5us it is increased by 410.
TBL_POINTER_NEW is a 16-bit variable and at the beginning of program execution has a value of 0. So, after the first interrupt it holds 410, after the second interrupt 820, after the third 1230 and so on. After 159 interrupts, TBL_POINTER_NEW holds 65190. So, at the next interrupt,
TBL_POINTER_NEW overflows and holds 64.
The interrupt occurs every 62.5us. At each interrupt TBL_POINTER_NEW is increased by 410. At the 160 th interrupt, TBL_POINTER_NEW overflows, just as it does the 320 th interrupt, the 480 th interrupt and so on.
Initially TBL_POINTER_NEW holds 0 and on subsequent interrupts, TBL_POINTER_NEW holds 410, 820, 1230, 1640, 2050, 2460, 2870, 3280, 3690, 4100 and so on.
TBL_POINTER_SHIFT right-shifts
TBL_POINTER_NEW eleven times and stores that value. Right shifting 11 times is the same as dividing by 2 11 (2 11 = 2048) – just more efficient. When the microcontroller starts up,
TBL_POINTER_SHIFT holds 0 and on subsequent interrupts, TBL_POINTER_SHIFT holds 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 ….. and so on. Now, the trend is that TBL_POINTER_SHIFT holds the same value for 5 consecutive interrupts – go on, you can do the math. Why 5 times? We’ll see that a little later.
After TBL_POINTER_NEW is shifted 11 times,
DUTY_CYCLE is assigned the resultant 5-bit value. This acts as – or rather is – the table pointer and the required value is retrieved off the sine table. This 16-bit value is then split into two 8-bit values to be assigned to OCR1AH and OCR1AL, thus setting the appropriate duty cycle.
Now let’s see why TBL_POINTER_SHIFT is needed to be incremented every 5 interrupts and how we’ve done that.
Our frequency is 50Hz – time period is 20ms. A half cycle takes 10ms. Recall that the sine table used is only for half a cycle. So, the 32 values must be called such that they make up the half cycle. The interrupt service routine is executed each 62.5us and so, retrieving all the values from the sine table and using them to update the duty cycle takes a total time of 62.5us * 32 = 2000us (assuming each value is retrieved/called once). That’s 2ms. But our half cycle is 10ms – 5 times larger than what we have now. So, we increase the time five folds. How? By calling each value from the table 5 times instead of only once. So, the time involved is now 32 * 62.5us * 5 = 10000us = 10ms.
This calculation we’ve just done is related to the frequency – 50Hz desired frequency and thus 10ms half cycle. I’ve shown this “backward” to explain why this has been chosen but remember that the microcontroller doesn’t know you want 50Hz frequency. The microcontroller doesn’t know that the desired time is 10ms.
So, now you know the answer to why I’ve called each sine table value 5 times: to ensure that the sine table that has 32 values occupies the entire 10ms. Now, how did I make it repeat 5 times? By setting SET_FREQ to 410. You might be wondering how this works. Well, it works this way.
SET_FREQ = 410. Each interrupt,
TBL_POINTER_NEW is increased by 410. Every 5 interrupts, TBL_POINTER_NEW is increased by 2050 (compared to the initial value). 2 11 = 2048. Since TBL_POINTER_SHIFT divides
TBL_POINTER_NEW by 2048, when
TBL_POINTER_NEW increases 5*410 times,
TBL_POINTER_SHIFT increases once. So, the number of repeats (5 in this case) is equal to the number of interrupts it takes for
TBL_POINTER_SHIFT to increase by one, which is equal to the number of times it takes for
SET_FREQ to equal or cross 2 11 (=2048). Since
SET_FREQ = 410, the number of times to cross 2048 is 5 and that is the number of times each table value is called. So, the table pointer is incremented every 5 interrupts. Thus SET_FREQ determines the frequency. If we had set
SET_FREQ to 200, the number of times to cross 2048 would be 11, as 200*10 = 2000 (less than 2048) but 200*11 = 2200 (more than 2048). Thus each sine table value would be called 11 times – the table pointer would be incremented every 11 interrupts. The output time period of the sine wave would then be 2 * 32 * 62.5us * 11 = 44000us = 44ms. The output frequency would thus be 22.7 Hz instead of the 50Hz we have now.
SET_FREQ can be calculated as {65536/ (32 * 5)} = 409.6 = 410 rounded off to the nearest integer. That’s SET_FREQ = [2 16 /{(Number of sine table values) * (Number of times each value is to be called)}].
I’ve talked about SET_FREQ , TBL_POINTER_NEW ,
TBL_POINTER_SHIFT and right shifting eleven times. Now you may ask why eleven times. Why not 5 or 10 or 12 or any other value? The reason is that we have a sine table with 32 values. 32 = 2 5 . Shifting a 16-bit variable eleven times to the right leaves us with a 5-bit value – one between 0 and 31. These 5 bits are the upper most (most significant) 5 bits. This 5-bit value is the sine table pointer. This works in conjunction with the number of sine table values and the value of
SET_FREQ to set or determine the output sine wave frequency. If we had 64 sine table values, we would right-shift TBL_POINTER_NEW 10 times instead of 11 so that the shifting operation results in a 6-bit value. 2 6 = 64 and that is the number of sine table values we have – the table pointer would have a value between 0 and 63.
In the interrupt, after the duty cycle is set,
TBL_POINTER_OLD is assigned the value of
TBL_POINTER_NEW . When TBL_POINTER_NEW is first assigned 410, TBL_POINTER_OLD holds 0. The 11-bit shifting is done. The duty cycle is set and then TBL_POINTER_OLD is set. So, the
TBL_POINTER_OLD update trails
TBL_POINTER_NEW update. So, every interrupt until TBL_POINTER_NEW overflows,
TBL_POINTER_NEW is greater than
TBL_POINTER_OLD .
When TBL_POINTER_NEW = 64370 and the ISR is to be executed, TBL_POINTER_OLD also holds 64370. TBL_POINTER_NEW is increased to 64780 and then the sine table value is called and
TBL_POINTER_OLD is then updated to 64780. The next interrupt, TBL_POINTER_NEW is increased to 65190 and the “if condition” is again false since at that stage TBL_POINTER_OLD holds 64780 – TBL_POINTER_NEW >
TBL_POINTER_OLD . Then at the end of the ISR,
TBL_POINTER_OLD is assigned 65190. And now comes the interesting part. TBL_POINTER_NEW now holds 65190 and TBL_POINTER_OLD holds 65190. 410 is to added to TBL_POINTER_OLD and TBL_POINTER_OLD overflows to hold 64. Now, TBL_POINTER_NEW (which holds 64) is less than TBL_POINTER_OLD (which holds 65190) and the if condition is true. So, the direction of MOSFET drive is reversed. If MOSFETs A and D were driven previously, MOSFETs B and C will now be driven and vice versa. Remember that by sending a logic high to PORTD1 or PORTD3, due to the AND gate, we’re just diverting the OC1 PWM to the required low side MOSFET. Thus 2 MOSFETs are driven with the same signals but in alternate half cycles. By inverting the direction of the full-bridge drive, we are carrying out the next half cycle with the same duty cycle values and sequence, but in the opposite direction – as is necessary (think AC waveform and opposite half cycle). This happens every (32*5 = 160) interrupts – when all the values of the table have each been called 5 times. Since TBL_POINTER_OLD then has a small value again, since it overflowed,
TBL_POINTER_SHIFT will then be equal to 0, meaning that the table pointer has restarted from zero and the SPWM starts over again. So,
TBL_POINTER_SHIFT , on subsequent interrupts has the values: 0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,………..30,30,30,30,30,31,31,31,31,31,0,0,0,0,0,1,1,1,……. And so on.
That's about it regarding the code.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 11:29pm On Nov 28
Still on spwm
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by harrwix(m): 9:54am On Dec 06
interesting... how can one get to learn this practically
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 6:59pm On Dec 06
harrwix:
interesting... how can one get to learn this practically

You can choose to opt for the online tutorial or the live tutorial..
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by harrwix(m): 8:12pm On Dec 06
pakingzzzzz:

You can choose to opt for the online tutorial or the live tutorial..
I prefer the live
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 8:13am On Dec 07
harrwix:

I prefer the live
Then you will have to come down to Imo state.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by harrwix(m): 10:22am On Dec 07
pakingzzzzz:

Then you will have to come down to Imo state.
I am in Lagos how is the online tutorial alternative
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 12:17pm On Dec 07
harrwix:


I am in Lagos
how is the online tutorial alternative

The online tutorial alternative includes; sending you a video practicals with voice explanations.
This video tutorials are of three types. Each type having two or more sub videos to reinforce the strength of explaining the technicalities involved.
The three stages I take you through, are as follows;
(1) The theoretical explanation of how each components and it's relation to the device influences the inverter.
(2) Building the components.
(3) programming the Arduino.
(4) How to troubleshoot.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by harrwix(m): 2:13pm On Dec 07
pakingzzzzz:


The online tutorial alternative includes; sending you a video practicals with voice explanations.
This video tutorials are of three types. Each type having two or more sub videos to reinforce the strength of explaining the technicalities involved.
The three stages I take you through, are as follows;
(1) The theoretical explanation of how each components and it's relation to the device influences the inverter.
(2) Building the components.
(3) programming the Arduino.
(4) How to troubleshoot.

Okay.... how can I get the videos
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 5:59pm On Dec 07
harrwix:

Okay.... how can I get the videos
Hit me on 0 9 0 2 9 3 6 5 0 8 3
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 7:03pm On Dec 09
harrwix:


Okay.... how can I get the videos

Call me.. I lost your number.
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 2:47pm On Dec 11
We do what we say!!
Need to execute you electronic projects?
Call us now
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 7:32pm On Dec 13
The sun shines on those who stand before it, than those who kneel before it!!
Call us now...
Re: Learn How To Build A Pure Sine Wave Inverter With Arduino Or (atmega328) by pakingzzzzz: 1:00am On Dec 16
Let us hear you.

(0) (Reply)

I Heard This On Consulting Capable / Pls Can I Study For Linux And Oracle Exams On My Own / Cv Writing Firm

(Go Up)

Sections: politics (1) business autos (1) jobs (1) career education (1) romance computers phones travel sports fashion health
religion celebs tv-movies music-radio literature webmasters programming techmarket

Links: (0) (1) (2) (3) (4) (5) (6) (7) (8) (9)

Nairaland - Copyright © 2005 - 2017 Oluwaseun Osewa. All rights reserved. See How To Advertise. 303
Disclaimer: Every Nairaland member is solely responsible for anything that he/she posts or uploads on Nairaland.