Arduino 3 phase inverter

 //Auto Rerun 3 sinus motor controller Arduino mini 168 Arduino 328 P 

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

pinMode(13, 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()

{

t_param = map(analogRead(3),0,1023,0,100);

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

blad = 1; //jezeli przeciazenie wylaczenie generacji napiecia

//digitalWrite(13, HIGH); //zapalenie diody

//jezeli przeciazenie wylaczenie generacji napiecia

digitalWrite(12, LOW); //zapalenie diody 

}

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

พุทธัง สะระณัง คัจฉามิ