Avtor: mag. Vladimir Mitrović
E-pošta: vmitrovic12@gmail.com
2019_271_43
Z našo serijo člankov o Arduino kompatibilnih modulih, ki jo na straneh revije Svet elektronike spremljate že več kot eno leto, želimo te poceni module približati Bascom-AVR uporabnikom. Do sedaj smo predstavili 13 programskih knjižnic z več kot 200 novimi ukazi in s tem pomembno obogatili Bascom-AVR programski jezik. Za vsakega od predstavljenih modulov smo napisali tudi nekaj testnih programov, ki ilustrirajo način uporabe njemu pridružene knjižnice in njenih ukazov
Sedaj je prišel čas za preboj: predstavljamo nastale projekte, v katerih se uporabljajo Arduino kompatibilni moduli krmiljeni z Bascomom in ukazi iz naših knjižnic! Pričnimo s kolekcijo ur, prikazanih na fotografijah na sliki 44.
Analogna ura z LED prstani
Prva od njih je kvazi analogna ura z LED prstani, v kateri se uporablja različna Arduino kompatibilna “ekipa” prikazana na fotografiji na sliki 45.
Ta vsebina je samo za naročnike
Shema ure je prikazana na sliki 46 in je res minimalistična. Precizna ura realnega časa je IC DS3231 iz ZS-042 modula. Za prikaz časa se uporabljata dva koncentrično postavljena prstana z 12 oziroma 24 WS2812B RGB čipi. Povezavo med njima dela AVR mikrokontroler, kot ATmega328P ali ATtiny85. Namesto mikrokontrolerja se lahko uporabijo tudi ustrezni moduli; jaz sam preizkusil Arduino Nano z ATmega328P mikrokontrolerjem. Prednost uporabe teh modulov glede na sam mikrokontroler je v tem, ker so na modulu integrirana še druga koristna vezja, kot napetostni stabilizator in programator. Uporaba modula prinaša tudi določene pomanjkljivosti, s katerimi se bomo pozabavali v enem od naslednjih nadaljevanj; v projektih, ki jih sedaj opisujemo, smo se jim spretno izognili. Tabela na sliki 46 prikazuje katere pine mikrokontrolerja, oziroma katere priključke Arduino Nano modula uporabljamo v naši uri.
Razjasnimo sedaj, kako je realiziran prikaz časa na prstanih z RGB čipi. Kroženje malega in velikega kazalca ure simulira postopno premikanje svetlobe z enega na drugi RGB čip manjšega, oziroma večjega prstana. Na slikah 47 in 48 svetli krožci predstavljajo ugasnjene, zatemnjeni krožec pa predstavlja vklopljen RGB čip. Intenziteto svetilnosti simbolizira stopnja zatemnjevanja: čim bolj je krog zatemnjen, večja je intenzivnosti svetilnosti ustreznega RGB čipa.
Manjši prstan ima 12 RGB čipov in tu je situacija lažje razumljiva: vsaki uri ustreza po en RGB čip. Poglejmo na sliki 47 kako bo izgledal prikaz časa v razponu od 12:00 do 12:45 in s pomiki po 15 minut:
- ob 12:00 s polno svetilnostjo svetijo RGB čipi 12h in 0m;
- ob 12:15 RGB čip 15m sveti s polno svetilnostjo, ker se “veliki kazalec” nahaja točno na poziciji 15m, medtem ko čip 12h sveti s 3/4, čip 1h z 1/4 intenzivnosti, kar signalizira, da se je “mali kazalec” premaknil proti 1h;
- ob 12:30 RGB čip 30m sveti s polno svetilnostjo, ker se “veliki kazalec” nahaja točno na poziciji 30m, medtem ko čipa 12h in 1h svetita z 1/2 intenzivnosti, kar signalizira, da se “mali kazalec” nahaja med 12h in 1h;
- ob 12:45 RGB čip 45m sveti s polno svetilnostjo, ker se “veliki kazalec” nahaja točno na poziciji 45m, medtem ko čip 12h sveti s 1/4, čip 1h pa s 3/4 intenzivnosti, kar signalizira, da se “mali kazalec” približuje poziciji 1h.
Večji prstan služi za prikaz minut in tu bi bilo idealno, če bi lahko uporabili prstan s 60 RGB čipi. Na žalost takšen prstan ne obstaja v komercialni ponudbi, zato sem izbral izvedbo s 24 RGB čipi, po eden za vsake 2,5 minute. Poglejmo na sliki 48 kako bo na takem prstanu izgledal prikaz časa v razponu od 12:00 do 12:05, v pomikih ene minute:
- ob 12:00 s polno svetilnostjo svetita RGB čipa 12h in 0m;
- ob 12:01 RGB čip 0m sveti s 2/3, čip 2,5m pa z 1/3 intenzivnosti, s čemer simbolizira, da se je “veliki kazalec” premaknil na nevidno pozicijo 1m; čip 12h sveti s polno svetilnostjo, čip 1h pa komaj vidno, kar signalizira, da se je tudi “mali kazalec” malo premaknil;
- ob 12:02 RGB čip 0m sveti s 1/3, čip 2,5m pa z 2/3 intenzivnosti, s čemer simbolizira, da se je “veliki kazalec” premaknil na neviden položaj 2m; čip 12h še naprej sveti s polno svetilnostjo, čip 1h je komaj viden;
- ob 12:03 RGB čip 2,5m sveti z 2/3, čip 5m pa z 1/3 intenzivnosti, s čemer simbolizira, da se je “veliki kazalec” premaknil na neviden položaj 3m; čip 12h še naprej sveti s polno svetilnostjo, čip 1h pa je komaj viden;
- ob 12:04 RGB čip 2,5m sveti z 1/3, čip 5m pa z 2/3 intenzivnosti, s čemer simbolizira, da se je “veliki kazalec” premaknil na neviden položaj 4m; čip 12h še naprej sveti s polno svetilnostjo, čip 1h je komaj viden;
- ob 12:05 RGB čip 5m sveti s polno svetilnostjo s čemer simbolizira, da se je “veliki kazalec” pokril s 5m; čip 12h še naprej sveti s polno svetilnostjo, čip 1h je komaj viden.
Ko bo čas tekel, se bodo ponavljale kombinacije od a) do f) za “velik kazalec”, medtem ko se bo pri “malem kazalcu” čip 12h postopno ugašal, čip 1h pa bo postaja vse svetlejši, kot smo že imeli priložnost videti na sliki 46.
Opomba: navedene intenzivnosti zgolj ilustrirajo princip prikaza časa; ker WS2812B RGB čipi lahko reproducirajo preko 16 milijonov različnih barv in intenzivnosti, ima programer veliko možnosti, da ustvari efekte v skladu z lastnimi željami in znanjem. Da bi to uspeli prikazati, smo v programskem primeru, ki ga opisujemo, napravili razliko med dopoldanskim in popoldanskim časom: za prikaz časa v dopoldanskih urah (0:00 – 11:59) se uporablja rdeča, v popoldanskih urah (12:00 – 23:59) pa modra svetloba različnih intenzivnosti. Zato je v fotografiji na sliki 49 sedaj točno 0:15, in ne 12:15.
Program Ring_ura_SE.bas
Program, katerega logiko prikazuje diagram poteka na sliki 50, je napisan za vezje glede na shemo na sliki 46 in mikrokontrolerje ATmega328P ali ATtiny85. Program je sestavljen iz inicializacijskega dela, glavne zanke in zanke za nastavljanje ure. Nastavljanje ure se bo aktiviralo, če je pritisnjena tipka T1 dalj kot 1s in se odvija po sledeči proceduri:
- prstan za prikaz minut se ugasne, svetloba dvakrat “odteče” preko vseh RGB čipov za prikaz ur in nato s polno svetilnostjo sveti RGB čip, ki ustreza trenutnemu času (uram);
- ure se menjajo s kratkimi pritiski na tipko T1, pri čemer vsaki pritisk pomeni +1h; dopoldanski in popoldanski čas se razlikujeta po barvi svetlobe RGB čipov;
- nastavljanje ur se konča s pritiskom na tipko T1 v trajanju daljšem od 1s: prstan za prikaz ur ugasne, svetloba”odteče”preko vseh RGB čipov za prikaz minut in nato svetijo RGB čipi, ki prikazujejo trenuten čas (minute);
- minute se menjajo s kratkimi pritiski na tipko T1, pri čemer vsak pritisk pomeni +1m;
- nastavljanje časa se konča s pritiskom na T1 v trajanju daljšem od 1s: sekunde se resetirajo na 0, svetloba odteče preko obeh prstanov in nato ura nadaljuje prikazovati čas na običajni način.
Tukaj bomo pojasnili samo najvažnejše dele programa; za popolno razumevanje je potrebno preučiti celoten program. V inicializacijskem delu definiramo, da se za komunikacijo z LED prstanoma uporablja pin PB4
Const Led_port = Portb Const Led_pin = 4
nato tudi trajanje reset impulzov in skupno število WS2812B čipov na prstanih:
Const Led_reset = 80 Const Led_number = 36
Po tem vključujemo obe knjižnici, tisto z ukazi za LED prstana in tisto z ukazi za uro realnega časa DS3231:
$include "WS2812B$SE.sub" $include "DS3231$SE.sub"
Moramo še definirati tudi pine, ki krmilijo I2C vodilo, preko katerega je DS3231 povezan z mikrokontrolerjem:
Config Scl = Portb.1 Config Sda = Portb.0 I2cinit
Tretja povezava, ki povezuje DS3231 z mikrokontrolerjem, je SQW; čeprav se v tem programu ne uporablja, bomo konfigurirali ustrezen pin mikrokontrolerja kot vhodnega in s tem omogočili možne nadgradnje programa:
Sqw Alias Pinb.2 Portb.2 = 1 : Config Sqw = Input
Pred vhodom v glavno Do-Loop zanko je treba še zbrisati trenutni prikaz na prstanih
Ws2812b$clear_all Ws2812b$show_all
in na ustrezen način inicijalizirati DS3231 čip:
Ds3231$write_control &B00000000
V glavni zanki se pogosto preverja, ali je pritisnjena tipka T1 (Set_button)
Do Debounce Set_button , 0 , Set_time , Sub
in če je, se izvrši rutina za nastavljanje ur po prej opisani proceduri. V glavni zanki se prav tako 2 krat v sekundi odčitava točen čas iz DS3231 čipa
... Gosub Read_hhmmss
in se ga pripravi za prikaz na displeju:
Gosub Disp_hh Gosub Disp_mm ... Loop
Podprogrami za prikaz na displeju uporabljajo tabele, v katerih so definirane barve in intenzivnosti svetilnosti, ki jih mora posamezni RGB prikazati v določenem času. Te tabele so nameščene v EEPROMu mikrokontrolerja. Podprogram Disp_hh uporablja tabele, ki definirajo vrednosti, ki bodo postavljene na dva sosedna RGB čipa manjšega prstana (ur):
$eeprom Dim Hh_r1am(13)as Eram Byte Data 16 , 15 , 14 , 14 , 12 , 12 , 8 , 8 , 4 , 4 , 2 , 2 , 1 ... Dim Hh_r2am(13)as Eram Byte Data 0 , 1 , 2 , 2 , 4 , 4 , 8 , 8 , 12 , 12 , 14 , 14 , 15
Tabela Hh_r1am vsebuje vrednosti, ki bodo postavljene na osnovni RGB čip (če je, ura npr., med 12 in 13, bo to RGB čip 1 na sliki 46), tabela Hh_r2am pa vsebuje vrednosti, ki bodo postavljene na naslednji RGB čip (če je ura med 12 in 13, bo to RGB čip 2 na sliki 46). Prvi par vrednosti (16,0) velja, kadar je točno 12:00: čip 1 sveti maksimalno (16), čip 2 pa je ugasnjen (0). Drugi par vrednosti (15,1) velja v času 12:01-12:05: čip 1 sveti s samo malo zmanjšano intenzivnostjo (15), čip 2 pa je minimalno vključen (1). Ko čas teče proti 12:59, se intenzivnost čipa 1 zmanjšuje, intenzivnost čipa 2 raste. Definiranih je skupno 13 parov vrednosti, od katerih prvi pokriva samo 1 minuto, zadnji 4 minute, vsi ostali pa po 5 minut. Ko preteče prva ura, se uporabljajo iste tabele, ki tedaj na isti način definirajo intenzitete RGB čipov 2 in 3, itd.
RGB čipi imajo 3 LEDice, zato se za definicijo intenzivnosti zelenega in modrega segmenta uporabljajo podatki iz podobnih tabel, Hh_g1am in Hh_g2am za zeleno, oziroma Hh_b1am in Hh_b2am za modro barvo. Ker program razlikuje dopoldanske in popoldanske ure obstaja še en komplet tabel za prikaz ur s sufiksom pm (Hh_r1pm , Hh_r2pm itd.) – skupaj je definiranih 156 vrednosti.
Podprogram Disp_hh postavlja vrednosti dveh sosednjih RGB čipov na manjšem prstanu. Trenutna vrednost ur bo določila vsebino spremenljivke Hh_led, ki predstavlja naslov prvega RGB čipa (1-12). Odvisno od trenutnih minut podprogram iz tabel prebere ustrezne vrednosti za rdeči, zeleni in modri segment tega čipa in jih shrani v spremenljivke Hh_red, Hh_green in Hh_blue. Preostane še prenos na naslovljen RGB čip prvi “komplet” barv
Ws2812b$set_pixel_color Hh_led , Hh_green , Hh_red , Hh_blue
in nato vse to, z ustreznimi vrednostmi, ponoviti tudi za drugi RGB čip.
Podprogram Disp_mm prikazuje minute na RGB čipih velikega prstana. Razpon 60 minut je razdeljen na 12 skupin s trajanjem 5 min; te skupine so 0-4 min, 5-9 min, …, 55-59 min. Znotraj vsake skupine se intenziteta osvetlitve čipov menja na način, ki smo ga pojasnili s pomočjo ilustracije na sliki 48: obstaja skupno 5 kombinacij, ki se postavljajo na tri sosednja RGB čipa in katere se menjajo z vsako preteklo minuto. Vrednosti za vsako posamezno kombinacijo se prav tako nahajajo v tabelah shranjenih v EEPROMu mikrokontrolerja. Tabele, ki definirajo intenziteto rdeče barve izgledajo tako:
Dim Mm_r1am(5)as Eram Byte Data 16 , 12 , 2 , 0 , 0 ... Dim Mm_r2am(5)as Eram Byte Data 0 , 2 , 8 , 8 , 2 ... Dim Mm_r3am(5)as Eram Byte Data 0 , 0 , 0 , 2 , 12
Opazili bomo, da je v prvi kombinaciji (16,0,0) vključen samo prvi RGB čip, nato se svetloba postopno seli proti drugemu (12,2,0), (2,8,0) in končno prehaja na tretji čip (0,8,2), (0,2,12). Podobne tabele so definirane tudi za zeleno in modro barvo, nato pa obstaja še en komplet tabel s sufiksom pm (Mm_r1pm , Mm_r2pm itd.) v katerem so definirane vrednosti za popoldanske ure – skupno je definiranih 90 vrednosti.
Podprogram Disp_mm bo preračunaval trenutno vrednost minut v indeksno spremenljivko Mm_led, ki predstavlja naslov ustreznega RGB čipa na velikem prstanu (13-36), in nato dohiti iz tabel pripadajoče vrednosti za rdeči, zeleni in modri segment tega čipa in jih shrani v spremenljivke Mm_red, Mm_green in Mm_blue.
Ko prenese adresiranemu RGB čipu prvi “komplet” barv
Ws2812b$set_pixel_color Mm_led , Mm_green , Mm_red , Mm_blue
bo podprogram isto proceduro ponovil za naslednja RGB čipa iz skupine.
Ker so tabele z intenzitetami ločeno shranjene v EEPROMu, jih pri programiranju mikrokontrolerja ne smemo pozabiti, da potrebno programirati tudi EEPROM in ne samo programski spomin mikrokontrolerja! Če je mikrokontroler med programiranjem že povezan z LED prstani, je priporočljivo najprej programirati EEPROM, nato pa programski spomin; v nasprotnem lahko posamezni RGB čipi med programiranjem neugodno intenzivno zasvetijo. To ločevanje tabel v EEPROM se mogoče zdi kot nepotrebna komplikacija, vendar obstajata dva dobra razloga zaradi katerih sem se za to odločil:
- na ta način sem uspel zmanjšati program pod 4 kB in ga naredil dostopnega uporabnikom demo verzije Bascom-AVRa;
- uporabnik lahko brez spremembe samega programa in celo brez potrebe z razumevanjem njegovega dela, z “ročnimi intervencijami” v vsebini EEPROMa mikrokontrolerja naredi poljubne spremembe v tabelah in tako eksperimentira s prikazom časa na displeju.
Za “ročne intervencije” je potrebno razumeti način, kako so tabele nameščene v EEPROM. To lahko preučimo s pomočjo prikaza na slikah 51 in 52.
Slika 51 prikazuje vsebino tabel s podatki za prikaz na malem prstanu (ure). Vrste označene s “H AM”se nanašajo na dopoldanske (0:00-11:59), vrste označene s “H PM” pa na popoldanske ure (12:00-23:59). “LED1” določa intenziteto posamezne barve prvega, “LED2” pa drugega iz para RGB čipov, ki prikazujeta trenuten čas. Stolpci določajo intenziteto in barvo RGB čipov odvisno od trenutnih minut: prvi stolpec velja, kadar so minute = 0, drugi za minute v razponu 1-5 itd. S slike 51 beremo naslednje:
- v dopoldanskih urah bo prikaz na displeju rdeče barve;
- v popoldanskih urah bo prikaz modre barve;
- vsakih 5 minut se intenziteta svetilnosti prvega RGB čipa zmanjšuje, drugega pa povečuje (v delu tabele v katerem sta v dve sosednji lokaciji vpisane iste vrednosti, se spremembe intenzivnosti dogajajo vsakih 10 minut).
Tabele s podatki za prikaz na velikem prstanu (minute) so prikazane na sliki 52. Minute se prikazujejo v skupinah po tri RGB čipe, zato imamo vrstice “LED1”, “LED2″ in LED3”. Vrednosti v prvem stolpcu vsake barve ustrezajo ničti, peti, deseti, … minuti. Vrednosti v drugem stolpcu vsake barve ustrezajo prvi, šesti, enajsti, … minuti. Ista logika velja tudi za ostale tri stolpce: podatki v vsakem od njih se vključujejo minute kasneje. Na sliki 52 lahko spremljamo, kako se znotraj obdobja 5 minut intenziteta postopno premakne iz prvega preko drugega na tretji RGB čip, in to v rdečem področju v dopoldanskem, v modrem področju pa v popoldanskih urah.
Ko smo prvič programirali mikrokontroler, lahko v tabelah “ročno” spreminjamo posamezne vrednosti, jih vpišemo v EEPROM in spremljamo učinke na displeju. Npr., v področju dopoldanskega časa lahko prekopiramo vrednosti iz rdečih polj v zelena in bo dopoldanski prikaz rumene barve. Prav tako lahko spremenimo številčne vrednosti v posameznih poljih: če vpišemo večje številke, bo prikaz svetlejši. Tukaj lahko ugotovimo, da so v originalnem programu uporabljene intenzivnosti do 16 (=&H10), čeprav je maksimalna intenziteta vsake barve za RGB čip WS2812B znatno večja, 255 (=&HFF). Razlog za tako majhne intenzitete leži v dejstvu, da LED prstani niso veliki: premer večjega je okoli 6,5 cm, optimalna oddaljenost za gledanje ur pa znaša 0,5 – 1 m. Na takšni oddaljenosti večja intenziteta postane neugodna za gledanje.
Zaključne pripombe
Program ne izkorišča vseh možnosti, ki jih nudi DS3231 RTC. Npr., ne uporabljajo se alarmi, za kar je potrebno preverjati SQW priključek ZS-042 modula – zato je ta povezava predvidena na shemi z namenom neke bodoče nadgradnje.
Kondenzator vrednosti 1000 µF je nujen samo takrat, ko se na displeju uporabljajo velike intenzitete. Pri intenzitetah kakršne smo uporabljali mi, je poraba LED prstana komaj nekaj mA, in takrat lahko uporabimo kondenzator z manjšo kapaciteto. Če uporabljamo Arduino Nano ali podoben modul, lahko kondenzator popolnoma izpustimo: v večini primerov bo dovolj tisti, ki je že vgrajen v njegov stabilizator.
Da bi lahko vzdrževal časovno funkcijo tudi med obdobjem, v katerem je napetost napajanja izključena, integrirano vezje DS3231 zahteva backup napajanje. Za ta namen je na ZS-042 modulu predvideno ležišče za litijevo baterijo tipa 2032. Projektant modula je predvidel, da se uporablja akumulatorska baterija oznake LIR2032. Če želite uporabiti standardno ne-polnjivo baterijo (najbolj pogosta oznaka CR2032), je potrebno odstraniti diodo ali upor, ki sta na sliki 53 označena s puščico, ali pač prerezati linijo označeno s križcem. Več o tem in o samem modulu in knjižnici DS3231$SE.sub poiščite v člankih Barduino (1) in (2), objavljenih v Svetu elektronike št. 255 in 256. Prav tako, več o LED prstanih in njihovih knjižnicah lahko najdete v člankih Barduino (5) in (6), objavljenim v Svetu elektronike 259 in 260.
Program analogna ura z LED prstani, Ring_ura_SE.bas, je napisan za mikrokontroler ATmega328P iz Arduino Nano modula, ki dela na frekvenci 16 MHz. Program bo dobro delal tudi z drugimi mikrokontrolerji, ki imajo najmanj 4 kB programskega spomina in po 512 B ali več SDRAMa in EEPROMa. Med ostalimi, so ustrezni ATmega88 – ATmega328 in tudi mali ATtiny85. Fotografija na sliki 54 dokazuje, da izvedba z ATtiny85 mikrokontrolerjem dejansko dela. V programu je bilo nujno spremeniti samo dva konfiguracijska ukaza:
$crystal = 8000000 $regfile = "attiny85.dat"
Opomba: program Ring_ura_SE.bas, kot tudi knjižnice DS3231$SE.sub in WS2812B$SE.sub, ki jih uporablja program lahko brezplačno dobite v uredništvu revije Svet elektronike. Barduino-13