Mikrokontrolleri sisendid-väljundid

Üks teoreetilisemat laadi postitus vahelduseks. Räägime mikrokontrolleritest. Mitte niivõrd sellest, mis need on või mis nende sees on, vaid sellest, kuidas need asjad maailmaga suhtlevad.

Ei ole võimalik tegutseda elektroonikuna ilma, et mikrokontrolleritega kokku ei puutuks. Need on populaarsed oma küllalt madala hinna ja suure paindlikkuse tõttu. Näiteks on võimalik terve Aprill 2018 kirjeldatud PWM generaator lahendada ühe mikrokontrolleriga, mis maksab alla 0.5€, mahub palju väiksemale pindalale ning on paindlikum. Näide paindlikusest on näiteks PWM-i sagedus. Kui analoogskeemi sagedust muuta tahad tuleb teha muudatusi riistvaras. Mikroarvutit kasutades piisab aga tarkvara uuendusest. Samuti, kui soovid panna oma PWMi täiteteguri sõltuma veel näiteks temperatuurist, siis mikrokontrolleriga lahendus on peale vaadates lihtne ja arusaadav. Analooglahendus aga pigem keeruline ja nõuab arusaamiseks mõningast vilumust.

Mikroarvutiga töötamise puuduseks on muidugi vajadus programmeerimist osata. Kui programmeerida ei taha, tuleb leida kambajõmm kes tahab. Professionaalses elus tuleb väga harva ette, et keegi teeb mõlemat. Need võivad olla üksiküritajad või väga väikesed meeskonnad. Startupid või ülikooli töötajad. Enamasti aga jaotatakse elektroonika disaini ja programmi kirjutamise ülesanded erinevate inimeste vahel. Seda seetõttu, et mõlemad distsipliinid on sedavõrd keerulised, et ühel inimesel on raske omada kõrget oskuste taset mõlemas. Samuti, kui kõike teeb üks inimene, läheb kauem aega kui tööd jagades.

Siit paistab ka tegelikult koht miks tuleks mikroarvutite kohta õppida. Lisaks sellele, et sul on tarvis mikroarvutite sisenditele-väljunditele riistvara disainida, tuleb sul aru saada, kuidas sinu ja programeerijate maailmad kokku puutuvad. Mikroarvuti sisendid-väljundid ongi see kokkupuute punkt.

Kui aga kohe alguses hobi projekti jaoks programmeerijat võtta ei ole, siis ära heida meelt. Maailmas on ports üsna komplektseid mikrokontrolleri arendamise plaate, mille programmeerimine on tehtud lihtsaks. Kõige populaarsem on Arduino platform. See on küllalt odav ja terve internet on täis näidiseid, kus seda kasutama õpetatakse. Programmeerimine sellele on imelihtne, sest loojad on sind säästnud keerulise arenduskeskkonna üles seadmisest ja kasutama õppimisest.

Niipalju siis sissejuhatuseks. Ma võtan näidis materjaliks maailma populaarseima Arduino, Arduino UNO, ning käin selle sisendid-väljundid ükshaaval üle.

Digitaalne sisend/väljund

Räägime väljundist kõigepealt. Mäletad H-silda? Kasutasid H-silla juhtimiseks nuppe? See on ideaalne funktsioon, mida mikroarvuti täita võiks. Selle asemel, et nupu abil H-silla sisendile kõrge pingenivoo anda, võib selle sisendi anda digitaalne väljund, mis programmeeritakse õigel momendil välja andma kõrge(või madala) signaali. Kõrge pingenivoo on tavaliselt 3,3V või 5V. Meie Arduino Unol on selleks tinglikult 5V. Madalaks pingenivooks on 0V.

Ma ütlen tinglikult, sest reaalsus ei ole päris nii selge ja sirgjooneline. Tegemist on siiski füüsiliste seadmetega, mis on mõjutatud keskkonnast, ennekõike temperatuurist. Samuti on tegemist masstoodetud seadmetega ning vähesed neist on ideaalsed. Ehk siis disaini luues tuleb tutvuda vastava mikroarvuti andmelehega ning täpsed nivood üle vaadata. Kõne all oleva Arduino UNO protsessori ATmega328P andmelehest leiab alloleva info.

