วันศุกร์ที่ 28 ตุลาคม พ.ศ. 2559

เราจะก้าวข้ามยุคสมัยไปพร้อมกัน





#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/100+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

}


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

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