Krmiljenje svetilnosti (PWM) s tipko (uporaba Timer2)

S tipko želimo spreminjati svetilnost razsvetljave (LED diode). Na začetku LED dioda ne sme svetiti, ko pritisnemo na tipko prvič, krmili LED diodo PWM signal z duty cyclom 30%, ko pritisnemo na tipko drugič, krmili LED diodo PWM signal z duty cyclom 60%, ko pritisnemo na tipko tretjič, krmili LED diodo PWM signal z duty cyclom 100%, s ponovnim pritiskom na tipko LED izklopimo. PWM signal naj bo oblike Phase Correct. Na serijskem monitorju se naj izpiše podatek o procentu duty cyclya. Postopek se mora ponavljati.

Uporabili bomo Timer2.

Tabela 1: Opis delovanja.

Timer2 je 8-bitni. Svoje izhodne PWM pine ima na pinu 11 (OC2A) in na pinu 3 (OC2B).

Tabela 2: Vloga bitov CS20, CS21 in CS22.

Tabela 3: Načini delovanja Timer2.

/*

   Primer Phase Correct PWM, Mode 1, Timer2.

   Krmiljenje LED diode s PWM signalom različnih duty cycle s pritiski na tipko.

   April 2015

   Avtor: Milan Ivič

 */

  int Tipka = 4;

  int StevecTipke = 0;         //Števec za shranjevanje števila pritiskov na tipko.

  int PrejsnjeStanjeTipke = LOW;

  float Duty_Cycle;

 void setup()

 {

    pinMode(Tipka, INPUT);

    pinMode(11, OUTPUT);     //PWM izhodni pin 11.

    Serial.begin(9600);

    //Neinvertirujoč PWM (pin 11) => bit COM2A1 postavimo na 1.

    //Bit WGM20 postavimo na 1 => PWM Phase Correct.

    TCCR2A = _BV(COM2A1) | _BV(WGM20);      //Pin 11, Phase Correct PWM, Mode 1.

    

    //Za preddelitev 1:64 postavimo bit CS22 na 1:

    TCCR2B = _BV(CS22);    //Preddelitev 1:64  => f=16000000/(64*255*2)= 490,196 Hz.

                                          //64 => preddelitev.

                                          //255 => Timer2 je 8 bitni register.

                                          //množeno z 2 => Timer2 se povečuje in ko doseže zg. vrednost se zmanjšuje.

 }

 void loop()

 {

   int TrenutnoStanjeTipke = digitalRead(Tipka);

   if (TrenutnoStanjeTipke != PrejsnjeStanjeTipke && TrenutnoStanjeTipke == HIGH)

    { 

      Serial.print("Pritisk na tipko:  ");

      Serial.println(StevecTipke);

      StevecTipke = StevecTipke + 1;    //Ob pritisku na tipko se StevecTipke poveča za 1.

      delay(100);                               //Zaradi odbijanja kontaktov tipke.

    }

   PrejsnjeStanjeTipke = TrenutnoStanjeTipke;   //Zaradi uporabe tipke.

   delay(100);                                  //Zaradi odbijanja kontaktov tipke.

    

    if(StevecTipke > 3)                //Imamo 4 možnosti: 0%, 30%, 60% in 100%.

    {

      StevecTipke = 0;

    }

    

    switch(StevecTipke)

    {

      case 0:

        OCR2A = 0;

        Duty_Cycle = 100/255*0;        //Izračun duty cycle.

        Serial.print("LED dioda ne sveti, duty cycle: ");

        Serial.print(Duty_Cycle);

        Serial.println(" %");

        delay(20);

        break;

        

      case 1:

        OCR2A = 77;                //Duty Cycle = 30%.

        Duty_Cycle = 100*77/255;

        Serial.print("LED dioda sveti, duty cycle: ");

        Serial.print(Duty_Cycle);

        Serial.println(" %");

        delay(20);

        break;

      

      case 2:

        OCR2A = 153;                 //Duty Cycle = 60%.

        Duty_Cycle = 100*153/255;

        Serial.print("LED dioda sveti, duty cycle: ");

        Serial.print(Duty_Cycle);

        Serial.println(" %");

        delay(20);

        break;

        

      case 3:

        OCR2A = 255;                //Duty Cycle = 100%.

        Duty_Cycle = 100*255/255;

        Serial.print("LED dioda sveti, duty cycle: ");

        Serial.print(Duty_Cycle);

        Serial.println(" %");

        delay(20);

        break;

    }

 }

Slika 1: Izpis ns serijskem monitorju

Stavki switch-case:

Stikalni stavki so izbirni stavki, povezani s skoki. Sintaksa uporabe je:

switch (izraz_stikala) stikalni_blok

Ta stavek se uporablja, ko nas zanima vrednost v izraz_stikala, ta pa sme biti tipa int ali char. Za vsako vrednost, ki nas zanima, mora biti v stikalnem bloku definiran cilj skoka z oznako case (v primeru da je ...):

Posebni primer oznake case je oznaka:

default:

in pomeni "sicer", če ne velja noben case. Zato se sme oznaka default pojaviti le enkrat v stikalnem bloku.

Slika 2: Diagram poteka za stavek switch-case

V namen, da se izvede samo tisti case, kateremu vrednost ustreza, uporabimo stavek break. Stavek break omogoči, da se izvede samo blok case, kateremu vrednost ustreza.

V programu v spremenljivko StevecTipke shranjujemo pritiske na Tipko. Te so lahko 0, 1, 2 in 3. Pri naslednjem pritisku na Tipko se spremenljivka StevecTipke inicializira na 0:

   if(StevecTipke > 3)

   {

      StevecTipke = 0;

   }

StevecTipke uporabimo za izraz stikala switch. Izvede se stikalni blok, ki ustreza številki, shranjeni v stikalu stavka switch-case. Da se izvele le ustrezni blok, na koncu vsakega uporabimo stavek break.

Za generiranje PWM signala smo uporabili Timer2, ki je 8-bitni in deluje v načinu Phase Correct PWM (Mode 1). Zato setiramo bit WGM20 v TCCR2A registru (tabela 3). Preddelitev smo izbrali 1:256, PWM signal pa je generiran na pinu 11 (setiran bit COM2A1 v registru TCCR2A).