Siit on näha, et kõrgematel temperatuuridel ja 5V toitepinge korral võib juhtuda, et kõrge pingenivoo on ainult 4V ja madal pingenivoo lausa 0,9V. See tähendaks praktikas, et kui sa tahad kõrge nivooga otse väljundi külge ühendatud LED-i põlema panna, siis kõrgematel temperatuuridel võib LED tuhmim olla. Teistpidi näiteks, kui otse väljundi külge bipolaartransistori baasi ühendad võib juhtuda, et seda transistori ei ole võimalik välja lülitada.

Töökindel ja stabiilne disain peab nende piirangutega arvestama.

Samasugused mured piiravad meid sisendite korral. Sisendid võtavad väljastpoolt mikrokontrollerit olevast maailmast signaali ja muudavad selle sisendiks mikrokontrolleris olevale programmile. Digitaalse sisendi puhul on selleks taas mingi loogikanivoo. Niiöelda kõrge või madal, üks või null. Mingit vahepealset võimalust ei ole. Selle signaali võib anda näiteks nupp või lüliti. Samuti võib see tulla mõne sensori või anduri väljundist.

Ka sisendi kohta on andmelehel tabel.

Seda tasub lugeda nii, et meie Arduino loeb sisendi kindla peale kõrgeks, kui sisendi pinge on kõrgem kui 70% toitepingest ehk 3,5V. Madal on garanteeritud, kui pinge on alla 30% toitepingest ehk 1,5V. Reaalsuses aga toimub üleminek ühest olekust teise kusagil 1,5V ja 3,5V vahel, kusjuures täpne pinge võib sõltuda sellest, kas sa lähed kõrgest madalaks või madalast kõrgeks. Digitaalne sisend on nimelt varustatud hüstereesiga (vt artiklit jaanuarist 2018).

Praktiline järeldus siit on see: Kui tahad, et mikroarvuti sinu sisendit kindla peale loeks just selliseks nagu sina soovid, hoia kindlasti pingenivoodel silma peal.

Räägin ka pull-up takistist. Eesti keeles oleks õige mõiste koormustakisti (L.Abo. Raadiolülitused). Alloleval pildil on näide digitaalsest väljundist.

Selleks, et siit saada kõrge nivoo, tuleb siia ka positiivne pinge külge saada. Selle jaoks kasutamegi koormustakistit.

Tänapäevastel mikroarvutitel on koormustakistid tavaliselt seadme sees ning neid saab vastavalt vajadusele sisse välja lülitada. Nii ka Arduino Uno-l oleva ATmega mikroarvuti puhul. Küll aga võid väga madala võimsustarbe saavutamiseks tahta ikkagi väliseid takisteid kasutada. Eriti kui saad teha järeleandmiseid lülituskiiruses. Kõnealuse mikroarvuti sisemised koormustakistid on takistusega 20- 50 kΩ. See võib olla vastuvõetamatult väike mõnes ülimadala energia tagavaraga rakenduses.

 

Üks aspekt on veel. Selleks on vool. Iga mikroarvuti sisend(väljund) suudab välja anda (neelata) mingisuguse piiratud koguse voolu. Arduino UNO-l on selleks 40mA sisendi/väljundi kohta. Lisaks sellele on piiratud toitesisendite, VCC ja GND, vool. Selleks voolu piiranguks on 100mA väljaviigu kohta. Ehk siis kuigi sul on 27 digitaalset sisendit/väljundit ei tohi nende voolude summa ületada 100mA.

Analoog Digitaal Muundur

See on juhuks, kui mikroarvuti mingit pinget teadma peab. Näiteks, kui tahame mõõta temperatuuri kasutades selleks Jaanuar 2018 artiklis demonstreeritud termotakistiga pingejagurit. Muundur muudab sisendi pinge mingisuguseks digitaalseks numbriks.

