Shield-A, učni pripomoček za programiranje mikrokontrolerjev (12)V nadaljevanju bomo pokazali, da lahko RGB diode prikazujejo veliko, veliko več, kot sedem barv. Za to je treba mešati osnovne barve – rdečo, zeleno in modro – v različnih razmerjih. Resda vrednosti uporov R11, R12 in R13 ni mogoče programsko spreminjati, lahko pa vplivamo na trajanje (širino) trenutnih impulzov, s katerimi krmilimo rdeči, zeleni in modri čip. Risba na sliki 43 ponazarja, kaj smo s tem mislili.
Avtor: mag. Vladimir Mitrović
E-pošta: vmitrovic12@gmail.com
2021-299-29
Zgornja slika prikazuje situacijo, ko skozi LED teče konstanten, največji tok, določen z napajalno napetostjo in vrednostjo upora, ki omejuje tok: srednji tok skozi diodo je enak temu največjemu toku in dioda zasveti v polni intenzivnosti (srednji tok je prikazan z višino rdečega stolpca). Na naslednjih treh risbah tok teče v impulzih skozi LED-ico: na njih je frekvenca konstantna, vendar se trajanje (širina) impulza spreminja. Krajši ko so ti tokovni impulzi glede na trajanje obdobja T, manjši je srednji tok skozi diodo in dioda slabše sveti. Na koncu na spodnji risbi ni tokovnih impulzov in dioda ne sveti.
Proces imenujemo pulzno-širinska modulacija (PWM) in se pogosto uporablja pri prilagajanju hitrosti elektromotorjev in jakosti osvetlitve, pri nadzoru servomotorjev itd. Uporabili ga bomo za prilagajanje jakosti in barve svetlobe RGB diod D8-D11 na razvojnem sistemu Shield-A. Potrebovali bomo tri generatorje impulzov, po enega za vsako osnovno barvo. Vsak od timerjev ATmega328P mikrokontrolerja lahko generira dva PWM signala: uporabili bomo Timer0 in “polovico” Timer2. Oba timerja sta osem-bitna in širinsko modulirani impulzi se generirajo, ko sta konfigurirana kot kaže slika 44.
Ta vsebina je samo za naročnike
Časovniki v PWM načinu štejejo od 0 do 255 in nato nazaj, proti 0. Zaradi tega načina štetja se vhodni signal 250 kHz ne bo delil s faktorjem 256, temveč s 512, kar bo dalo impulze približno 488 Hz – še vedno dovolj, da dobimo iluzijo, kako LED sveti s stalno svetlobo in brez utripanja. Impulzi se ustvarijo s primerjavo trenutne vrednosti časovnika z vrednostjo, vneseno v OCR registre. Ko timer prišteva in je vrednost števca enaka vrednosti v OCR registru, bo OC povezan izhod spremenil stanje iz »1« v »0«. Ko timer odšteva in je vrednost števca enaka vrednosti v OCR registru, bo OC povezan izhod spremenil stanje iz »0« v »1«. Tako vrednost, ki jo vnesemo v OCR registre, določa trajanje ali širino impulza: višja kot je vnesena vrednost, širši bodo impulzi. Opazili bomo, da so na sliki 44 vsi simboli modri, kar v skladu z našim prejšnjim dogovorom pomeni, da celoten postopek poteka na strojni ravni: program mora konfigurirati timerje, vnesti želene vrednosti v OCR registre in nato lahko stori karkoli, timerja bosta še naprej neodvisno ustvarjala impulze!
Slika 45 prikazuje, da izhodi OC0B, OC0A in OC2B uporabljajo iste priključke mikrokontrolerja, kot PD5, PD6 in PD3. Pravzaprav v trenutku, ko nastavimo timerje, da delujejo v PWM načinu, priključki PD5, PD6 in PD3 izgubijo svojo digitalno vhodno / izhodno funkcijo in se povežejo z OC izhodi timerja (oznake ~ 5, ~ 6 in ~ 3 v Arduino zapisu). Izhoda OC0B (~ 5) in OC0A (~ 6) določata tok rdečega in modrega RGB diodnega čipa. Vendar OC2B (~ 3) ni neposredno povezan z zelenim čipom; če želimo uporabiti ta izhod, ga moramo priključiti na priključek PD7 (na sliki 45 zeleni mostiček, označen s klicajem). Najbolj praktično je to narediti tako, da povežete 6. in 14. priključek na konektorju alfanumeričnega zaslona (slika 46).
Pomembno: PD7 mora biti konfiguriran kot vhod; v nasprotnem primeru ne bomo dosegli želenega učinka in možne so trajne poškodbe mikrokontrolerja! Za pravilno izbiro vrednosti uporov R11-R13 glejte predhodni članek.
V naslednjih primerih se bomo naučili, kako nastaviti timerje iz programa za delovanje v PWM načinu!
15. programska naloga: Na RGB diodah D8-D11 postopoma spreminjajte jakost rdeče svetlobe od najmanjše do največje in nazaj; isto ponovite z zeleno in modro. Poleg tega naj na RGB diodah D8-D11 barve postopoma prehajajo iz modre v rdečo, nato iz rdeče v zeleno in nazadnje iz zelene nazaj v modro.
Bascom-AVR rešitev
(program Shield-A_15a.bas)
Najprej bomo vse priključke mikrokontrolerja, na katere so priključene katode RGB diod, konfigurirali kot izhod in jih postavili v stanje “0”:
Config Portb = &B00001111 Portb = &B00000000
S tem smo hkrati vklopili vse štiri RGB diode (tu ne uporabljamo multipleksiranja). Ni nam bilo treba konfigurirati priključkov PD5, PD6 in PD3 kot izhode, ker bomo namesto tega uporabili izhode timerja PWM, OC0B, OC0A in OC2B. Timerja konfiguriramo glede na zastavljeno nalogo:
Config Timer0 = Pwm , Prescale = 64 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up Config Timer2 = Pwm , Prescale = 64 , Compare B Pwm = Clear Up
Tukaj boste opazili, da sta oba timerja postavljena v PWM način dela s faktorjem deljenja 64, Compare A in Compare B sta Bascom-AVR imeni za OCR registra. Tema OCR registroma bomo dodelili alternativni imeni v skladu z barvami, ki jih krmilijo in vpisali jim bomo začetno vrednost 0 – tako so vse barve izključene.
Modra Alias Ocr0a Rdeča Alias Ocr0b Zelena Alias Ocr2b Modra = 0 Rdeča = 0 Zelena = 0
V programu bomo uporabili še pomožno spremenljivko Barva:
Dim Barva As Byte
Njeno vrednost bomo menjati v For-Next zanki od 0 do 255
Do Wait 1 For Barva = 0 To 255 Rdeča = Barva Waitms 20 Next
in nato nazaj, od 255 do 0:
For Barva = 255 To 0 Step -1 Rdeča = Barva Waitms 20 Next
Vsako vrednost bomo prenesli v OCR0B register (= Rdeča) in tako postopno menjali intenziteto rdeče barve od ugasnjene do maksimuma in nazaj. Isto bomo ponovili z zeleno in modro barvo in zaključili glavno Do-Loop zanko: For Barva = 0 To 255 Zelena = Barva ... For Barva = 0 To 255 Modra = Barva ... Loop
Bascom-AVR rešitev dodatne naloge
(program Shield-A_15b.bas)
Če želimo spreminjati barve v skladu z zastavljeno nalogo, bomo morali hkrati spreminjati parametre dveh barv:
Do Wait 1 For Barva = 0 To 255 Rdeča = Barva Modra = 255 - Barva Waitms 20 Next
V tej For-Next zanki bo rdeča postopoma rastla od ugasnjene do maksimalne intenzivnosti, modra pa se sočasno zmanjševala od maksimalne intenzivnosti do ugasnjene: prehod iz modre v rdečo barvo se bo dogodil preko različnih nians vijolične barve. Na isti način bomo dosegli prehod rdeče v zeleno preko oranžne in rumenozelene, ter zelene v modro preko modrozelene:
Wait 1 For Barva = 0 To 255 Zelena = Barva Rdeča = 255 - Barva Waitms 20 Next Wait 1 For Barva = 0 To 255 Modra = Barva Zelena = 255 - Barva Waitms 20 Next Loop
Ostanek programa je identičen programu Shield-A_15a.bas!
Arduino rešitev
(program Shield-A_15a.ino)
V Arduino IDE obstaja funkcija analogWrite(), ki nam omogoča enostavno krmiljenje s PWM priključki oziroma z OC izhodi timerja. Funkcija sprejema dva argumenta: številko priključka in vrednost od 0 do 255 (kar označuje širino impulza). Funkcija prepoznava ali je priključek povezan z OC izhodom timerja in če je povezan s katerim izhodom.
Ker v C programskem jeziku ne obstaja ukaz alias, je za namene enostavnejšega branja programske kode potrebno uporabiti spremenljivke s samopojasnujočimi imeni. Njihova vrednost bo številka priključka, ki je priključen na OC izhod timerja:
byte rdeča = 5; byte modra = 6; byte zelena = 3;
Najprej bomo vse priključke mikrokontrolerja, na katere so spojene katode RGB diod, konfigurirati kot izhodne in jih postavili v stanje “0”:
void setup() { DDRB = B00001111; PORTB = B00000000;
Nato nastavimo D7 priključek kot vhod za zaščito mikrokontrolerja pred kratkim stikom na priključku D3:
pinMode(7, INPUT); }
S postavljanjem katod RGB diod v stanje “0” smo sočasno vklopili vse štiri RGB diode (tu ne uporabljamo multipleksiranja). Ni nam bilo treba konfigurirati priključkov PD5, PD6 in PD3 kot izhode, ker bomo namesto tega uporabili izhode timerja PWM, OC0B, OC0A in OC2B. Arduino IDE samodejno konfigurira timerje v PWM načinu s faktorjem deljenja 64, zato nam tega ni treba storiti.
V funkciji loop() bomo s pomočjo for zankemenjali vrednost spremenljivke barva od 0 do 255
void loop() { delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(rdeča, barva); delay(20); }
in nato nazaj, od 255 do 0:
for ( int barva = 255; barva >=0; barva--){ analogWrite(rdeča, barva); delay(20); }
Funkcija analogWrite() prenaša vsako novo vrednost spremenljivke Barva v OCR0B register, s čemer postopno menjamo intenziteto rdeče barve od ugasnjene do maksimuma in nazaj. Isto bomo ponovili z zeleno in modro barvo in zaključili glavno loop() funkcijo:
delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(zelena, barva); delay(20); } for ( int barva = 255; barva >=0; barva--){ analogWrite(zelena, barva); delay(20); } delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(modra, barva); delay(20); } for ( int barva = 255; barva >=0; barva--){ analogWrite(modra, barva); delay(20); } }
Arduino rešitev dodatne naloge
(program Shield-A_15b.ino)
Uporabili bomo isti algoritem kot v rešitvi za Bascom-AVR:
void loop() { delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(rdeča, barva); analogWrite(modra, 255-barva); delay(20); } delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(zelena, barva); analogWrite(rdeča, 255-barva); delay(20); } delay(1000); for ( int barva = 0; barva <=255; barva++){ analogWrite(modra, barva); analogWrite(zelena, 255-barva); delay(20); } }
Ostanek programa je identičen programu Shield-A_15a.ino!
***
V programih smo ustvarili 256 različnih intenzivnosti posamezne barve. Opazili boste, da so razlike med obema korakoma zelo opazne pri nizki intenzivnosti, medtem ko je pri večjih intenzivnostih to razliko težko opaziti. To je posledica narave človeškega vida: če bi želeli spremembe intenzivnosti narediti vidne tudi pri večji intenzivnosti, bi morali uporabiti zanke s spremenljivim korakom. Tega nismo storili z razlogom, želeli smo, da so programi čim bolj preprosti in razumljivi. Iz istega razloga smo se izognili hkratnemu prikazovanju različnih barv na RGB diodah, ker bi potem morali programe zapletati z multipleksiranjem – to bomo pustili za naslednje nadaljevanje!
Opomba: Programe Shield-A_15a.bas, Shield-A_15a.ino, Shield-A_15b.bas in Shield-A_15b.ino lahko brezplačno dobite v uredništvu revije Svet elektronike.
Shield-A (12)