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).