AD muundur jaotab toitepinge väikesteks pinge vahemikeks, millest igaühele vastab üks digitaalne number. Vahemike suurus sõltub muunduri bittide arvust. Tinglikult võiks öelda, et ka digitaalne sisend on ühe bittine AD muundur. Bitt on arvuti matemaatika vähim ühik. See saab olla vaid kaks väärtust. Erinevalt meie tavalisest kümnendsüsteemi numbrist, kus igal numbri positsioonil saab olla 10 erinevat väärtust. Kui pinge on alla mingi halvasti defineeritud läve on bitt 0 ja kui pinge on üle selle läve on bitt 1. Meie Unol on kümne bitine analoog digitaal muundur.

See järgmine osa on äkki veidi keeruline, kui sa varem arvutitehnikaga kokku ei ole trehvanud. Igaks juhuks selgitan.

Kui sul on üks bitt, saab sellel olla kaks väärtust: 0 ja 1.

Kui sul on kaks bitti, saab neil kahe peale kombinatsioonina olla 4 erinevat väärtust: 00, 01, 10 ja 11.

Kui sul on kolm bitti, saab neil olla kolme peale kokku 8 erinevat väärtust. 000, 001, 010, 011, 100, 101, 110 ja 111.

Ehk siis kehtib seaduspära, kui sul on x arv bitte, siis nende bittidega saab moodustada 2 astmes x kombinatsiooni. Seega 10 bittise AD muunduriga saab toitepinge vahemiku jagada 2 astmes 10 erinevaks pingevahemikuks. 2 astmes 10 on 1024. Kui tahame teada, mis ühe pingevahemiku suurus on, siis jagame toitepinge 1024-ga.

Kui AD muunduri sisendile rakendada toitepinge, ütleb muundur programmile numbri 1024. Kui AD muunduri sisendil on 0V, ütleb muundur programmile numbri 0. Kui aga muunduril on näiteks pinge 2,2V ütleb muundur

Miks see elektroonikut huvitab?

Üldiselt on nii, et programmi kirjutaja ei topi oma nina asjadesse, mis toimuvad väljaspool mikroarvutit. Seega tuleb elektroonikul tekitada valemid, mis aitavad muundurist tulevad numbrid muuta mingiks arusaadavaks väärtuseks.

Oletame näiteks, et meid huvitab Arduino toitepinge väärtus. Vastavalt Uno andmelehele võib see pinge olla vahemikus 6 kuni 20V (Arduino plaadil olev pingeregulaator teeb sellest mikroarvutile vajaliku 5V). Meil on seda pinge väärtus millegi jaoks vaja teada. Selle pinge mõõtmiseks kasutame me pingejagurit, mis jagab toitepinge neljaks.

Selleks, et programm (programmeerija) teaks mis see pinge täpselt on tuleb kokku panna valem. Antud juhul on see üsna sirgjooneline:

  1. Arvuta AD muundurist tuleva numbri põhjal pinge AD sisendil
  2. Tee pöördtehe, et saada kätte see pinge, mis sind päriselt huvitab.

Antud juhul näeks terviklik valem välja selline.

Kaks olulist ja omavahel seotud AD muunduri täpsust mõjutavat parameetrit on pingeallika impedants ja muunduri võendamissagedus. Kahjuks on nii, et AD muunduse protsess ei toimu momentaalselt. See võtab veidi aega. Kui palju see aega võtab sõltub veidi sellest kuidas ADC ehitatud on. Neid variante on mitu ning ma ei hakka laia valikut tutvustama. Arduino mikrokontrolleris näeb sisemine skeem välja selline:

Vooluallikad, mis skeemi vasakus servas näidatud, tähistavad lekkevoolu ning neid me praegu ei arvesta. Mis siit aga silma jääb on madalpääsfilter. AD muundur vaatab pinget kondensaatoril ning kondensaatorit laetakse läbi takisti. Kondensaatori laadimine võtab mõnevõrra aega. Kui palju aega sõltub sellest, kui täpset lugemit sa vajad ja millist resolutsiooni sa kasutad.

