You are on page 1of 3

/*

Arduino - ATmega328 - PWM signal


Arduino is open-source electronics platform with flexibility and developing the
easy-to-use software and hardware.
The ATmega328 can be buy within an arduino development kit.
To work with this kit, a development software is available in the internet pages
of arduino.
It enables to write code in programming language C and you can use some interna
l functions of arduino,
which makes work even more easy.
But there is no possibility how to generate invertion PWM signal for 6 channels.
In other words, if you need to work with your generated signal in one outup and
with
its inverse signal in another one output (shown in image),there is no predefined
function for this.
You have to look into datasheet, how to make it work, to write into register the
appropriate values.
I worked on this issue in previous days and I attach my code here. The code was
designed to work fast,
therefore there are sinetables with values for 0to 180 for every phase. It is possib
le to calculate
a lot of values using one table with values for 0to 60, but there have to be algori
thms to calculate
appropriate values and that is time consuming and in the other hand, the process
or has 32kBytes memory,
so it is no problem to declare tables for 180. I generated these tables using Matl
ab.
This code generated in the result sine wave for three phases with frequency 50Hz
.
*/
//
//
//
//
ut
//
//
//
//
//
//

22.11.2009 - EPP, Group1, Michala Srnova


Generating of PWM signals for three phase inverter circuit
generating of sine signals with freq of 50Hz
the amplitude of these signals will be calculated to desired value (using inp
signal)
input signal: voltage on analog input
output values: PWM signals on all 6 PWM outputs:
1. signal to 1.phase (+ switch)
2. signal to 1.phase (- switch) opposite to signal for 1.phase
3.,4. signals to 2.phase
5.,6. signals to 3.phase

#include "WProgram.h"
void setup();
void loop();
int i; //for cycle
int analogPin = 0; //No. of input pin
int Input=1023; //this value is from ADC: it can be in range:0 - 1023 (0-5V)
float K;
// Constant : is equal Input/1023
float ph0;
// For calculating value of phase 1
float ph1;
// phase 2
float ph2;
// phase 3
//setting of sin table for half-period, 78 samples
//this realization is uneffective due to used memory - because it is possible t
o keep only values of first 60 degrees and
//+only for first phase. Others can be calculated.

//But this microchip hase a lot of memory and his only one role is to generate
PWM. We need to have values up time, and calculations
//which would be necessary (for calculating samples for phase 2 and 3, and for
angles of whole sine wave) are time-consuming
int sinus0[]={0,10,20,31,41,51,61,71,81,91,101,110,119,128,137,146,154,163,
170,178,185,192,199,205,211,217,222,227,231,236,239,243,246,248,25
0,252,
253,254,254,254,254,253,252,250,248,246,243,239,236,231,227,222,21
7,211,
205,199,192,185,178,170,163,154,146,137,128,119,110,101,91,81,71,6
1,
51,41,31,20,10,0};
int sinus1[]={220,225,230,234,238,242,245,247,250,251,253,254,254,254,254,254,25
2,251,
249,246,244,240,237,233,228,224,219,213,207,201,194,188,180,173,16
5,157,
149,140,131,122,113,104,94,85,75,65,55,44,34,24,13,3,6,17,
27,38,48,58,68,78,88,98,107,116,126,134,143,152,160,168,175,183,
190,197,203,209,215,220};
int sinus2[]={220,215,209,203,197,190,183,175,168,160,151,143,134,125,116,107,9
7,88,
78,68,58,48,37,27,17,6,3,14,24,34,45,55,65,75,85,94,
104,113,123,132,140,149,157,165,173,181,188,195,201,207,213,219,2
24,229,
233,237,241,244,247,249,251,252,254,254,255,254,254,253,251,250,2
47,245,
242,238,234,230,225,220};
void setup()
{
//for default settings
//=====setting of timer for fast PWM method====
//frequency PWM is fosc/(8*256) (by 16MHz oscil. = 7812,5)
//timer 0, 8-bit timer, pins 5,6(+) 128us
TCCR0A=0b10110011; // generate inverted PWM signals in output
TCCR0B=0b00000010; // set of source of clock signal + prescaller
//timer 2, 8-bit timer, pins 9,10(+) = same settings as timer0 - 128us
TCCR2A=0b10110011; // generate inverted PWM signals in output
TCCR2B=0b00000010;
//timer 1, 16-bit timer, pins 3, 11(+)
TCCR1A=0b11100001; // set for generate negative values first
TCCR1B=0b00001010;
//setting of PWM ports to output
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(3,OUTPUT);
}
void loop()
{
//whole our code processed in infinity cycle
delay(64);
//change of polarity of phase 1
TCCR0A = TCCR0A ^ 0b01010000;
//cycle for half period

for(i=0; i<78;i++)
{
//reading the value of input voltage
Input=analogRead(analogPin); //Input=1023;
K = Input / 1023.00;
//now Input value is in range: 0-1
//generating of value OCR0x,OCR1x,OCR2x , where for same counter are values
the same
ph0=sinus0[i]*K; //this value should be float
//setting of OCR0x
OCR0A=byte(ph0);
OCR0B=byte(ph0);
//for 2. phase:
if(i==52){
//passed 52 samples, it means, that values of phase two will be negative =>
the setting of generating signals must be changed
//TCCR2A=0b1011 0011; => 0b1110 0011 => for XOR =mask: 0101 0000
TCCR1A = TCCR1A ^ 0b01010000;
}
ph1=sinus1[i]*K;
OCR1A=byte(ph1);
OCR1B=byte(ph1);
//for 3.phase
if(i==26){
//26 samples - change positive to negative and vice versa
TCCR2A = TCCR2A ^ 0b01010000;
}
ph2=sinus2[i]*K;
OCR2A=byte(ph2);
OCR2B=byte(ph2);
//wait for end of now processing cycle - than generate new samples for next
cycle
// flag TOV1=1 when PWM period ends
while(TOV1 != 1){
//check it every 16 micro seconds - with changes in timer, it is 64 times
bigger value
delayMicroseconds(1024);
delay(64);
}
}
}
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}

You might also like