วันพุธที่ 31 พฤษภาคม พ.ศ. 2560

โปรแกรม Arduino ให้เป็น อินเวอร์เตอร์ สามเฟสTomasz Drazek 3 Phase Motor ...

//Arduino   Atmega 168    Atmega   328P 3 phase induction motor Variable Speed Controller //Code

// Complier By  Arduino    Version   101    Version   106  Software 
//รุ่นนี้เป็นแบบ AUTO RE RUN โค๊ดนี้ใช้วอลลุ่ม  5KB ตัวเดียวทำหน้าที่ ปิด -ปิด ปรับรอบ  ให้ใช้ R  //4K7  ต่อ ไฟ+5Vdc แล้วต่อเข้า ขาข้างด้าน + MAX    ของ VR  ต่อ R 1K-10 K  ต่อ เข้า A3 ของ //ATmega 168   ATmega 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); 
}
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(12, LOW); //zapalenie diody 
}

ไม่มีความคิดเห็น:

แสดงความคิดเห็น