Kasutades maksimaalset resolutsiooni saad sa võendada 15kSPS. kSPS on lühend inglisekeelsest kilo Samples per Second ning annab teada, et võendamissagedus on 15 000 võendamist sekundis. See aga ei ole päris kogu tõde. Nimelt on Arduino Uno mikroarvutil 6 AD kanalit, mis jagavad ühte AD muundurit. Seega tuleb maksimaalne võendamissagedus kanalite vahel ära jagada.

Mis on aga vajalik võendamissagedus? Sõltub rakendusest. Toa temperatuuri mõõdad võibolla ühe korra minutis. Välistemperatuuri ühe korra tunnis. Mootorit läbivat elektrivoolu tahad võibolla mõõta ühe korra millisekundis. Küll aga tuleb iga sisendi puhul korraldada asjad nii, et signaalid mille sagedus on suurem, kui pool võendamissagedusest ei pääse muunduri sisendisse. See reegel tuleb Nyquist–Shannoni teoreemist, mis ütleb, et pidevat signaali on võimalik rekonstrueerida, kui sul on iga signaali perioodi kohta kaks võendust. Praktikas tähendab see seda, et AD sisendi ette tuleb panna madalpääsfilter. Täitsa tavalises rakenduses, kus mõõdad kord millisekundis elektrivoolu või kord minutis temperatuuri, võid vabalt filtri murdesageduseks võtta pool AD muunduri võendamissagedusest.

Võendamine või nagu eestikeelne wiki koledasti pakub “Sämplimine” on asi mis läheb väga kiiresti väga keeruliseks, kui üritad selle tehnoloogia matemaatilisest taustast aru saada. Loe kindlasti juurde Wikist. Samas ei tasu karta, sest üldiselt saab ka ilma matemaatikata rakendused tööle.

Pulsilaiusmodulatsioon

Kui sul on tarvis pulsilaiusmodulatsiooni (PWM) tuleb programeerijatele öelda mis on vajaminev sagedus. Üsna paljud rakendused, servomootorid näiteks, seavad üsna kindlad piirangud PWM-i sagedusele. Kui rakendus selgeid piire ei sea, tuleb see sul endal välja mõelda. Kui sa tüürid valgusdioode või mootorit ei pruugi sul väga suurt sagedust vaja olla. Pigem on isegi tark hoida madalamat sagedust, et vähendada müra seadmete toite ahelates. Kui sa kasutad PWM-i aga mingi pingenivoo tekitamiseks, tahad sa just pigem kõrgemat sagedust. See muudab moduleeritud pinge silumise oluliselt lihtsamaks.

Kui see, mida PWM välja annab sõltub mõnest sinu antud sisendist, tuleb sul edasi anda, kuidas see sõltuvus matemaatiliselt välja näeb. Või kas täiteteguril on mingisugune miinimum-maksimum? Näiteks tahame, et dioodid mida tüürime PWM-iga transistori toel ning mis saavad toidet Arduinot toitvast adapterist, põleksid ühesuguse heledusega sõltumata sellest mis on toitepinge. Ehk siis kasutaksime AD muundurist saadud väärtusi täiteteguri määramiseks selliselt. Mida suurem sisendpinge, seda madalam täitetegur.

PWM-i tehakse mikroarvuti sees üllatavalt sarnasel moel sellele, kuidas tegime PWM-i analoogis. Me tekitame stabiilse tõusu ning lülitame väljundit mingil kindlal väärtusel selle tõusu peal. Lihtsalt mikroarvutis on selleks tõusuks kindla perioodiga kasvav number vastavas registris. Reseti jaoks on teine number mingis teises registris. Ning väljundi ümber lülitamiseks on kolmas number kolmandas registris.

