LEDCtrl – tai stipriai „perprojektuotas” (angl. overengineered) LED juostos valdiklis, aprūpintas PIR ir LDR jutikliais, 2×8 LCD ir rotoriniu enkoderiu, skirtas valdyti palėpės laiptų apšvietimą. Idėja susikonstruoti šį daiktą kilo gan seniai, po to kai naktį dėdė sugebėjo nusiristi nuo palėpės laiptų, nes tiesiog pamiršo, kad palėpės laiptai yra gan statūs (beveik kaip kopėčios). Norėdamas apsaugoti save ir artimuosius nuo panašių nutikimų, nusprendžiau palėpės laiptų angą apšviesti pigia LED juosta, maitinama iš 12V maitblokio. Sprendimas buvo vykęs, tačiau naktį erzino gan ryškus parazitinis palėpės kambario apšvietimas, trukdantis miegoti. Bandžiau problemą spręsti po ranka pasitaikiusiu LM317. Viskas buvo kaip ir gerai, tačiau norėjosi kažkokio mandresnio, ne taip kaistančio, sprendimo, leidžiančio dinamiškai keisti LED juostos šviesos stiprį. Taip pat norėjau kažkokio interaktyvumo. Taip ir kilo idėja susikonstruoti valdiklį, kuris LED juostą įjungtų (ar sustiprintų LED šviesos srautą) tik tada kai to reikia, t. y. tik tada kai kas nors lipa laiptais ar eina jų link.
Schema ir PCB
Schema idiotiškai paprasta. Atmega8 su standartiniu apkabinimu. 2×8 LCD, kurio kontrastas sureguliuotas 100R ir 10K varžiniu dalikliu, o pašvietimas valdomas lauktranziu Q2 (gal tik reikėjo pašvietimo grandinėje nuosekliai kokį srovę ribojantį rezistorių įmontuoti). Kadangi valdiklis yra pritaikytas IPM (angl. PWM) valdyti standartines kiniškas 12V LED juostas, todėl schemoje yra ir 7805 reguliatorisu su atitinkamu apkabinimu.
Vartotojo sąsaja realizuota rotoriniu enkoderiu su mygtuku, pirktu iš ebay. Enkoderį pasirinkau grynai iš smalsumo, nes buvo baisiai įdomu su juo pasižaisti. Be to buvo labai nusibodę paprasti mygtukai.
Schemoje įprojektuoti 3 šviesos diodai LED1–LED3 skirti „debuginimui”, kurie baigtame projekte tiesiog gražiai mirksi ir jokios naudos neduoda. Taip pat nepamiršau į schemoje įdėti ir AVR ISP bei USART jungčių. Pastaroji irgi labiau skirta „debuginimui”, nes visa naudotojo sąsaja yra realizuota per LCD ekranėlį ir rotorinį enkoderį.
Kadangi pigios kiniškos LED juostos (pirkau į ebay) dažniausiai būna su integruotais srovę ribojančiais rezistoriais, valdiklis juostą valdo paprasčiausiu IPM (angl. PWM) per lauko tranzistorių Q1.
Aplinkos apšviestumo lygis fiksuojamas paprasčiausiu LDR – 12K-100K fotorezistoriumi. Iš jo ir rezistoriaus R12 yra sudarytas varžinis daliklis, kurio išėjimas patenka tiesiai į atmegos ADC.
Judesius fiksuoja ultra pigus PIR modulis iš ebay. Apie panašius PIR modulius galit pasiskaityti Adafruit Learn sistemoje. Linkas iš ties pravartus, nes ten yra aprašyti skirtingi PIR veikimo režimai ir būdai pakeisti PIR išėjimo signalo parametrus. Verta iš kart įspėti, net potenciometru „Time” nureguliavus PIR signalo periodo trukmę iki minimumo, ji vis tiek yra labai ilga. Gal kokiai signalizacijai tai ir gerai, bet ne mano atveju. Man norėjosi trumpų PIR signalo periodų, todėl PIR modulio išėjimą prie INT0 prijungiau per RC high pass filtrą su maždaug 2 ms laiko konstanta. Kad įrašas atrodytų rimčiau, štai jums PIR signalo prieš filtą (geltona kreivė) ir po filtro (žalia kreivė) oscilograma:
PCB projektavau neturėdamas omenyje jokio konkretaus korpuso (žioplas sprendimas), todėl stengiausi ją padaryti kuo mažesnę, visas jungtis išvesti į vieną kraštą, palikti pakankamai vietos rotorinio enkoderio rankenėlei. Tiesa pasakius, pirminiame variante buvau privėlęs žioplų klaidų (sumaišiau LCD maitinimo VEE ir VDD išvadus, nepalikau pakankamai vietos tarp 12V maitinimo jungčių, kiek per vėlai sugalvojau PIR prijungti per RC filtrą ir pan.), tačiau prie projekto prisegtame archyve šios klaidos yra ištaisytos.
Tiesa, verta paminėti, kad schemoje nėra apsaugos nuo atvirkštinio maitinimo prijungimo (angl. reverse poliarity protection), srovės ribojimo ir apsaugos nuo trumpo jungimo grandžių. Šį „kliurką” pastebėjau, tik montuodamas valdiklį į korpusą. Jei ketinat darytis šio valdiklio kopiją, būtinai pagalvokit apie minėtas apsaugas.
Surinkimas
Kaip ir minėjau, PCB tikrai paprasta, todėl ją sulituoti nebuvo sunku. Gal tik kiek teko pavargi bandant ištaisyti žioplą LCD maitinimo klaidą (laidų raizgalynė PCB dešiniajame kampe). Svarbiausia, kad viskas veikė. Ne iš pirmo karto, bet veikė.
Visas smagumas prasidėjo, kai pagaliau prisiruošiau sumontuoti valdiklį į plastikinę dėžutę / korpusą. Norėjau, kad daugiau nebereikėtų niekada lįsti į valdiklio vidų, todėl nusprendžiau išvesti AVR ISP ir USART jungtis į lauką. Tam tiesiai prie PCB prilitavau IDC tipo kabelį su DB9 jungtimi. Aišku, nei vienam nei kitam IDC kabelio galui nepagailėjau karštų klijų. 😀 Taip pat nusprendžiau tiesiai prie PCB prilituoti ir PIR jutiklio išvadus, todėl laidų gavosi neplanuotai daug..
Nusprendžiau PCB korpuso viduje tvirtinti 3 mm varžais, o tarp korpuso ir PCB sudėti 8 mm plastikines tarpines (tie juodi vamzdeliai nuotraukoje apačioje). Juos sukišti į savo vietas buvo gan keblu, bet su stomatologo įrankiais tai pavyko atlikti gan greitai. 🙂 Taip pat montuojant šiek tiek kreivokai išgręžiau varžtų tvirtinimo skyles, todėl jas pridengiau raudono kartono poveržlėmis.
Nors viduje gavosi tikra laidų raizgalynė, iš išorės valdiklis gavosi gan gražus. Kaip rusai sako: „сойдёт для сельской местности!”.
Softas
Va čia tai sudėtingiausiai projekto dalis, todėl kad valdiklio programoje yra realizuoti 4 darbo režimai ir 3 lygių naudotojo meniu. Praktiškai visi valdiklio nustatymai yra keičiami per naudotojo meniu, todėl programos kodas gavosi tikrai sudėtingas ir ilgas. Prie to dar prisidėjo tai, kad programą rašiau praktiškai metus su nereguliariomis pertraukomis, iš kurių ilgiausia buvo beveik 6 mėn. Programuojantys puikai žino, kad net padarius kelių dienų pertrauką būna sunku vėl „įsijaust į kodą”, o dar po ilgesnės pertraukos iš vis pasidaro sunku galus sugaudyti. Kodo tvarkingumui tikrai nepadėjo ir tai, kad ūpui pakelti dažnai nevengiau buteliuko alaus ar viskio šlakelio. 😀 Na bet yra kaip yra. Gal vienas kitas bugas ir liko, bet daiktas veikia, atlieka savo funkcijas ir nelūžta.
Pačio kodo komentuoti neketinu, nes nieko ten nėra ypatingo. Tiesiog ilga switch–case if– else if–else spageti makalynė su šiokiais tokiais komentarais ir viskas. Kam reikės, tas jau (tikriausiai tik aš pats kada nors ateityje) atsirinks. Gal tik verta paminėti kelis atmega8 hardware išnaudojimo sprendimus:
- INT0 – Pertrauktis apdoroja PIR jutiklį.
- INT1 – Pertrauktis skirta darbui su rotoriniu enkoderiu. Naudojama vaikščiojimui per naudotojo meniu bei parametrų verčių keitimui tiek confige tiek ir esant tam tikriems darbo režimams.
- TIMER0 – TIMER0_OVF_vect pertrauktis atlieka ADC matavimus, kur reikia sušeria gautas reikšmes ir kai kuriuose darbo režimuose atnaujina LCD rodomą informaciją. Kodėl nepanaudojau ADC pertraukties? Nežinau. T. y. nebeatsimenu, nes ADC nuskaitymą užkūriau vieną ir pirmųjų 😀 Rodos dėl to, kad ADC pertrauktis stabdė kitų procesų darbą.
- TIMER1 – TIMER1_COMPA_vect pertrauktis naudojama kaip laikrodis, skaičiuojantis sekundėmis. Pastarosios naudojamos atgaliniam skaičiavimui tarp darbo režimų persijungimo ir LCD pašvietimo trumpam įjungimui.
- TIMER2 – Laikmatis naudojamas tik impulso pločio moduliacijai (angl. PWM).
- USART – Sukonfigūruota ant 9600 Boud, 8 bitų su 1 Stop bitu. Skirta grynai debuginimui.
- EEPROM – visi konfigūraciniai parametrai, prieinami naudotojui per meniu, yra saugomi EEPROM’e. Tam, kad pirmą kartą užprogramuotas valdiklis nepradėtų grybauti, kode yra aprašyta funkcija first_time_boot(), kuri valdikliui startavus pirmą kartą į EEPROM surašo pagrindinių parametrų vertes.
Beje, visą valdiklio projektą, kartu su programos kodu, galite rasti straipsnio apačioje, atsisiuntimuose. 😉
Darbo režimai
Kaip minėjau, valdiklyje yra realizuoti 4 darbo režimai. Trumpai apie juos:
- ON/OFF – LED juosta arba visiškai išjungta, arba nuolat šviečia pasirinktu stiprumu. Šviesos intensyvumas reguliuojamas darbo metu rotoriniu enkroderiu ir nustatyta vertė iškart išsaugoma EEPROM’e.
- PIR/LDR – Valdiklis nuolat tikriną ar kambario apšviestumas nenukrito žemiau nustatytos vertės (parametras LDRth). Užfiksavus, kad kambario apšviestumas yra nebepakankamas, yra įjungiama PIR pertrauktis. Suveikus PIR jutikliui, valdiklis švelniai sustiprina LED šviesos intensyvumą nuo naudotojo nustatytos reikšmės PWMmin iki PWMmax (žr. poskyrį „Naudotojo meniu„). Tai atlikęs mikrovaldiklis laukia nustatytą laiko intervalą TimeOut ir LED juostos šviesos stiprį švelniai sumažina nuo PWMmax iki PWMmin.
Atgalinio TimeOut skaičiavimo metu PIR pertrauktis gali suveikti iš naujo tik jeigu LDR jutiklio rodmenys nepakilo aukščiau nuostato LDRth. Tada laikas pradedamas skaičiuoti iš naujo. Jei LDR jutiklio rodmenys staiga pakilo aukščiau nuostato LDRth, pav. užlipom laiptais ir įjungėm kambario apšvietimą, PIR pertrauktis yra išjungiama ir PIR signalas yra tiesiog ignoruojamas. - PIR – Veikimo principas yra analogiškas „PIR/LDR” darbo režimui, tik čia nėra atsižvelgiama į fotorezistoriaus rodmenis. T. y. tiesiog, pirmą kartą PIR užfiksavus judesį, valdiklis velniai sustiprina LED šviesos intensyvumą nuo naudotojo nustatytos reikšmės PWMmin iki PWMmax (kai tai veikia galite pamatyti skirsnyje „Rezultatai”). Tai atlikęs mikrovaldiklis laukia nustatytą laiko intervalą TimeOut ir LED juostos šviesos stiprį švelniai sumažina nuo PWMmax iki PWMmin. Atgalinio TimeOut skaičiavimo metu PIR pertrauktis gali suveikti iš naujo. Tada laikas pradedamas skaičiuoti iš naujo.
- LDR – Tai savotiškas PI tipo LED juostos šviesos stiprio reguliatorius. Šiame darbo režime fotorezitoriaus vertė yra matuojama 8 kartus ir išvedamas vidurkis (I reguliatoriaus grandis). Po to ši vertė proporcingai (P reguliatoriaus grandis) yra perskaičiuojama ir „sušeriama” į OCR2 registrą. Reguliatoriaus proporcinis koeficientas yra reguliuojamas tiesiai iš naudotojo meniu, darbo režimo metu (žr. poskyrį „Naudotojo meniu„).
Iš principo yra galimi du skirtingi šiuo darbo režimo variantai: „atvirkštinis” ir „tiesioginis” LED juostos šviesos stiprio reguliavimas. „Atvirkštinis” reguliavimas LED juostos šviesos intensyvumą mažina vis labiau, kuo patalpa yra labiau apšviesta. „Tiesioginis” reguliavimas – LED juostos šviesos intensyvumą didina vis labiau, kuo patalpa yra labiau apšviesta. Kokiu režimu reguliatorius veikia yra nustatome konfigūracijos meniu punkte LDRinv (žr. poskyrį „Naudotojo meniu”).
Naudotojo meniu
Vat ant tiek naudotojo sąsaja yra komplikuota. 😀 Taip, ant tiek komplikuota, kad nenufotografavęs beveik kiekvieno LCD rodomo puslapio (pamiršau vieną 🙁 ) ir „nesuphotoshopinęs” visko į vieną paveikslą, net nesugebėčiau nieko paaiškinti. Na tai pradedam…
Statusas
Tai LCD puslapiai, kurie yra rodomi esant konkrečiam darbo režimui. T. y. kai jau iš pirmo nustatymo meniu lygio buvo išsirinktas konkretus darbo režimas. Kiekvienas darbo režimo statuso puslapis yra šiek tiek skirtingas.
- ON/OFF režimo metu yra indikuojama, kad LED juosta yra išjungta („OFF”) arba, kokiu ryškumu (procentais) ji šviečia.
- Esant PIR darbo režimui, LCD ekrane atvaizduojamas TimeOut laikas.
- PIR/LDR režimo metu – pirmiausia, kol fotorezitoriaus rodmenys (nuotraukoje „R55”, kur 55 – tai esame LDR reikšmė procentais), nenukrito žemiau LDRth nuostato (nuotraukoje „T20”, kur 20 – nuostato vertė), rodomas vienas puslapis. Kai fotorezitoriaus rodmenys nukrenta žemiau LDRth nuostato yra persijungiama į PIR darbo režimo puslapį.
- LDR darbo režimo metu, pirmoje LCD eilutėje yra rodoma reali LDR reikšmė procentais. Antroje LCD eilutėje yra rodomas PI reguliatoriaus proporcinis koeficientas (nuotraukoje „K”), šalia jo, tai kas patenka į OCR2 registrą procentais, to reikia, kad būtų galima stebėti koeficiento „K” įtaką PI reguliatoriaus darbui.
1-as meniu lygis
Esant bet kokiam darbo režimui, du kartus paspaudus rotorinio enkoderio mygtuką, naudotojas yra permetamas į nustatymų meniu. Tiksliau, į pirmąjį jo lygį, kuriame galima pasirinkti pageidaujamą darbo režimą, pereiti į konfigūracijos meniu „Config” arba sugrįžti į darbo statuso langą (t. y. išeiti iš meniu).
Pasirinkus vieną iš darbo režimų, yra papildomai paklausiame, ar tikrai norimą jį įjungti. Jei pasirenkama reikšmė „ON”, darbo režimas yra tuoj pat įjungimas, o vartotojas yra nuvedamas į darbo režimo statuso langą. Jei pasirenkama „OFF” – naudotojas yra gražinamas į pirmąjį menių lygį.
Pasirinkus menių punktą „CONFIG” yra pereinama į konfigūracinį menių.
2-as meniu lygis
Čia yra keičiami valdiklio nustatymai, apie kuriuos šiek tiek užsiminiau skirsnyje „Darbo režimai”. Funkcija „EXIT” naudotoją gražina į prieš tai buvusį meniu lygį, o pasirinkus vieną iš keistinų parametrų yra pereinama į 3-iąjį meniu.
3-čiasis meniu lygis
- MinPWM – procentais keičiamas minimalus LED juostos šviesos stipris. Realybėje 0% atitinka OCR2=0x00, o 100$ – OCR2=0x255. Arba, dar paprasčiau: 0% – 0V, 100% – 12V.
- MaxPWM – analogiškai procentais keičiamas ir maksimalus LED juostos šviesos stiprio nustatymas.
- TimeOut – laiko intervalas sekundėmis, kurį mikrovaldiklis PIR ir PIR/LDR darbo režimuose laukia prieš sumažindamas LED juostos šviesos stiprį nuo PWMmax iki PWMmin.
- LDRth – keičiamas minimalus kambario apšviestumo lygis, prie kurio PIR/LDR darbo režimas turėtų įjungti PIR pertrauktį. LCD puslapyje yra rodomas tiek realus, iš LDR gaunamas, apšviestumo lygis procentais (nuotraukoje „R56”), tiek ir nustatomo LDRth parametro vertė (nuotraukoje „T20”) procentais.
- LDRinv – Galimybė „invertuoti” analoginio skaitmeniniu keitiklio (realiai LDR jutiklio) rodmenis. Kai LDRinv=0, duomenys nėra invertuojami. LDRinv=1 – invertuoja duomenis. Tiek realūs R, tiek invertuoti duomenys I yra vienu metu atvaizduojami šiame LCD puslapyje.
- ADCgain – analoginio skaitmeninio keitiklio stiprinimo koeficiento nustatymo langas.
Rezultatai
Štai taip atrodo mano palėpes laiptų apšvietimas. Kairėje nuotraukoje LED juosta šviečia silpniausiu pajėgumu, dešinėje – didžiausiu.
O čia keli filmukai, kai veikia valdiklis. Filmavimo metu buvo įjungtas darbo režimas „PIR/LDR”.
Atsisiutimai
Valdiklio schemą, PCB ir programinę įrangą rasite čia: LEDCtrl