#define UN (400.0) //napiecie znamionowe silnika
#define FN (50.0) //czestotliwosc znamionowa silnika
#define P (UN/FN) //wsp. okreslajacy proporcje napiecia do czestotliwoci znamionowej
#define T_PWM (0.000255) //okres sygnalu PWM - ustawiony przez preskaler w licznikach
#define T_MAX (4.0) //okreslenie maksymalnego okresu napiecia wyjsciowego
#define T_MIN (0.02) //minimalny okres napiecia wyjsciowego
#define K_MAX floor(T_MAX/T_PWM) //liczba wartosci okresu dla T_MAX
#define K_MIN ceil(T_MIN/T_PWM) //liczba wartosci okresu dla T_MIN
volatile static unsigned int dlugosc_tab_sin; //zmienna zawierajaca liczbe wartosci w pelnym
//okresie napiecia wyjsciowego
static unsigned int i = 0; //zmienna pomocniacza
volatile static unsigned int licznik_glowny = 0;//zmienna wystepujaca w przerwaniu czyklicznie
//^ co okres T_PWM zwiekszajaca swoja wartosc o 1
static unsigned int next_value_sin = 0; //zmienna ktora wartosc sin nalezy obliczyc
static double t_param=100; //parametr okreslajacy okres napiecia wyjsciowego
static float t = T_PWM; //T_PWM
static float omega_t; //pulsacja napiecia wyjsciowego pomnozona przez T_PWM
static float t_out; //okres wyjsciowy napiecia
static float U_o_param; //parametr okreslajacy wielkosc napiecie wyjsciowego
//^ obliczony na podstawie t_out i U_in
static unsigned int ocr0a, ocr0b, ocr1a;//zmienne pomocnicze do przechowywania obl. wypelnien
static unsigned int ocr1b, ocr2a, ocr2b;//^
static double sin_in; //zmienna zawierajaca parametr funkcji sin
static double blad = 1; //zmienna uzyta do zatrzymania generowania napiecia przy przeciazeniu
static unsigned int analog=0; //zmienna zawierajaca zmierzona wartosc
static double U_in = 0; //zmienna przechowujนca pomiar napiecia ukladu posredniczacego
static double U_rms_max; //maksymalna aktualnie mozliwa do generacji wartosc skuteczna napiecia
static bool a=0; //zmienna logiczna do realizacji dwoch naprzemiennych pomiarow
int main()
{
io_init(); //inicjalizacja wejsc i wyjsc
timers_init(); //inicjalizacja licznikow PWM
adc_init(); //inicjalizacja przetwornika ADC
while(1) //nieskonczona petla z programem glownym
{
if(i==185) //warunek okreslajacy wejscie do funkcji zmiany
{ //parametrow napiecia wysjciowego, wywolanie co okolo 100ms
zmien_predkosc(); //funkcja zmiany parametrow napiecia wyjsciowego
i=0;
}
next_value_sin = licznik_glowny%dlugosc_tab_sin; //kolejna wartoๆ sinusa do obliczenia
sin_in=omega_t*next_value_sin;
/*obliczenie wartosci do rejestrow okreslajacych wypelnienie sygnalu wyjscioweg*/
ocr0a = round(blad*(U_o_param*(sin(sin_in)+1)*254/2)+1);//pin 6
ocr0b = ocr0a - 1;
ocr1a = round(blad*(U_o_param*(sin(sin_in-2.09)+1)*254/2)+1);//pin 9
ocr1b = ocr1a - 1;
ocr2a = round(blad*(U_o_param*(sin(sin_in+2.09)+1)*254/2)+1);//pin 11
ocr2b = ocr2a - 1;
/*uaktualnienie wartosci w rejestrach*/
cli(); //zabronienie na obsloge przerwan na wypadek gdyby
//podczas uaktualniania wystapilo przerwanie
OCR0A = ocr0a; //pin 6
OCR0B = ocr0b; //pin 5
OCR1AL = ocr1a; //pin 9
OCR1BL = ocr1b; //pin 10
OCR2A = ocr2a; //pin 11
OCR2B = ocr2b; //pin 3
sei(); //zezwolenie na obsloge przerwan
i++;
}
}
void adc_init()
{
ADCSRA |= _BV(ADEN);//uruchomienie przetwornika
ADCSRA |= _BV(ADPS2);//ustawienie preskalera
ADCSRA |= _BV(ADPS1);//^
ADCSRA |= _BV(ADPS0);//^
ADMUX |= _BV(REFS0);// napiecie odniesienia ustawione jako napiecie zasilania
ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru
}
void timers_init()
{
cli(); // obsloga przerwan zabroniona
//timer0 init
TCCR0A |= _BV(COM0A1) | _BV(COM0B0) | _BV(COM0B1) | _BV(WGM00);
TCCR0B |= _BV(CS01); //preskaler 8
TIMSK0 |= _BV(TOIE0); //flaga od wartosci 0 wlaczona
//timer1 init
TCCR1A |= _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(WGM10);
TCCR1B |= _BV(CS11); //preskaler 8
//timer2 init
TCCR2A |= _BV(COM2A1) | _BV(COM2B0) | _BV(COM2B1) | _BV(WGM20);
TCCR2B |= _BV(CS21); //preskaler 8
//zerowanie wartosci licznik๓w
TCNT0 = 0;
TCNT1L = 0;
TCNT2 = 0;
/* licznik zlicza w g๓re do 255, nastepnie w d๓ณ: /\/\/\
przy wartosci 255 jest przerwanie przy ktorym dokonuje sie
pomiarow napiec i pradow
*/
sei(); //zezwolenie na obsloge przerwan
}
void io_init()
{
pinMode(6, OUTPUT); //OC0A
pinMode(5, OUTPUT); //OC0B
pinMode(9, OUTPUT); //OC1A
pinMode(10, OUTPUT);//OC1B
pinMode(11, OUTPUT);//OC2A
pinMode(3, OUTPUT); //OC2B
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(12, OUTPUT);
}
ISR(TIMER0_OVF_vect) //przerwanie przy wartosci 0 licznika0
{
analog = ADC;
if(a)
{
U_in = 0.0709*analog;
ADMUX |= _BV(MUX0); //wybranie wejscia ADC1 do pomiaru pradu
}
else
{
ADMUX |= ADMUX &= 0b11110000; //wybranie wejscia ADC0 do pomiaru napiecia
if(analog>579)
{
blad = 0; //jezeli przeciazenie wylaczenie generacji napiecia
digitalWrite(12, HIGH); //zapalenie diody
}
}
ADCSRA |= _BV(ADSC);//start odczytywania pomiaru
a=a^1; //bramka XOR neguje wartosc logiczna a
licznik_glowny++;
if(licznik_glowny>=dlugosc_tab_sin) licznik_glowny = 0;
}
void zmien_predkosc()
{
U_rms_max = U_in*0.62; //wartosc 0.62 wyzanczona eksperymentalnie
bool up; //zmienna logiczna, informuje o nacisnietym przycisku zwieksz czestotliwosc
bool down; //zmienna logiczna, informuje o nacisnietym przycisku zmiejsz czestotliwosc
up = digitalRead(4); //odczyt: czy nacisniety przycisk zwieksz czestotliwosc
down = digitalRead(2); //odczyt: czy nacisniety przycisk zmiejsz czestotliwosc
if(up==1) t_param--; //jezeli nacisniety przycisk zwieksz czestotliwosc to zmiejsz okres
if(down==1) t_param++; //jezeli nacisniety przycisk zmniejsz czestotliwosc to zwieksz okres
if(t_param<0) t_param=0; //zabezpieczenie przekroczenia wartosci skrajnych
if(t_param>100) t_param=100;//^
dlugosc_tab_sin = ceil((K_MAX-K_MIN)*t_param/500+K_MIN);//ilosc wartosci wypelnien w jednym okresie
t_out = T_PWM*dlugosc_tab_sin; //obliczenie okresu napiecia wyjsciowego
omega_t = t*2*PI/t_out; //obliczenie pulsacji napiecia wyjsciowego
U_o_param = (P/t_out)/U_rms_max; //obliczenie parametru okreslajacego wielkosc napiecia wyjsciowego
if(t_out>1) U_o_param = 0.5*(18.5/U_rms_max); //napi๊cie na wyjsciu przy niskiej czestotliwosci 10V
if(U_o_param>1) U_o_param=1; //zabezpieczenie przekroczenia wartosci skrajnych
}
typedef unsigned char PROGMEM prog_uchar;
// table of 256 sine values / one sine period / stored in flash memory
PROGMEM prog_uchar const sine256_u[] = {
87, 90, 93, 96, 99,102,105,108,111,115,118,121,124,127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,
192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,251,252,
252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,
238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,
152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102, 99, 96, 93, 90, 87, 84, 81, 78, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51,
49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4,
3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23,
25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 78, 81, 84
};
PROGMEM prog_uchar const sine256_v[] = {
250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,
184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102, 99, 96, 93, 90, 87, 84, 81,
78, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20,
18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5,
6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76,
78, 81, 84, 87, 90, 93, 96, 99,102,105,108,111,115,118,121,124,127,130,133,136,139,143,146,149,152,155,
158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,
240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251
};
PROGMEM prog_uchar const sine256_w[] = {
49, 46, 44, 42, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37,
39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, 78, 81, 84, 87, 90, 93, 96, 99,102,105,108,
111,115,118,121,124,127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,
212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,
254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,
227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,
133,130,127,124,121,118,115,111,108,105,102, 99, 96, 93, 90, 87, 84, 81, 78, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51
};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
double dfreq;
//const double refclk=31372.549; // =16MHz / 510
const double refclk=31130.0 ; // measured
// variables used inside interrupt service declared as voilatile
volatile byte icnt; // var inside interrupt
volatile byte icnt1; // var inside interrupt
volatile byte c4ms; // counter incremented all 4ms
volatile unsigned long phaccu; // phase accumulator
volatile unsigned long tword_m; // dds tuning word m
void setup()
{
Serial.begin(115200); // connect to the serial port
Serial.println("DDS Test");
Setup_timer3();
// disable interrupts to avoid timing distortion
cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK3,TOIE3); // enable Timer3 Interrupt
dfreq=100.0; // initial output frequency = 100.0 Hz
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
}
void loop()
{
while(1) {
if (c4ms > 250) { // timer / wait fou a full second
c4ms=0;
dfreq=map(analogRead(0),0,1023,0,12); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz
//dfreq=analogRead(0);
cbi (TIMSK3,TOIE3); // disble Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
sbi (TIMSK3,TOIE3); // enable Timer2 Interrupt
Serial.print(dfreq);
Serial.print(" ");
Serial.println(tword_m);
}
}
}
//******************************************************************
// timer3 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer3() {
// Timer3 activate PWM Pin 5,2,3
DDRE |= _BV(PORTE3); TCCR3A |= _BV(COM3A1);
DDRE |= _BV(PORTE4); TCCR3A |= _BV(COM3B1);
DDRE |= _BV(PORTE5); TCCR3A |= _BV(COM3C1);
// Timer3 Clock Prescaler to : 1
sbi (TCCR3B, CS30);
cbi (TCCR3B, CS31);
cbi (TCCR3B, CS32);
// Timer3 PWM Mode set to Phase Correct PWM
cbi (TCCR3A, COM3A0); // clear Compare Match
sbi (TCCR3A, COM3A1);
sbi (TCCR3A, WGM30); // Mode 1 / Phase Correct PWM
cbi (TCCR3A, WGM31);
cbi (TCCR3B, WGM32);
}
//******************************************************************
// Timer3 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 uSec ( inclusive push and pop)
ISR(TIMER3_OVF_vect) {
phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
icnt=phaccu >> 24; // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC
OCR3A=pgm_read_byte_near(sine256_u + icnt);
OCR3B=pgm_read_byte_near(sine256_v + icnt);
OCR3C=pgm_read_byte_near(sine256_w + icnt);
if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}
}
/*
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 internal 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 0ยฐto 180ยฐ for every phase. It is possible to calculate
a lot of values using one table with values for 0ยฐto 60ย, but there have to be algorithms to calculate
appropriate values and that is time consuming and in the other hand, the processor has 32kBytes memory,
so it is no problem to declare tables for 180ยฐ. I generated these tables using Matlab.
This code generated in the result sine wave for three phases with frequency 50Hz.
*/
// 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 input 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 to 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,250,252,
253,254,254,254,254,253,252,250,248,246,243,239,236,231,227,222,217,211,
205,199,192,185,178,170,163,154,146,137,128,119,110,101,91,81,71,61,
51,41,31,20,10,0};
int sinus1[]={220,225,230,234,238,242,245,247,250,251,253,254,254,254,254,254,252,251,
249,246,244,240,237,233,228,224,219,213,207,201,194,188,180,173,165,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,97,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,224,229,
233,237,241,244,247,249,251,252,254,254,255,254,254,253,251,250,247,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;
}
#include <avr/pgmspace.h>
#include <avr/io.h>
PROGMEM const uint16_t sine512[] = {250,256,262,269,275,281,288,294,301,308,314,319,326,332,339,344,350,356,362,367,374,379,384,389,395,400,404,410,414,419,423,428,433,436,440,445,449,452,455,458,463,466,468,471,474,476,478,481,483,485,487,488,490,491,493,494,495,496,496,498,499,499,499,500,500,499,499,499,498,498,496,496,495,494,493,493,492,491,489,488,487,486,484,483,481,480,478,476,474,473,471,470,468,466,465,463,460,459,457,455,453,452,450,449,447,446,445,443,442,440,439,438,436,435,434,433,432,432,431,430,430,429,428,428,428,428,427,427,427,427,427,428,428,428,428,429,430,430,431,432,432,433,434,435,436,438,439,440,442,443,445,446,447,449,450,452,453,455,457,459,460,463,465,466,468,470,471,473,474,476,478,480,481,483,484,486,487,488,489,491,492,493,493,494,495,496,496,498,498,499,499,499,500,500,499,499,499,498,496,496,495,494,493,491,490,488,487,485,483,481,478,476,474,471,468,466,463,458,455,452,449,445,440,436,433,428,423,419,414,410,404,400,395,389,384,379,374,367,362,356,350,344,339,332,326,319,314,308,301,294,288,281,275,269,262,256,250,244,238,231,225,219,212,206,199,192,186,181,174,168,161,156,150,144,138,133,126,121,116,111,105,100,96,90,86,81,77,72,67,64,60,55,51,48,45,42,37,34,32,29,26,24,22,19,17,15,13,12,10,9,7,6,5,4,4,2,1,1,1,0,0,1,1,1,2,2,4,4,5,6,7,7,8,9,11,12,13,14,16,17,19,20,22,24,26,27,29,30,32,34,35,37,40,41,43,45,47,48,50,51,53,54,55,57,58,60,61,62,64,65,66,67,68,68,69,70,70,71,72,72,72,72,73,73,73,73,73,72,72,72,72,71,70,70,69,68,68,67,66,65,64,62,61,60,58,57,55,54,53,51,50,48,47,45,43,41,40,37,35,34,32,30,29,27,26,24,22,20,19,17,16,14,13,12,11,9,8,7,7,6,5,4,4,2,2,1,1,1,0,0,1,1,1,2,4,4,5,6,7,9,10,12,13,15,17,19,22,24,26,29,32,34,37,42,45,48,51,55,60,64,67,72,77,81,86,90,96,100,105,111,116,121,126,133,138,144,150,156,161,168,174,181,186,192,199,206,212,219,225,231,238,244};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
//vyssi refclk == vyssi frekout const unsigned long refclk=1562960;
const unsigned long refclk=781480;
volatile int current_count;
volatile unsigned long phase_accumulator;
volatile unsigned long tword_m;
volatile unsigned long stepm;
volatile word count = 0;
volatile byte DT = 10;
volatile byte ampl = 13;
volatile word offset_1 = 171;
volatile word offset_2 = 341;
word fnom = 5000;
word fzad = 0;
word boost = 600;
word readpot;
word calc;
boolean ISR_exec_time = 1;
boolean RUN = 0;
byte bufclr = 0;
void setup()
{
pinMode(6, OUTPUT); //OC4A
pinMode(7, OUTPUT); //OC4B
pinMode(8, OUTPUT); //OC4C
pinMode(11, OUTPUT); //OC1A
pinMode(12, OUTPUT); //OC1B
pinMode(13, OUTPUT); //OC1C
//pinMode(5, OUTPUT); //OC3A
//pinMode(2, OUTPUT); //OC3B
//pinMode(3, OUTPUT); //OC3C
pinMode(52, OUTPUT);
pinMode(53, OUTPUT);
pinMode(22, INPUT_PULLUP);
pinMode(23, INPUT_PULLUP);
sbi (GTCCR, TSM);
sbi (GTCCR, PSRASY);
sbi (GTCCR, PSRSYNC);
Setup_timer1();
Setup_timer2();
Setup_timer4();
//Setup_timer3();
//Setup_timer5();
TCNT1 = 0;
//TCNT3 = 0;
TCNT4 = 0;
//TCNT5 = 0;
GTCCR = 0;
//Disable Timer 0
cbi (TIMSK0,TOIE0);
tword_m=pow(2,32)*fzad/refclk;
sbi (TIMSK4,TOIE4);
Serial.begin(9600);
}
void loop()
{
while(1)
{
readpot = 0;
for (int i=0; i <= 9; i++)
{
readpot = readpot + analogRead(0);
}
if (digitalRead(22)==0 && fzad==0)
{
offset_1 = 341;
offset_2 = 171;
}
if (digitalRead(22)==1 && fzad==0 )
{
offset_1 = 171;
offset_2 = 341;
}
//===============================================
if (digitalRead(23)==1 && fzad!=readpot)
{
//================================================
if (fzad>readpot && TCNT2 > 10)
{
fzad = fzad-1;
TCNT2=0;
}
if (fzad<readpot && TCNT2 > 10)
{
fzad = fzad+1;
TCNT2=0;
}
//================================================
stepm = pow(2,32)*fzad/refclk;
calc = ((1280/(fnom/100))*(fzad/100))/10;
if (fzad > fnom) //*500
{
calc = 128;
}
if (fzad < boost)
{
calc = 14;
}
cbi (TIMSK4,TOIE4);
ampl = calc; //*5
tword_m = stepm;
sbi (TIMSK4,TOIE4);
}
//===============================================
/* */
if (count > 7000)
{
bufclr = bufclr+1;
count = 0;
Serial.println(bufclr);
Serial.println(fzad);
Serial.println(ampl);
}
}
}
ISR(TIMER4_OVF_vect)
{
sbi(PORTB,ISR_exec_time);
phase_accumulator=phase_accumulator+tword_m;
current_count=phase_accumulator >> 23;
word offs;
word offs1;
word offs2;
offs= current_count + offset_1;
offs2 = current_count + offset_2;
if (offs > 511)
{
offs = offs - 512;
}
if (offs2 > 511)
{
offs2 = offs2 - 512;
}
offs = (pgm_read_word_near(sine512 + offs)*ampl) >> 6;
offs1 = (pgm_read_word_near(sine512 + current_count)*ampl) >> 6;
offs2 = (pgm_read_word_near(sine512 + offs2)*ampl) >> 6;
if (tword_m > 0)
{
OCR4B = offs + DT;
OCR1B = offs;
OCR4A = offs1 + DT;
OCR1A = offs1;
OCR4C = offs2 + DT;
OCR1C = offs2;
}
else
{
OCR4B = 1023;
OCR1B = 0;
OCR4A = 1023;
OCR1A = 0;
OCR4C = 1023;
OCR1C = 0;
}
cbi(PORTB,ISR_exec_time);
count = count+1;
/* */
}
void Setup_timer1(void)
{
//Clock Prescaler : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer1 Phase Correct PWM
sbi (TCCR1A, COM1A0);
sbi (TCCR1A, COM1A1);
sbi (TCCR1A, COM1B0);
sbi (TCCR1A, COM1B1);
sbi (TCCR1A, COM1C0); //tretireg
sbi (TCCR1A, COM1C1); //tretireg
// Mode 1 / Phase Correct PWM
sbi (TCCR1A, WGM10);
sbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
void Setup_timer4(void)
{
sbi (TCCR4B, CS40);
cbi (TCCR4B, CS41);
cbi (TCCR4B, CS42);
cbi (TCCR4A, COM4A0);
sbi (TCCR4A, COM4A1);
cbi (TCCR4A, COM4B0);
sbi (TCCR4A, COM4B1);
cbi (TCCR4A, COM4C0);
sbi (TCCR4A, COM4C1);
sbi (TCCR4A, WGM40);
sbi (TCCR4A, WGM41);
cbi (TCCR4B, WGM42);
cbi (TCCR4B, WGM43);
}
void Setup_timer2(void)
{
//Prescaler : 1
cbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
sbi (TCCR2B, CS22);
// Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
cbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
cbi (TCCR2A, COM2B1);
//Phase Correct PWM
cbi (TCCR2A, WGM20);
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
/*
void Setup_timer3(void)
{
sbi (TCCR3B, CS30);
cbi (TCCR3B, CS31);
cbi (TCCR3B, CS32);
cbi (TCCR3A, COM3A0);
sbi (TCCR3A, COM3A1);
cbi (TCCR3A, COM3B0);
sbi (TCCR3A, COM3B1);
cbi (TCCR3A, COM3C0);
sbi (TCCR3A, COM3C1);
sbi (TCCR3A, WGM30);
sbi (TCCR3A, WGM31);
cbi (TCCR3B, WGM32);
cbi (TCCR3B, WGM33);
}
void Setup_timer5(void)
{
sbi (TCCR5B, CS50);
cbi (TCCR5B, CS51);
cbi (TCCR5B, CS52);
cbi (TCCR5A, COM5A0);
sbi (TCCR5A, COM5A1);
cbi (TCCR5A, COM5B0);
sbi (TCCR5A, COM5B1);
cbi (TCCR5A, COM5C0);
sbi (TCCR5A, COM5C1);
sbi (TCCR5A, WGM50);
sbi (TCCR5A, WGM51);
cbi (TCCR5B, WGM52);
cbi (TCCR5B, WGM53);
}
Setup_timer2();
void Setup_timer2()
{
//Prescaler : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
cbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
cbi (TCCR2A, COM2B1);
//Phase Correct PWM
sbi (TCCR2A, WGM20);
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
volatile byte ms4_delay;
volatile byte c4ms;
if (c4ms > 25)
{
c4ms=0;
offset_3=analogRead(0)/4;
dfreq=50.0;
cbi (TIMSK2,TOIE2);
tword_m=pow(2,32)*dfreq/refclk;
sbi (TIMSK2,TOIE2);
}
*/
/*
if(ms4_delay++ == 125)
{
c4ms++;
ms4_delay=0; //reset count
}
coffs = pgm_read_word_near(sine512 + coffs2 - 1);
OCR1B = ((word)coffs*99)/100; // +1 korekce
*/
/*
*/
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcat_P(dest, src) strcat((dest), (src))
#define strcmp_P(a, b) strcmp((a), (b))
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#endif
// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //define a bit to have the properties of a clear bit operator
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator
int PWM1= 11;// PWM1 output, phase 1
int PWM2 = 3; //[WM2 ouput, phase 2
int PWM3 = 10; //PWM3 output, phase 3
int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls
int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls
int program_exec_time = 6; //monitor how quickly the interrupt trigger
int ISR_exec_time = 7; //monitor how long the interrupt takes
double dfreq;
const double refclk=31376.6; // measured output frequency
// variables used inside interrupt service declared as voilatile
volatile byte current_count; // Keep track of where the current count is in sine 256 array
volatile byte ms4_delay; //variable used to generate a 4ms delay
volatile byte c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second
volatile unsigned long phase_accumulator; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.
void setup()
{
pinMode(PWM1, OUTPUT); //sets the digital pin as output
pinMode(PWM2, OUTPUT); //sets the digital pin as output
pinMode(PWM3, OUTPUT); //sets the digital pin as output
pinMode(program_exec_time, OUTPUT); //sets the digital pin as output
pinMode(9, OUTPUT); //sets the digital pin as output
sbi(PORTD,program_exec_time); //Sets the pin
Setup_timer1();
Setup_timer2();
//Disable Timer 1 interrupt to avoid any timing delays
cbi (TIMSK0,TOIE0); //disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); //enable Timer2 Interrupt
dfreq=1000.0; //initial output frequency = 1000.o Hz
tword_m=pow(2,32)*dfreq/refclk; //calulate DDS new tuning word
}
void loop()
{
while(1)
{
sbi(PORTD,program_exec_time); //Sets the pin
if (c4ms > 250) // c4ms = 4ms, thus 4ms *250 = 1 second delay
{
c4ms=0; //Reset c4ms
dfreq=analogRead(0); //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz
cbi (TIMSK2,TOIE2); //Disable Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; //Calulate DDS new tuning word
sbi (TIMSK2,TOIE2); //Enable Timer2 Interrupt
}
}
}
//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer1(void)
{
// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer1 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0);
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0);
sbi (TCCR1A, COM1B1);
// Mode 1 / Phase Correct PWM
sbi (TCCR1A, WGM10);
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2()
{
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
sbi (TCCR2A, COM2B1);
// Mode 1 / Phase Correct PWM
sbi (TCCR2A, WGM20);
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
//Timer2 Interrupt Service at 31372,550 KHz = 32uSec
//This is the timebase REFCLOCK for the DDS generator
//FOUT = (M (REFCLK)) / (2 exp 32)
//Runtime : 8 microseconds
ISR(TIMER2_OVF_vect)
{
cbi(PORTD,program_exec_time); //Clear the pin
sbi(PORTD,ISR_exec_time); // Sets the pin
phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.
current_count=phase_accumulator >> 24; // use upper 8 bits of phase_accumulator as frequency information
OCR2A=pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM
OCR2B=pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_1)); // read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM1
OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
//increment variable ms4_delay every 4mS/125 = milliseconds 32uS
if(ms4_delay++ == 125)
{
c4ms++;
ms4_delay=0; //reset count
}
cbi(PORTD,ISR_exec_time); //Clear the pin
}
##############################################################
atmega328bb.name=ATmega328 on a breadboard (8 MHz internal clock)
atmega328bb.upload.protocol=stk500
atmega328bb.upload.maximum_size=30720
atmega328bb.upload.speed=57600
atmega328bb.bootloader.low_fuses=0xE2
atmega328bb.bootloader.high_fuses=0xDA
atmega328bb.bootloader.extended_fuses=0x05
atmega328bb.bootloader.path=arduino:atmega
atmega328bb.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
atmega328bb.bootloader.unlock_bits=0x3F
atmega328bb.bootloader.lock_bits=0x0F
atmega328bb.build.mcu=atmega328p
atmega328bb.build.f_cpu=8000000L
atmega328bb.build.core=arduino:arduino
atmega328bb.build.variant=arduino:standard
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcat_P(dest, src) strcat((dest), (src))
#define strcmp_P(a, b) strcmp((a), (b))
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#endif
// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //define a bit to have the properties of a clear bit operator
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))//define a bit to have the properties of a set bit operator
int PWM1= 11;// PWM1 output, phase 1
int PWM2 = 3; //[WM2 ouput, phase 2
int PWM3 = 10; //PWM3 output, phase 3
int offset_1 = 85; //offset 1 is 120 degrees out of phase with previous phase, Refer to PWM to sine.xls
int offset_2 = 170; //offset 2 is 120 degrees out of phase with offset 1. Refer to PWM to sine.xls
int program_exec_time = 6; //monitor how quickly the interrupt trigger
int ISR_exec_time = 7; //monitor how long the interrupt takes
double dfreq;
const double refclk=31376.6; // measured output frequency
// variables used inside interrupt service declared as voilatile
volatile byte current_count; // Keep track of where the current count is in sine 256 array
volatile byte ms4_delay; //variable used to generate a 4ms delay
volatile byte c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second
volatile unsigned long phase_accumulator; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.
void setup()
{
pinMode(PWM1, OUTPUT); //sets the digital pin as output
pinMode(PWM2, OUTPUT); //sets the digital pin as output
pinMode(PWM3, OUTPUT); //sets the digital pin as output
pinMode(program_exec_time, OUTPUT); //sets the digital pin as output
pinMode(9, OUTPUT); //sets the digital pin as output
sbi(PORTD,program_exec_time); //Sets the pin
Setup_timer1();
Setup_timer2();
//Disable Timer 1 interrupt to avoid any timing delays
cbi (TIMSK0,TOIE0); //disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); //enable Timer2 Interrupt
dfreq=1000.0; //initial output frequency = 1000.o Hz
tword_m=pow(2,32)*dfreq/refclk; //calulate DDS new tuning word
}
void loop()
{
while(1)
{
sbi(PORTD,program_exec_time); //Sets the pin
if (c4ms > 250) // c4ms = 4ms, thus 4ms *250 = 1 second delay
{
c4ms=0; //Reset c4ms
dfreq=analogRead(0); //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 1.023kHz
cbi (TIMSK2,TOIE2); //Disable Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; //Calulate DDS new tuning word
sbi (TIMSK2,TOIE2); //Enable Timer2 Interrupt
}
}
}
//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer1(void)
{
// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer1 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0);
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0);
sbi (TCCR1A, COM1B1);
// Mode 1 / Phase Correct PWM
sbi (TCCR1A, WGM10);
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
//Timer 1 setup
//Set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2()
{
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
sbi (TCCR2A, COM2B1);
// Mode 1 / Phase Correct PWM
sbi (TCCR2A, WGM20);
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
//Timer2 Interrupt Service at 31372,550 KHz = 32uSec
//This is the timebase REFCLOCK for the DDS generator
//FOUT = (M (REFCLK)) / (2 exp 32)
//Runtime : 8 microseconds
ISR(TIMER2_OVF_vect)
{
cbi(PORTD,program_exec_time); //Clear the pin
sbi(PORTD,ISR_exec_time); // Sets the pin
phase_accumulator=phase_accumulator+tword_m; //Adds tuning M word to previoud phase accumulator. refer to DDS_calculator (from Martin Nawrath) for explination.
current_count=phase_accumulator >> 24; // use upper 8 bits of phase_accumulator as frequency information
OCR2A=pgm_read_byte_near(sine256 + current_count); // read value fron ROM sine table and send to PWM
OCR2B=pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_1)); // read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM1
OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(current_count + offset_2));// read value fron ROM sine table and send to PWM, 120 Degree out of phase of PWM2
//increment variable ms4_delay every 4mS/125 = milliseconds 32uS
if(ms4_delay++ == 125)
{
c4ms++;
ms4_delay=0; //reset count
}
cbi(PORTD,ISR_exec_time); //Clear the pin
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น