Programmeerija valib kasvava numbri kasvukiiruse. See võib käia sama kiiresti, kui mikroarvuti taktsagedus Võib kasutada taktiks mõnda teist suvalist sisemist või välimist kella ning võib kasutada ka mingeid kordajaid. Kordajate all pean silmas, et kui kell teeb näiteks 8 takti kasvab register ühe arvu võrra. Pannes paika registri kasvukiiruse ja registri väärtuse millal loendur nullida tuleb ongi programmeeria paika pannud PWM-i perioodi ja sageduse.

Teine register millesse kirjutada tuleb, paneb paika millal väljundit lülitatakse. See muutub pidevalt ja sellega pannakse paika täitetegur.

Pane tähele, et valides erinevat kasvukiirust ja loenduri nullimise arvu saad valida, mis on PWM-i resolutsioon. Mis on vähim täiteteguri muutus mida teha saad. On see 1%, 10%, 0,1%.

Üldiselt tasub siin programmeerijaga läbi rääkida. Tasub endale selgeks mõelda, mis on see resolutsioon mida su rakendus vajab. Arvutada täitetegur efektiivseks pingeks ja mõelda kui suur pinge samm vajalik on.

SPI

Serial Peripheral Interface, eesti keeles siis lisaseadmete järjestikliides. Aga ettevaatust selle eestikeelse nimega. See on minu tõlge ja ma ei ole kunagi varem kuulnud, et keegi seda tõlkida üritaks. Sama kehtib tegelikult kõikide järgnevate sisendite-väljundite kohta. Ei tasu loota, et teised insenerid asju eesti keelde tõlgivad. Seetõttu on tark püsida tuntud ja turvalise lühendi, SPI juures.

Igatahes. Tegemist on järjestikliidesega, mis on loodud suhtlemiseks lähedalasuvate, tavaliselt samal trükkplaadil, asuvate lisaseadmetega. Lisaseadmeteks võivad olla välised mälud, sensorid, teised mikroarvutid ja palju muud.

Seletan kiiresti misasi on järjestikliides. See on andmete edastamise viis, kus andmed antakse üle ühte juhet(rada, traati) mööda. Erinevatel ajahetkedel antakse traadile erinev pinge, kas siis kõrge või madal ning vastuvõtja loeb igas ajaühikus juhtme pealt pingenivoo.

Üleval on pilt. mis demonstreerib kaheksa bitti ehk ühe baidi edasiandmist.

Teine variant andmete ülekandmiseks on paralleelliides. Sellise liidese korral on sul kaheksa juhet ning kogu bitt antakse edasi ühe ajaühiku sees.

Siililegi selge, et paralleelliides võimaldab kiiremat andmeedastust. Küll aga nõuab paralleelliides suuremat trükkplaadi pinda ja rohkem komponentide väljaviike. Seega üldiselt võetakse paralleelliides kasutusele alles siis, kui järjestikliides aeglaseks kipub jääma. Levinumad rakendused on personaalarvuti ning igasugune kaamerate ja videotöötlusega seonduv. Samuti radari rakendused paljud sidesüsteemid ja kõik muu säärane, kus töödeldakse ja liigutatakse väga suuri andmehulki lühikese ajaga.

Arduino Uno aga ei ole sellisteks rakendusteks ehitatud ja sellel paralleelliidest ei ole. Lihtsalt märkus: kui sa ikkagi tahad Arduinole paralleelliidest, pead digitaalsed sisendid/väljundid (GPIO-d) programmi abil paralleelliidesena käituma panema. Seda liigutust kutsutakse ingliskeelse sõnaga bitbanging ja sellest me siin rohkem ei räägi.Nüüd. SPI-d iseloomustab see, et sul on üks ülemus (master) ja mitu alluvat (slave). Ülemus ütleb kellega ta rääkida tahab ning annab liidesele ka taktsageduse. All on pilt eestikeelsest SPI-st rääkivast Wikipedia artiklist, mida kindlasti samuti lugeda tasuks.

Näed nelja signaali

MOSI – Master Out Slave In, Ülem Välja Alluv Sisse

MISO- Master In Slave Out, Ülem Sisse Alluv Välja

SCLK- Serial CLocK, Jada Kell

nSS – Slave Select, Alluva Valik (üsna tihti ei õnnestu tekstitöötlusprogrammides tekitada seda kriipsu, mis joonisel SS-i peal on. See kriips tähendab, et see signaal on “madal-aktiivne”. Üks variant selle omaduse tähistamiseks on eesliide n)

SCLK annab kogu süsteemile taktsageduse. Seda tekitab Master ning andmete väljaandmine ja vastuvõtja pool lugemine käib selle taktsageduse alusel. nSS signaal on loodud Slave-i valimiseks. Täht n lühendi eest tähistab, et alluva valimiseks tuleb vastaval juhtmel pinge tõmmata madalale nivoole.

MISO ja MOSI on andmete vahetamiseks. Need kaks ja SCLK võivad olla kõigi ühel siinil olevate seadmete peale ühised. nSS tuleb aga igale alluvale eraldi tekitada.

I2C

I-ruut-c, võiks eesti keelde tõlkida, i-kaks-c on ka arusaadav. Inglise keeles võiks öelda i-square-c. Liidese täisnimi on Inter-Integrated Circuit (integraalskeemide vaheline). Liides leiutati kunagi Philipsi poolt, samuti lühimaa suhtluseks ühe sardsüsteemi raames. All on pilt eestikeelsest wikipediast I2C kohta.

Pane tähele, et sisuliselt on kommunikatsiooniks vaja kahte juhet. Vdd tähistab toitepinget ja sellega antakse märku, et suhtlusliinid vajavad pull-up takisteid.

Kahe ühenduse nimed on SDA ja SCL. Serial Data ja Serial Clock. Ehk siis erinevalt SPI-st liiguvad andmed edasi-tagasi ning info selle kohta, kelle poole Master pöördub kõik ühte juhti mööda. Selle teeb võimalikuks see, et kõigil alluvatel on oma aadress. Positiivne pool on see, et sa pääsesid hulgast trükkplaadi radadest. Halb on aga see, et nüüd pead kasulike andmete kõrval ka aadresse liigutama. See aga teeb andmeedastuskiirust aeglasemaks.

UART

See on ehk kõige baas ja alus. Kõige arhailisem järjestik kommunikatsiooni viis. Lühend tähendab Universal Asynchronous Receiver-Transmitter. See on kahe juhtmega liides (ühine GND peab ka olema) TX ja RX. TX ehk transmit on integraalskeemi väljund. RX ehk receive on selle sisend. Sõna asünkroonne tähistab, et kaks kommunikatsiooni osapoolt ei jaga ühist kellatakti. See on üks asi mille poolest UART teistest käsitletud järjestik liidestest erineb. Ei ole eraldi kellaliini, mis ülemad-alamad ühte takti seab.

Teine erinevus on see, et UART töötab kahe seadme vahel. SPI ja I2C võimaldavad võrke.

UARTi puhul on ülioluline jälgida, et ühe integraalskeemi TX ühendatakse kindlasti teise integraalskeemi RX-i külge ja vastupidi. Usu või mitte, see on üks tüüpviga esimese ringi prototüüpidel.

Kokkuvõte

Sellest põgusast ülevaatest ei tasu ennast uinutada lasta. Sardsüsteemide loomine (mikrokontroller + selle lisaseadmed) on piisavalt keeruline ettevõtmine. Siinkirjeldatu aitab sind kindlasti edasi, kuid saatan on peidus pisidetailides.

Õnneks on kapitalistlikus maailmas igasuguste integraalskeemide tootjad väga huvitatud sellest, et sa just nende tooteid ostaksid. Seetõttu üritavad nad oma toodete kasutamist sinu jaoks võimalikult lihtsaks teha, pakkudes suurt hulka kirjandust ja näidiseid. Otsi need üles ja loe põhjalikult.

Postituse päises oleva foto autor on Andres Keskküla