This is an old revision of the document!
Raamat, mida käes hoiad, on esimene praktiline mikrokontrolleri ja robootika käsiraamat eesti keeles, mis autorite lootuste kohaselt aitab robootikahuvilistel oma teadmisi laiendada ja paremaid lahendusi ehitada ning meelitab uusi huvilisi inseneriteadustega tegelema. Tegemist on just Eesti vajadustest ja situatsioonist lähtuva praktilise abimehega, mida saab kasutada nii koolis, ülikoolis, hobirobootikas kui ka ettevõtetes praktiliste AVR mikrokontrolleritel põhinevate süsteemide õppimisel ja arendamisel. Käsiraamat on suunatud nii õpetajale kui ka õpilasele, aidates mõlemal kiiremini ja tulemuslikumalt soovitud tulemuseni jõuda: õpilastel siis targemaks saada ja õpetajatel oma õppeaine lihtsamalt ja paremini õpilasteni viia :)
Platvorm
Praktiliste harjutuste konkreetsuse huvides on elektroonika platvormiks valitud ATmega128 mikrokontrolleril põhinev Mehhatroonika ja Robootika Kodulabori komplekt, mis on paljudes Eesti koolides juba kasutusel. AVR on PIC-i kõrval üks kõige levinumatest mikrokontrolleritest harrastuselektroonikute seas ja see on õppeotstarbeks igati sobilik. AVR-i kohta leiab nii internetist kui raamatutest ka palju ingliskeelset infomaterjali.
Raamat jaguneb tinglikult viieks osaks.
1. osa teeb kiire sissejuhatuse algajale või meeldetuletuse kogenud elektroonikule lihtsatest, kuid hädavajalikest elektriskeemi arvutusvalemitest. Need valemid ja nende rakendamisoskus tulevad kasuks mitmete praktiliste harjutuste läbimisel. Kiirtutvustus on ka C-keele kohta, mis annab näidete varal ülevaate keele süntaksist.
2. osa annab ülevaate 8-bitilistest AVR seeria mikrokontrollerist ATmega128 näitel. Peatükk seletab eesti keeles lahti AVR-i andmelehtedes kirjutatu ja on abiks praktiliste harjutuste läbimisel. Algaja võib AVR-i tutvustuse esialgu vahele jätta ja pöörduda selle poole harjutuste käigus, sest tutvustus eeldab üldteadmisi, mida annavad harjutuste teoreetilised peatükid.
3. osa kirjeldab praktiliste tööde aluseks olevat riist- ja tarkvara platvormi. Tarkvaraplatvormi kuulub ka harjutuste jaoks loodud tarkvarateek, mis teeb levinuima mikrokontrolleri funktsionaalsuse kasutamise lihtsaks ja mugavaks. Väheneb nn. raua programmeerimise maht ja rohkem saab tähelepanu pöörata seadme toimeloogikale. Tarkvarakeskkondadest on toetatud nii Windowsi kui ka Linuxi operatsioonisüsteem.
4. osas on praktilised harjutused, mis on konkreetsed näited enam levinud elektroonikaseadmete kasutamiseks AVR mikrokontrolleriga. Kõik harjutusülesanded on üles ehitatud ja teema järgi grupeeritud nii, et neid oleks õppimisel võimalikult mugav kasutada. Igal harjutuse peatükil on eraldi seadet ja selle tööpõhimõtet selgitav teooriaosa ning praktiline osa, mis õpetab seadet programmi kaudu juhtima. Harjutuste paremaks mõistmiseks on toodud ka lühinimekiri raamatu teistest peatükkidest. Harjutuste gruppide juurde kuuluvad harjutusülesanded, mida õpetaja saab anda grupitööna. Iga teema sisaldab ka kordamisküsimusi, mis tihti sunnivad antud teema kohta rohkem infot otsima.
5. peatükk on samuti hea õppimise abiline, eriti projektitöö puhul. Peatükk näitlikustab, kuidas esitada projektitööna valminud lahendust ja selle dokumentatsiooni. Toodud on soovitatavad dokumentatsiooni punktid koos osalise näitelahendusega.
Loodame, et raamat on abimeheks nii noorele kui ka vanale robootika- ja mikrokontrollerite huvilisele ning toob mehhatroonika kui suure perspektiiviga tulevikuala juurde uusi huvilisi.
Lumine ja pakasene Tallinn, jaanuar 2010
Raivo Sell
Mikrokontroller on arvuti mahutatuna ühe kiibi peale (inglise keeles computer-on-a-chip). Tegu on integraalskeemiga, mis sisaldab nii mälu, protsessorit kui ka sisend-väljundliideseid. Mikrokontroller programmeeritakse täitma mingit kindlat ülesannet, nii et kui funktsionaalsust tahetakse muuta või täiendada, siis tuleb kiibile uus programm peale laadida. Mikrokontrollerid erinevad tavaarvutist (lauaarvuti, sülearvuti, server) mitme erineva aspekti poolest:
Mikrokontrollereid leidub väga palju seadmetes, mida inimesed igapäevaselt kasutavad, näiteks kodutehnika (mikrolaineahi, telekas), mänguasjad (Lego NXT, rääkivad nukud), sõiduvahendid (auto, tõstuk) jms. Nende laialdane kasutus on olnud võimalik tänu sellele, et oma programmeeritavuse ja laialdase funktsionaalsuse tõttu on seadmetele lihtne juurde lisada uusi omadusi ning muuta need intelligentsemateks.
Robootika on ala, mis ühendab endas teadmisi ja tehnoloogiat robotite ehitamiseks. Tehnoloogia kiire arengu tõttu on aga üha hägustumas mõiste robot kui inimest asendav automaat. Robotina ei saa võtta ainult humanoidrobotit, autotööstuse koosteliini robotkätt, lennuki autopilooti, närvivõrkudel põhinevat tehisintelligenti või lihtsat koristusrobotit, vaid juba ka arvutis jooksvat tarkvara, mis teeb inimese eest mingi töö ära (näiteks raporti koostamine). Roboteid luuakse teadupärast ju inimese asendadamiseks teatud ülesannete täitmisel. Selleks on mitmeid põhjuseid: töökeskkond on inimesele liiga ohtlik, tootmishinda tuleb alandada, et inimtööjõu eest ei peaks enam maksma, nüri ja üksluine töö põhjustab palju eksimusi inimese töös või uued juhtimissüsteemid on nii keerulised ja ajakriitilised, et inimene tuleb asendada automaatse otsustajaga.
Kuna robootika valdkond on väga lai, siis järgnevalt piiritleme seda kui hobirobootikat, kus süsteemid ei ole väga keerulised ning on võimetekohased ehitada ka üksiktegijal. Hobirobootikas on levinumad mikrokontrollerid järgmised:
Väga tihti on kolmandad osapooled loonud arendusplaadid ja -keskkonnad eelnevalt mainitud mikrokontrollerite baasil. Kuna neid on palju, siis tasub välja tuua vaid tuntumad: Arduino (AVR-i baasil), BASIC Stamp (PIC-i baasil) ja Lego NXT (ARM-i baasil). Raamatus lähemalt käsitletavad Kodulabori arendusvahendid on loodud AVR ATmega128 mikrokontrolleri baasil.
Kuna mikrokontrollereid ja nende baasil loodud arendusplaate on väga palju, siis tekib kindlasti küsimus, et kuidas see kõige sobivam leida. Laias laastus võib vaadeldavad omadused jagada nelja kategooriasse - hind, füüsilised parameetrid, arenduskeskkond ja klienditugi. Füüsilistest parameetritest tasub jälgida järgmisi:
Arenduskeskkonna all mõeldakse PC arvuti tarkvara, mille abil saab teha järgmist: kirjutada ja kompileerida programmi, laadida programm mikrokontrollerisse ning siluda programmi töö käigus, et avastada võimalikke vigu. Siinkohal saabki määravaks see, kui mugav ja lihtne on kõiki neid toiminguid teha, kuna programmi väljatöötamise käigus on see põhiline töökeskkond. Siit jõuab ka neljanda kategooria - klienditoe - juurde ehk kui lihtne on saada abi ja toetust võimalike ettetulevate probleemide lahendamiseks. Kõiki neid nelja eespool mainitud kategooriat vaagides peakski sobiva arendusplaadi leidma.
Praktilistes harjutustes on kirjeldatud elektriskeeme, mis on niivõrd tüüpilised, et on järgnevates peatükkides eraldi välja toodud. Nende tundmine on oluline praktilistest harjutustest aru saamiseks ja läbimiseks. Kindlasti tulevad need kasuks ka paljudes huviliste isiklikes projektides.
Ohmi seadust kasutatakse elektrijuhile rakendatud pinge ja juhti läbiva voolutugevuse vahelise sõltuvuse iseloomustamiseks. Iseloomustav tegur on juhi takistus ehk juhi omadus elektrilaengute liikumist takistada. Ohmi seaduse sõnastas Georg Simon Ohm järgmiselt: voolutugevus juhis on võrdeline juhi otstele rakendatud pingega ja pöördvõrdeline juhi takistusega. Valemi kirjapilt:
I = U / R
kus:
Ohmi seadusest on tuletatud mitmeid teisi valemeid, mida elektroonikas igapäevaselt kasutatakse.
Kui LED-i (valgusdioodi) on vaja toita kõrgema pingega, kui on selle päripinge, ja väiksema vooluga, kui toiteallikas välja annab, tuleb LED-iga järjestikku lisada takisti. Takisti piirab nii voolu kui tekitab vajaliku pingelangu. Õige takisti leidmiseks on Ohmi seadusest tuletatud lihtne valem:
R = (Uin - Uf) / If
Ur = Uin - Uf
Pr = Ur ⋅ If
kus:
LED-i voolu piirav takisti peab olema vähemalt sama suure takistusega kui R ja vähemalt sama suure võimsusega kui Pr.
Pingejagur on elektriahel, mille väljundpinge moodustab osa sisendpingest. Väljundpinge suurus sõltub elektriahela moodustavate takistite takistuse suhtest. Kõrvaloleval skeemil on toodud kahe takistiga pingejaguri elektriskeem. Skeemi väljundpinge on arvutatav järgmise valemiga:
U2 = U1 ⋅ (R2 / (R1 + R2))
kus:
Valem tuleneb Ohmi seadusest, mille järgi:
I = U1 / (R1 + R2)
ning:
U2 = I ⋅ R2
Kauaaegne populaarne PC arvutite programmeerimiskeel C on laialt levinud ka mikrokontrollerite programmeerimisel. C on lakooniline riistvaralähedane keel, mis võimaldab kirjutada riistvara võimalusi efektiivselt kasutavat programmikoodi. C-keele süntaksis on võtmesõnu minimaalselt, palju sisaldab see erineva tähendusega märke, mis teevad keele õppimise raskeks. Järgnev peatükk sisaldab lühiülevaadet C-keele süntaksi osadest, mis on kasutusel ka praktiliste näidete juures. Algajal on C kohta soovitatav lugeda täiendavaid materjale.
Põhimõtteliselt võib C-keele programmi kirjutada ükskõik mis kujul, kas või üherealisena, sest kompilaator eeldab vaid süntaksireeglite järgimist. Samas on selguse ja lihtsuse huvides ikkagi soovitatav tähelepanu pöörata ka programmikoodi stiilile. Tüüpiline C-keele programmi ülesehitus:
/* Päisefailide kaasamine */ #include <avr/io.h> #include <stdio.h> /* Makro-deklaratsioonid */ #define PI 3.141 /* Andmetüübid */ typedef struct { int a, b; } element; /* Globaalsed muutujad */ element e; /* Funktsioonid */ int main(void) { // Lokaalsed muutujad int x; // Programm printf("Tere maailm!\n"); }
Programmi saab kirjutada teksti, mida ei kompileerita ja mis on programmeerijale abiks selgitamisel või märkmete tegemisel. Ka saab kommentaare kasutada programmilõikude ajutiseks täitmisest kõrvaldamiseks. Näide kahte liiki kommentaaridest:
// Üherealine kommentaar. // Kommentaariks loetakse kahe kaldkriipsu järel olevat teksti. /* Mitmerealine kommentaar Kommentaari algus ja lõpp määratakse kaldkriipsude ja tärnidega. */
C-keele baasandmetüübid:
Tüüp | Miinimum | Maksimum | Bitte | Baite |
---|---|---|---|---|
(signed) char | -128 | 127 | 8 | 1 |
unsigned char | 0 | 255 | 8 | 1 |
(signed) short | -32768 | 32767 | 16 | 2 |
unsigned short | 0 | 65535 | 16 | 2 |
(signed) long | -2147483648 | 2147483647 | 32 | 4 |
unsigned long | 0 | 4294967295 | 32 | 4 |
float | -3.438 | 3.438 | 32 | 4 |
double | -1.7308 | 1.7308 | 64 | 8 |
Sulgudes olevat sõna “signed” ei pea kasutama, sest ilma selleta andmetüübid juba on vaikimisi bipolaarsed.
AVR mikrokontrolleril int = short
PC arvutil int = long
C-keeles puudub spetsiaalne teksti-andmetüüp. Selle asemel kasutatakse char tüüpi massiive (nendest edaspidi) ja ASCII “tähestikku”, kus igal tähel ja märgil on oma järjekorranumber.
Programmis saab kasutada kindlat andmetüüpi mälupesasid - muutujaid. Muutujate nimed võivad sisaldada ladina tähestiku tähti, numbreid ja alakriipsu. Nimi ei tohi alata numbriga. Muutuja deklareerimisel kirjutatakse selle ette andmetüüp. Väärtuse omistamiseks muutujale kasutatakse võrdusmärki (. Näide muutujate kasutamisest:
// char tüüpi muutuja c deklareerimine. char c; // Muutujale c väärtuse omistamine. c = 65; c = 'A'; // A on ASCII märgisüsteemis samuti väärtusega 65 // int tüüpi muutuja i20 deklareerimine ja algväärtustamine. int i20 = 55; // Mitme unsigned short tüüpi muutuja deklareerimine unsigned short x, y, test_variable;
Konstante deklareeritakse samamoodi nagu muutujaid, kuid ette lisatakse const võtmesõna. Konstantide väärtust ei saa programmi käigus muuta. Näide kasutamisest:
// int tüüpi konstandi määramine const int x_factor = 100;
Baasandmetüüpidest saab struct võtmesõnaga struktuure koostada. Struktuur on justkui kombineeritud andmetüüp. Tüüpi deklareeritakse typedef võtmesõnaga. Näide struktuurist andmetüübi loomise ja kasutamise kohta:
// Uue punkti andmetüübi deklareerimine typedef struct { // x ja y koordinaat ning värvikood int x, y; char color; } point; // Punkti muutuja deklareerimine point p; // Punkti koordinaatide määramine p.x = 3; p.y = 14;
Andmetüüpidest võib koostada massiive (jadasid). Massiiv võib olla ka mitmemõõtmeline (tabel, kuup, jne). Näide ühe- ja kahemõõtmelise massiivi kasutamisest:
// Ühe- ja kahemõõtmelise massiivi deklareerimine. char text[3]; int table[10][10]; // Teksti moodustamine tähemassiivist text[0] = 'H'; // Täht text[1] = 'i'; // Täht text[2] = 0; // Teksti lõpetamise tunnus (null-bait) // Tabeli ühe elemendi muutmine table[4][3] = 1;
Muutujate, konstantide ja väärtust tagastavate funktsioonidega saab koostada avaldisi (tehteid). Avaldise väärtusi saab omistada muutujatele, neid saab kasutada funktsiooni parameetritena ja erinevates tingimuslausetes.
C-keeles toetatud aritmeetilised tehted on liitmine (+), lahutamine (-), korrutamine (*), jagamine (/) ja mooduli võtmine (%). Näited aritmeetiliste tehete kasutamisest:
int x, y; // Mooduli võtmine, korrutamine ja väärtuse omistamine. // x saab väärtuse 9. x = (13 % 5) * 3; // Liitev-omistav operaator. // x väärtuseks saab 14. x += 5; // Ühe lahutamise kiirmeetod // x väärtuseks saab 13. x--;
Loogilised tehted on eitus (!), loogiline korrutamine (&&) ja loogiline liitmine (||). Näide tehete kasutamisest:
bool a, b, c; // Algväärtustamine. a = true; b = false; // Eitus. // c väärtus tuleb väär sest tõest eitati. c = !a; // Loogiline korrutamine. // c väärtuseks tuleb väär, sest üks operandidest on väär. c = a && b; // Loogiline liitmine. // c väärtus tuleb tõene, sest üks operandidest on tõene. c = a || b;
NB! bool andmetüüp C-keeles tegelikult puudub, selle asemel on kasutusel täisarvud, kus 0 tähistab väära ja iga muu arv tõest väärtust. Näiteks Kodulabori teegis on defineeritud bool kui unsigned char. Konstant true tähistab seal väärtust 1 ja false väärtust 0.
Arvude väärtuste võrdlemisel saadakse loogilised väärtused. Võrdlustehted on samaväärsus (, erinevus (!
, suurem (>), suurem-võrdne (>
, väiksem (<) ja väiksem-võrdne (⇐). Näide kasutamisest:
int x = 10, y = 1; // Suurem-kui võrdlustehe, mis on tõene. // Tehte ümber on sulud vaid selguse pärast. bool b = (5 > 4); // Erinevuse tehe. // Tehte tulemus on väär. b = (4 != 4); // Aritmeetiline, võrdlus ja loogiline tehe üheskoos. // b tuleb väär, sest esimene loogilise korrutise operand on väär. b = (x + 4 > 15) && (y < 4);
Bititehted on andmetega binaarses arvusüsteemis tegelemiseks. Neid saab rakendada kõigi täisarv-tüüpi andmetega. Bititehted sarnanevad loogiliste tehetega, kuid erinevad selle poolest, et tehe teostatakse iga bitiga eraldi, mitte kogu arvuga. C keeles on bititeheteks inversioon (~), konjunktsioon (&), disjunktsioon (|), antivalentsus (^), nihe vasakule («) ja nihe paremale (»).
// Märgita 8-bitise char-tüüpi muutuja deklareerimine. // Muutuja väärtus on kümnendsüsteemis 5, kahendsüsteemis 101. unsigned char c = 5; // Muutuja c disjunktsioon arvuga 2 (kahendsüsteemis 010). // c väätuseks saab 7 (kahendsüsteemis 111). c = c | 2; // Bitinihe vasakule 2 võrra. // c väärtuseks saab 28 (kahendsüsteemis 11100). c = c << 2;
Bititehted on hädavajalikud mikrokontrollerite registrite kasutamisel. Täpsemalt tutvustab neid AVR registrite peatükk.
Funktsioon on programmilõik, mida saab selle nime järgi täitmiseks välja kutsuda. Funktsioonil võivad olla parameetrid ja funktsioon võib tagastada ühe väärtuse. Kui funktsioon ei tagasta väärtust, on selle tüüp void. Kui funktsioonil pole parameetreid, tuleb vanemat C-keele kompilaatorit kasutades void kirjutada ka parameetrite deklaratsiooni asemele. Näide liitmisfunktsioonist ja ilma tagasisideta funktsioonist:
// Kahe int tüüpi parameetriga funktsiooni deklareerimine. // Funktsioon tagastab int-tüüpi väärtuse. int sum(int a, int b) { // Kahe arvu liitmine ja summa tagastamine return a + b; } // Ilma parameetrite ja tagastatava väärtuseta funktsioon. void power_off(void) { }
Funktsiooni kasutamiseks tuleb see välja kutsuda. Funktsioon peab programmikoodis olema deklareeritud enne välja kutsumise kohta. Näide liitmisfunktsiooni väljakutsumisest.
int x; int y = 3; // Liitmisfunktsiooni väljakutsumine. // Parameetriteks on muutuja ja konstandi väärtus. x = sum(y, 5); // Väljalülitamise funktsiooni väljakutsumine. // Parameetrid puuduvad. power_off();
C-keele programmi täitmist alustatakse main nimelisest funktsioonist, mis teeb selle kohustuslikuks funktsiooniks.
Tingimuslause võimaldab vastavalt sulgudes oleva avaldise tõesusele täita või mitte täita tingimusele järgnevat lauset või programmilõiku. Tingimuslause võtmesõna on if. Näide kasutamisest:
// Avaldis on tõene ja lause x = 5 täidetakse, // sest 2 + 1 on suurem kui 2. if ((2 + 1) > 2) x = 5; // Kui x on 5 ja y on 3, siis täidetakse järgnev programmilõik. if ((x = 5) && (y = 3)) { // Suvaline tegevus y = 4; my_function(); }
Tingimuslause võib olla pikem ja sisaldada ka lauset või programmilõiku, mis täidetakse avaldise mittetõesuse korral. Selleks tuleb if tingimuslause järel kasutada else võtmesõna.
// Kas x on 5 ? if (x = 5) { // Suvaline tegevus z = 3; } // Kui x ei olnud 5, kas siis x on 6 ? else if (x = 6) { // Suvaline tegevus q = 3; } // Kui x ei olnud 5 ega 6... else { // Suvaline tegevus y = 0; }
Kui on vaja võrrelda avaldist mitme erineva väärtusega, on mõistlik kasutada valikulauset switch võtmesõnaga. Näide kasutamisest:
int y; // Tingimuslause y võrdlemiseks switch (y) { // y on 1 ? case 1: // Suvaline tegevus. function1(); break; // y on 2 ? case 2: // Suvaline tegevus. function2(); break; // Kõik muud juhtumid default: // Suvaline tegevus. functionX(); // break lauset pole vaja, // kuna võrdlemine lõppeb nagunii. }
Tsüklitega saab programmilõiku täita mitmeid kordi.
while võtmesõnaga tähistatud programmilõiku täidetakse seni, kuni sulgudes olev avaldis on tõene.
int x = 0; // Tsükkel kestab seni, kuni x on väiksem kui 5. while (x < 5) { // x suurendamine ühe võrra. x++; }
for võtmesõnaga tsükkel sarnaneb while tsüklile, kuid lisaks on sulgudes ära määratud enne tsüklit täidetav lause ja iga tsükli ajal täidetav lause.
Näide:
int i, x = 0; // Algul määratakse i nulliks. Tsüklit täidetaks seni, kuni // i on vähem kui 5. Iga tsükli lõpus suurendatakse i ühe võrra. for (i = 0; i < 5; i++) { // x suurendamine 2 võrra. x += 2; } // Siinkohal tuleb x väärtuseks 10.
while ja for tsüklitest saab erandkorras väljuda break võtmesõnaga. continue võtmesõnaga saab alustada järgmist tsüklit ilma järgnevat koodi täitmata.
int x = 0, y = 0; // Lõputu tsükkel, kuna 1 on loogiline tõesus. while (1) { // Tsüklist väljutakse, kui x on saavutanud väärtuse 100. if (x >= 100) break; // x suurendamine, et tsükkel kunagi lõppeks ka. x++; // Kui x on 10 või vähem, siis alustatakse järgmist tsüklit. if (x <= 10) continue; // y suurendamine. y++; } // Siinkohal on y väärtus 90.
Järgnevad peatükid tutvustavad AVR mikrokontrollerit mille põhjal on koostatud kogu käesolev raamat. Mikrokontroller, olgugi, et pisike, on täis palju võimalusi, mille kasutamise kohta on Atmel kirjutanud peaaegu 400-leheküljelise juhendi. Lisaks käivad sellega kaasas veel mitmed spetsiifilised lisadokumendid. Kogu sellest infost on siinkohal tehtud kiire ja võimalikult lihtne ülevaade mis aitab algajal paremini AVR-ist aru saada ja selle andmelehte lugema õppida.
AVR on Atmeli poolt toodetav 8-bitiste RISC mikrokontrollerite seeria. Harvardi arhitektuuri kohaselt on AVR-il eraldi programmi- ja andmemälu. Programmi jaoks on süsteemisiseselt ümberkirjutatav välkmälu (inglise keeles Flash), andmete jaoks staatiline (SRAM) ja EEPROM mälu. Taktsagedus ulatub enamasti kuni 16 MHz ja jõudlus on peaaegu 1 MIPS megahertsise takti kohta.
AVR mikrokontrollerite tootmist alustati 1997. aastal ja praeguseks on see vabakutseliste elektroonikute seas üks levinumaid. Esialgse edu tagasid odavad arendusvahendid, mitmekesine perifeeria ühes korpuses ja madal voolutarve. Nüüdseks võib eeliseks lugeda suure infomaterjali ja õpetuste pagasi, mis aastate jooksul tekkinud on. Paratamatult on AVR tehnoloogia vananev, kuid konkurentsis püsimiseks teeb Atmel ka tänapäevase perifeeria ning 16- ja 32-bitiste siinidega AVR mikrokontrollereid, millest esimesed on 8-bitistega ühilduvast XMega ja teised täiesti uuest AVR32 seeriast.
Vastavalt rakenduste tüübile on ka AVR mikrokontrollereid olemas erineva konfiguratsiooniga. Suurema osa AVR-e moodustab megaAVR seeria, mis on suure programmimälu mahuga. Vastupidiselt megaAVR seeriale on olemas tinyAVR seeria väiksemate kestade ja kärbitud võimalustega. Lisaks on veel mikrokontrollerite seeriad spetsiaalselt USB, CAN, LCD, ZigBee, automaatika, valgustuse juhtimise ja akutoitega seadmete jaoks.
Järgnevalt on kirjeldatud peamisi megaAVR seeria mikrokontrollerite võimalusi selle seeria ühe levinuima kontrolleri - ATmega128 näitel, mis on ka kodulabori komplektis kasutusel. Üldiselt on kõigil AVR seeria mikrokontrolleritel registrite nimed, tähendused ja kasutamise kord reglementeeritud, nii et näiteid saab väikeste muudatustega ka teiste kontrollerite puhul kasutada. Peamised erinevused esinevad perifeeria juures. Tutvustuse koodinäited on toodud Assembleris ja C-keeles AVR LibC abil.
Nagu kõik teisedki kiibid, on ka AVR mõne kesta sisse pakendatud. Traditsiooniline kest on DIP (nimetatakse ka DIL). DIP on nii-öelda jalgadega kest - kõik kiibi viigud on umbes 5-millimeetriste jalgadena näpuotsasuurusest mustast plastist korpusest välja toodud. DIP kest on mõistlik valik hobirakendustes ja prototüüpide puhul, sest selle jaoks on saada odavad pesad, kust mikrokontrolleri saab läbipõlemise korral lihtsalt kätte ja uuega asendada. Samas on jalad ka DIP kesta miinuseks, sest nende jaoks on vaja trükkplaadile auke puurida.
Palju kompaktsemad on pindliides ehk SMT (nimetatakse ka SMD) kestad, sest neil on jalad mõeldud mitte plaadi läbistamiseks, vaid otse rajale kinnijootmiseks. SMT kestas on kiibid õhukesed sendi- või mündisuurused neljakandilised mustad korpused, mille jalad on umbes millimeetri pikkused. SMT kestas kiipide jootmisel on vaja täpsemat kätt ja paremaid töövahendeid.
AVR-e on saada nii DIP kui SMT kestades. Viikusid on püütud loogiliselt ning elektriliselt ühtlaselt paigutada. Näiteks on maa ja toiteviigud suurematel kiipidel toodud mitmesse kiibi külge, välise kvartsi viigud on maa viigu lähedal, siinide viigud on numbrilises järjekorras, andmesideliideste viigud on kõrvuti jne. AVR digitaalsed viigud ühilduvad TTL/CMOS standardsete pingenivoodega. 5 V toitepinge juures tähistab pinge 0 kuni 1 V loogilist nulli, mida nimetatakse ja kirjutatakse elektroonikute kõnepruugis ka kui null, 0, madal, maa, mätas, ground või GND. Sama toitepinge juures tähistab pinge 3 kuni 5,5 V loogilist üht, mille nimetused on üks, 1, kõrge, high. Selline suur loogiliste väärtuse pingeskaala kehtib sisendite kohta - väljundpinge on ilma koormuseta AVR viikudel vastavalt olekule ikkagi 0 V või toitepinge lähedane. Tehnoloogiast tingituna on ka analoogpinge (ADC kanalid) väärtused lubatud sarnases 0 kuni 5,5 V vahemikus.
Et järgnevatest näidetest ATmega128 kohta paremini aru saada, on välja toodud ATmega128 SMT kesta viikude skeem. Viikude juures on selle number, primaarne funktsioon ja sulgudes alternatiivne funktsioon või mitu. Toiteotsad on GND ja VCC. AVCC ja AREF on vastavalt analoog-digitaalmuunduri toite ja võrdluspinge viigud. XTAL1 ja XTAL2 on välise kvarts-ostsillaatori, resonaatori või taktigeneraatori jaoks. Viigud PB0 kuni PG4 tähistavad sisend-väljundsiinide bitte. Viikude alternatiivfunktsioonidest tuleb juttu vastavates peatükkides.
Üks kõige raskemini mõistetavaid asju mikrokontrollerite juures on algajate jaoks tavaliselt “register”. Sellest mõistest ei pääse üle ega ümber, kui on soov mikrokontrolleritega tegeleda. Ka käesolev materjal eeldab, et lugeja on tuttav registri mõistega ja seepärast on järgnevalt seda algajale ka võimalikult lihtsalt selgitatud.
Register on nagu mõne kodumasina nuppude paneel. Seal on lülitid, mida saab sisse vajutada või välja lükata. Üks parim näide on kassetimängija. Kes veel mäletab, siis kassetimängijatel on (oli) vasakult paremale 6 nuppu:
Iga nupp teeb midagi, kuid ainult õigel kasutamisel. Näiteks stopp-nupp ei tee midagi enne, kui kassett on mängima pandud - alles siis teeb see midagi arusaadavat ja peatab mängimise. Edasi- või tagasikerimise nuppe võib aga igal ajal vajutada, sest linti hakatakse kerima nii poole mängimise kui seismise ajal. Salvestama hakkab kassetimängija aga ainult siis, kui salvestamise nupp koos mängimise nupuga alla vajutada. Mõni on ehk proovinud mitu nuppu või kõik nupud korraga alla vajutada - sel juhul võis mängija mida iganes teha või üldse katki minna.
Mikrokontrolleri registriga on sama lugu nagu kassetimängija nuppudega - iga nupuke paneb seal õigel kasutamisel midagi käima. Valesid nuppe vajutades mikrokontroller (enamasti) küll katki ei lähe, kuid ei tööta ka. Tegelikult registris selliseid nuppe nagu kodumasinatel muidugi pole, on hoopis hulk transistore, mis elektrit sisse ja välja lülitavad. Lihtsamatel mikrokontrolleritel on registris 8 transistoridel põhinevat elektrilist lülitit. Registrit võib aga käsitleda nagu 8-bitist arvu, milles iga bitt tähistab ühe lüliti olekut. Näiteks biti väärtus 1 võib tähendada, et lüliti on sees ja 0, et lüliti on väljas.
Kuna registri lülitite olekut saab väga hästi esitada arvuna ja vastupidi, siis võib registrit võrrelda ka mäluga, mis suudab hoida ühe arvu suurust informatsiooni. Selle võrdlusega jõudis jutt selleni, et registrid ongi mälupesad. Vahe mälupesaga seisnebki üldjuhul ainult selles, et mälupesa ei tee muud, kui hoiab informatsiooni, registris see informatsioon aga juhib midagi. Ehk kui pildil kujutatud registrisse kirjutada binaarväärtus 01100001, siis kolm näilist lülitit lükatakse alla ja midagi hakkab toimuma.
Kui kassetimängijal võib igat nuppu eraldi vajutada, siis registrites on ühe “lüliti” või biti muutmine keerulisem. Üldjuhul tuleb muuta kogu registri sisu korraga. Enne kui bittide muutmisest rääkida, tuleks aga teada veel seda, et registreid on mikrokontrolleris palju. Mõnede mikrokontrolleri osade juhtimiseks võib kasutusel olla ka kümneid registreid. Registrite paljusus tähendab, et registreid peab kuidagi eristama ja seda tehakse nimega. Üks ilus registri nimi on näiteks PORTB. Tõe huvides võib mainida, et tegelikult on nimed vaid inimese välja mõeldud asendused numbrilistele aadressidele.
C-keele programmis registri väärtuse kirjutamiseks või lugemiseks tuleb selle poole nagu muutuja poole pöörduda. Järgnev näide demonstreerib väljamõeldud registrisse REG binaarväärtuse kirjutamist ja selle väärtuse muutujasse reg lugemist. Binaarväärtuse ette kirjutatakse 0b (ees on null), et kompilaator arvusüsteemist aru saaks.
REG = 0b01100001; unsigned char reg = REG;
Põhimõtteliselt registrite väärtuse kirjutamises ja lugemises midagi keerulist polegi, kuid keerulisemaks läheb lugu siis, kui soovitakse muuta registri üksikute bittide väärtust. Bittide muutmiseks tuleb enne aga selgeks saada binaartehted ja erinevad arvusüsteemid. Keegi ei keela tegutseda binaararvudega, kuid binaararvudega tegelemine on tülikas nende pikkuse tõttu ja tavaliselt kasutatakse nende asemel heksadetsimaalarve, mis on lühemad.
Heksadetsimaalarvus pole numbrid mitte 0 ja 1, nagu binaarsüsteemis, ega 0-st 9-ni, nagu kümnendsüsteemis, vaid 0-st F-ni. Üks heksadetsimaalnumber moodustub neljast bitist. Kõrvalolev tabel näitab heksadetsimaalnumbritele vastavaid binaararve. Binaararve teisendatakse heksadetsimaalarvuks bitte nelja kaupa madalamast järgust alates lugedes. Järkusid loetakse paremalt vasakule ja nende nummerdamist alustatakse nullist. Näiteks binaararvu 1110 madalaima ehk 0. järgu väärtus on 0 ja kõrgeima ehk 3. järgu väärtus on 1. Eespool toodud näidisregistri binaarväärtus 01100001 on heksadetsimaalkujul 61, mis C-keeles kirjutatakse kujul 0x61 (ees on null).
Üksikute bittide muutmiseks arvus (registris, muutujas või kus iganes) tuleb kasutada binaartehteid. Binaartehe on tehe binaararvude vahel, kus nende arvude iga biti vahel toimub omaette loogikatehe. Enamasti on mikrokontrollerites kasutusel neli binaartehet, millel kõigil on mitu nimetust. Kõrval on toodud kõigile neljale binaartehtele vastav loogikatehe üksiku biti või bittidega.
Nüüd on lühidalt selgitatud kõik, mida läheb vaja üksikute bittide väärtuste muutmiseks. Kuid ilmselt jääb teooriast ikkagi väheks ja seepärast on järgnevalt toodud mõningad tüüpnäited registritega.
Selleks, et üks või enam bitte registris kõrgeks ehk üheks seada, tuleb kasutada loogilist liitmise tehet. Liitmistehte üks operand peab olema register, teine binaararv, kus kõrge on ainult see bitt, mida ka registris soovitakse kõrgeks seada. Seda teist binaararvu nimetatakse ka bitimaskiks. Kõrvalnäites toodud tehe näeb C-keeles välja niimoodi:
// Oletame, et REG = 0x0F REG = REG | 0x11; // Üks meetod REG |= 0x11; // Teine meetod // Siinkohal REG = 0x1F
Ühe või enama biti registris madalaks ehk nulliks seadmiseks tuleb kasutada loogilise korrutamise tehet. Tehte üks operand peab olema register, teine bitimask, kus madalaks on seatud vaid see bitt, mida ka registris soovitakse madalaks seada. Kõrvalnäites toodud tehe näeb C-keeles välja nii:
// Oletame, et REG = 0x0F REG = REG & 0xFE; // Üks meetod REG &= 0xFE; // Teine meetod // Siinkohal REG = 0x0E
Ühe või enama biti registris inverteerimiseks tuleb kasutada mittesamaväärsuse tehet. Tehte üks operand peab olema register, teine bitimask, kus kõrgeks on seatud vaid see bitt, mida ka registris soovitakse inverteerida. Kõrvalnäites toodud tehe näeb C-keeles välja järgmiselt:
// Oletame, et REG = 0x0F REG = REG ^ 0x11; // Üks meetod REG ^= 0x11; // Teine meetod (rakendada tohib korraga ainult üht) // Siinkohal REG = 0x1E
Kogu registri bittide inverteerimiseks tuleb kasutada eitustehet. See on unaarne tehe ehk tal on ainult üks operand. Kõrvalnäites toodu tehe näeb C-keeles välja niimoodi:
// Oletame, et REG = 0x0F REG = ~REG; // Siinkohal REG = 0xF0
Ühe või enam biti väärtuse lugemiseks registrist tuleb kasutada sama tehet mis biti nullimisel - loogilist korrutamist. Tehte üks operand peab olema register, teine bitimask, kus kõrgeks on seatud vaid see bitt, mille väärtust registrist lugeda soovitakse. Kõrvalnäites toodud tehe näeb C-keeles välja järgmiselt:
// Oletame, et REG = 0x0F unsigned char x = REG & 0x01; // Siinkohal x = 0x01
Tegelikult on paljudes programmeerimiskeeltes peale binaartehete veel mõned bitioperatsioonid, mis teevad programeerija elu lihtsamaks. Need on bitinihutuse operatsioonid, mis binaararvus nihutavad bitte kas vasakule või paremale poole. Nihutusoperatsioonide põhiline väärtus seisneb registritega tegeldes nende võimes bitijärkusid bitimaskiks teisendada ja vastupidi.
Kõrvaloleval pildil on toodud näide bitinihutuse operatsioonist vasakule. Bitinihutus pole loogikaoperatsioon ja sel puudub vastav tähis, C-keeles on see aga “«”. Nihet vasakule kasutatakse bitijärgu bitimaskiks teisendamiseks. Näiteks kui soovitakse kuuenda biti (NB! järk on 5) maski, siis tuleb arvu 1 nihutada vasakule 5 korda. Näites toodud operatsioon näeb C-keeles välja sedasi:
REG = 0x01 << 5; // Siinkohal REG = 0x20
Sarnaselt bitinihkega vasakule toimib ka bitinihke operatsioon paremale. Selle operatsiooni tähis C-keeles on “»”. Nihet paremale kasutatakse bitimaskist biti loogilise väärtuse leidmiseks. Eespool oli toodud näiteks üksiku biti väärtuse lugemise tehe. Oletame, et bitt, mida lugeda, pole aga madalaima järguga, vaid näiteks järguga 5. Sel juhul oleks lugemisel vastus kas 0x20 või 0x00, kuid vahel läheb vaja vastust 1 või 0 ja siis tulebki appi nihe paremale. Kõrvalnäites toodud operatsioon näeb C-keeles välja nii:
// Oletame, et REG väärtus on 0x20 unsigned char x = REG >> 5; // Siinkohal on x väärtus 0x01 (ehk lihtsalt 1)
Kui bitinihke operatsioonidega nihkub bitt madalaimast järgust paremale või kõrgeimast järgust vasakule, siis see bitt kaob. Mõnedes programmeerimiskeeltes on olemas ka roteeruvad bitinihke operatsioonid, kus “servast” välja minev bitt tuleb teiselt poolt tagasi. C-keeles roteeruvad bitinihke operatsioonid puuduvad, kuid vajadusel saab need ise kirjutada.
Kõik toodud bitioperatsioonide näited toimivad peale registrite ka muutujatega ja konstantidega. Viimased saavad muidugi ainult operandideks, mitte vastusteks olla.
Selleks et midagi reaalselt ka mikrokontrolleri registritega teha saaks, tuleb osata selle mikrokontrolleriga läbi saada. Kõigi mikrokontrolleritega käib kaasas andmeleht või mitu, kus on dokumenteeritud kogu selle struktuur ja funktsionaalsus. Andmelehes on kirjeldatud ka registreid. Järgnevalt uurime,kuidas aru saada AVR-i andmelehe registrite kirjeldusest.
Pildil on toodud ATmega128 mikrokontrolleri register UCSRnA, mille pikem nimetus on “USART Control and Status Register A”. See on register, millega sätitakse AVR-i USART moodulit ja kust saab lugeda selle mooduli olekuid. Kõik AVR-i registrite nimed kirjutatakse suurte tähtedega, kuid tähelepanelik lugeja ilmselt märkab, et selles registris on väike n-täht. Väikese n-tähega tähistatakse nimelt mõne mooduli indeksit. Kuna ATmega128-s on 2 üsna sarnast USART moodulit, siis ei kirjeldata nende registreid topelt, vaid ühe korra ja n-tähe asemele peab lugeja arvestama kas “0” või “1”. Seega ATmega128-s on registrid UCSR0A ja UCSR1A.
Registri sisu tähistab paksu piirjoonega 8 lahtriga kast. Iga lahter tähistab üht bitti. Kasti kohal on toodud biti järgud - paremalt vasakule suurenevad. Kuna AVR on 8-bitine mikrokontroller, on ka enamik registreid 8-bitised. Mõningad erandid on 16-bitised registrid, mis koosnevad tegelikult kahest 8-bitisest. Peale selle, et registritel on nimi, on ka igal registri bitil nimi - täpselt nagu kassetimängija nuppudelgi. Iga biti kohta käib andmelehes ka selle selgitus. Biti nimed on samuti lühendid ja n-täht neis tuleb samuti asendada mooduli indeksiga. Mõnes registris pole kõiki 8 bitti kasutatud ja sel juhul tähistatakse biti lahter sidekriipsuga.
Registri bittide all on toodud kaks rida, kus on kirjas see, kas bitt on loetav, kirjutatav või mõlemat. Näiteks olekubitte ei saa kirjutada, isegi kui seda programmis üritada - bitt lihtsalt ei omanda väärtust, mis talle antakse. Biti puhul, mida saab ainult kirjutada, on öeldud üks väärtus, mis selle lugemisel alati tuleb. Teises reas on bittide all toodud väärtus, mis on bitil pärast mikrokontrolleri käivitamist (inglise keeles reset).
Kui AVR-i registrite nimed viitavad tegelikult mälupesade aadressidele, siis biti nimede taga peitub selle biti järgu number. Seega registris bittidega manipuleerimiseks tuleb bitinimed nihutusoperatsiooni abil bitimaskiks teisendada. Järgnevalt on toodud mõned C-keele näited eeltoodud USART 0 mooduli registri kasutamiseks.
// TXC0 biti kõrgeks seadmine UCSR0A |= (1 << TXC0); // U2X0 biti madalaks seadmine UCSR0A &= ~(1 << U2X0); // UDRE0 biti(maski) väärtuse lugemine unsigned char u = (UCSR0A & (1 << UDRE0)); // Siinkohal on u väärtus kas 0 või 32, // mis võimaldab seda loogilises avaldises kasutada if (u) { // MPCM0 biti inverteerimine UCSR0A ^= (1 << MPCM0); } // Mõnikord on aga vaja saada konkreetne 0 või 1 väärtus. // Selleks tuleb loetud bitti nihutada paremale. u >>= UDRE0; // Siinkohal on u väärtus kas 0 või 1
AVR-il on sisemine 8-bitine andmesiin, kustkaudu liiguvad andmed arvutusüksuse (ALU), olekuregistri (SREG), programmiloenduri (PC), muutmälu (SRAM) ja perifeeria vahel. ALU-s täitmisele minev programm ehk instruktsioonide jada tuleb välkmälu aadressilt, mille määrab programmiloendur. ALU juurde kuuluvad 32 üldkasutatavat 8-bitist registrit, mida kasutatakse paljude instruktsioonide täitmisel operandidena.
AVR-i käsukonveier on kaheastmeline. Samal ajal kui üht instruktsiooni täidetakse, laetakse järgmine instruktsioon programmimälust juba valmis ära. See on ka põhjus, miks siirdekäskude täitmine võtab 2 takti siirdetingimuse täitumisel. Kuna uus instruktsioon laetakse käsukonveierisse alati järgmiselt mäluaadressilt, siis siiretel muule programmiaadressile tuleb eelnevalt laetud instruktsioon minema visata ja uus laadida, sest see oli vanast ehk siis valest kohast laetud.
Üldkasutatavaid registrid R0-R31 on justkui vahepuhvrid mälu ja perifeeria andmete hoidmiseks ning nendega toimetamiseks. Üldkasutatavad registrid lihtsustavad protsessori arhitektuuri, kuna ALU jaoks on need kiirelt kättesaadavad ja igal arvutusel ei pea operandide lugemiseks mälust andmesiini kasutama hakkama. Üldkasutatavaid registreid kasutatakse kõikide andmetega seotud aritmeetiliste ja loogiliste operatsioonide tegemiseks.
Assemblerkeeles programmeerides võib kiiret töötlust vajavaid andmeid üldkasutatavas registrites hoida. Kui programmeeritakse C-keeles ja on soov kindlasti kasutada üldkasutatavat registrit muutuja hoidmiseks, defineeritakse muutuja täiendavalt “register” tüüpi. Näiteks:
register char x;
Enamiku AVR-ide käsustik koosneb 90-133 erinevast instruktsioonist. ATmega128-l on 133 instruktsiooni. Instruktsioonid on kas ühe, kahe või üldse ilma operandideta. Enamik instruktsioone täidab mikrokontrolleri protsessor ühe takti jooksul, kuid keerukamad kulutavad kuni 5. AVR-i järeltulija XMega puhul on mitmeid instruktsioone täiendatud, nii et need kulutavad vähem takte. Suurem osa AVR-i instruktsioonidest on siireteks, andmete liigutamiseks, võrdlusteks, loogilisteks ning aritmeetilisteks teheteks. Tehete ja võrdluste puhul on kasutusel olekuregister,kus märgitakse vastavate bittidena ära juhud, kui tehte tulemus ALU-s oli negatiivne või positiivne, oli null, ületas maksimaalse võimaliku väärtuse (8-bitti), vajab biti ülekandmist järgmisesse tehtesse ja paaril keerukamal juhul veel.
Toodud on assembleris ehk puhtalt instruktsioonidena kirjutatud kood, mis liidab muutmälus aadressil $100 (detsimaalarvuna 256) asuvale baidile juurde arvu 5. Kasutatud käsud on olemas kõigil AVR-idel.
ldi r1, 5 ; Konstandi 5 laadimine üldkasutatavasse registrisse r1 lds r2, $100 ; Baidi laadimine muutmälust registrisse r2 add r2, r1 ; Registrile r2 registri r1 väärtuse liitmine sts $100, r2 ; Registri r2 väärtuse kirjutamine tagasi muutmällu
Pinumälu (inglise keeles Stack) on andmete ülesehitus, kus viimasena mällu kirjutatud andmed loetakse esimesena välja. AVR-is saab pinumälu kasutada alamfunktsioonide, katkestuste ja ajutiste andmete juures. Alamfunktsioonide ja katkestuste täitmisel lisatakse eelnevalt pinumällu programmiloenduri aadress, mille pealt programm katkes. Kui alamfunktsioon või katkestus on töö lõpetanud, loetakse pinumälust aadress, kust programmi tööd jätkata. Ajutisi andmeid lisatakse pinumällu tavaliselt lühemate programmilõikude juures, mis ei vaja mälu reserveerimist kogu programmi ajaks. Lihtsamad assemblerkeele programmid on kirjutatud üldjuhul nii, et pinumälu ei pea kasutama, kuid selle võtavad kasutusele kompilaatorid, kui programmis on palju muutujaid ning funktsioone.
MegaAVR seeria mikrokontrolleritel on pinumälu füüsiline asukoht muutmälus, kuid mõnel tinyAVR seerial muutmälu üldse puudub ja pinumälu tarbeks on spetsiaalne üsna piiratud mahuga mälu. Sellistele, ilma muutmäluta mikrokontrolleritele kompilaatoreid üldjuhul pole.
Kõrgtaseme keeles (Pascal, C, C++) programmeerides ei pea otseselt mikrokontrolleri siseeluga kursis olema, sest kompilaator valib ise oma äranägemise järgi üldkasutavaid registreid ja instruktsioone, kuid see teadmine tuleb kasuks. Oluline on mikrokontrolleri instruktsioone tunda ajakriitilistes rakendustes, kus protseduurid peavad toimuma loetud protsessori taktide jooksul.
Nii nagu enamik digitaalelektroonikatki, töötab AVR kindlal taktsagedusel. Kindel taktsagedus tagab kogu kiibi ulatuses andmevahetuse töökindluse. Taktsignaali ehk töötakti genereerimiseks on AVR-i puhul mitu võimalust.
See on kiibisisene taktigeneraator, mis ei vaja väliseid komponente, kuid pole ka kuigi kõrge sagedusega ega täpne.
Sama põhimõttega mis sisemine RC ostsillaator, kuid sel pole erilist eelist.
Kvartsostsillaatoris kasutatakse elektriväljas oma resonantssagedusel võnkuvat kristalli ja selle piesoelektrilist omadust mehhaanilisel deformatsioonil (võnkumisel) elektriväli tekitada. Kvartsostsillaatorit võimaldavad ligi 0,001% täpsust taktsagedust ja seda olenemata temperatuurist.
Tegu on kvartsostsillaatorile sarnaneva lahendusega, kus kasutatakse odavamat piesoelektrilist materjali. Resonaatorid on reeglina ka väiksemad kui kvartsostsillaatorid, kuid paraku on nad ka ebatäpsemad (~0,5%) ja temperatuuritundlikud.
Välist taktsignaali võib tekitada ükskõik mis seade, peaasi et taktsagedus ja amplituut (pinge) oleks piirides. Näiteks võib skeemis kasutada eraldi taktigeneraatorit, mis takteerib mitut mikrokontrollerit.
Katkestuse (inglise keeles interrupt) saavad AVR-il tekitada loendurid, andmesideliidesed, analoog-digitaalmuundur, komparaator, spetsiaalsed sisend-väljundviigud ja paljud muud asjad, olenevalt kontrollerist. Igat katkestust saab lubada või keelata seda genereerivas üksuses. Olenemata katkestuse lubamisest või mitte, on iga katkestuse jaoks vastavas kontrolleriüksuses 1-bitine andmeväli (lipuke, inglise keeles interrupt flag), mis märgitakse katkestust põhjustava sündmuse toimumisel tõeseks. Kui toimub nimetatud andmevälja muutumine ja katkestus on lubatud, hakkab kontroller täitma koodi, mis oli katkestuse toimumisel ette nähtud.
AVR mikrokontrolleris on iga katkestus seotud kindla sündmusega. Igal sündmusel on olekuregistris lipubitt, mis tähistab sündmuse juhtumist. Lisaks on sündmustega seotud katkestuste maskeerimise registrid ja vastavad bitid. Kui sündmuse katkestuse bitt on maskeerimata ja tekib sündmus, jätab protsessor mõne(kümne) töötakti jooksul käimasoleva programmi täitmise pooleli ning alustab katkestuse programmi täitmist. Pärast katkestuse programmi täitmist jätkab protsessor poolelijäänud programmi täitmist.
Katkestuste kasutamiseks AVR LibC teegiga tuleb kasutusele võtta interrupt.h fail. Katkestusel täitmisele minev programmikood lisatakse pärast “ISR”-i nimelist võtmesõna. “ISR” järele sulgudesse kirjutatakse katkestuse nimi. C-keele koodinäide:
#include <avr/interrupt.h> ISR(XXX_vect) { // Tee midagi }
Globaalne, kõigi katkestuste toimumise lubamine, määratakse ära juht- ja olekuregistris SREG. Võimaluse kõiki katkestusi keelata või lubada tingib andmete kaitse vajadus. Kuna katkestused katkestavad käimasoleva programmi täitmise, võivad nad segada või rikkuda andmeid, mida põhiprogramm katkestamise hetkel kasutas. Sellist olukorda saab vältida kõikide katkestuste keelamisega enne tundlike andmetega tegelemist. Globaalne katkestuste keelamine on lihtne, kui seda saab teha ühe registri (SREG) muutmisega. Pärast kriitilise programmiosa lõppu saab katkestused uuesti lubada ja kõik katkestused, mille lipuke vahepeal ära märgiti, lähevad täitmisele.
Oletame, et programmis on kasutusel 16-bitine muutuja, mille väärtust muudab nii põhiprogramm kui ka katkestuse programmilõik, ja selle muutuja väärtus omistatakse hiljem teisele muutujale:
#include <avr/interrupt.h> // Globaalsed 16-bitised muutujad x ja y unsigned short x, y; // Suvaline katkestus, mis muudab x väärtuse ISR(XXX_vect) { x = 0x3333; } int main() { // Muutujale x väärtuse omistamine x = 0x1111; // Mingi katkestuse tööle seadistamine // Globaalne katkestuste lubamine - // võrdub SREG registris I biti märkimisega sei(); // x väärtuse muutujasse y laadimine y = x; }
Programm on väga lihtne - algul omistatakse muutujale x väärtus 0x1111 ja hiljem selle väärtus omakorda muutujale y. Kui vahepeal tekib katkestus, saab x-i väärtuseks 0x3333. Loogikareeglite järgi saab muutujal y programmi lõpus olla kaks võimalikku väärtust, kuid 8-bitise AVR peal on ka kolmas võimalus. Nimelt, 8-bitise arhitektuuriga toimub 16-bitiste andmete liigutamine 2 takti jooksul ja vahepeal tekkiv katkestus võib andmete ühtsust rikkuda. Niisiis, peale 0x1111 ja 0x3333 võib tekkida ka väärtus 0x3311. Et sellist asja ei juhtuks, tuleks ajutiselt keelata katkestused enne operatsioone, mis toimuvad pikemalt kui 1 takti jooksul.
Toodud näites muutujale y muutuja x väärtuse omistamine ohutul meetodil:
// Globaalne katkestuste keelamine cli(); // Laadimine y = x; // Globaalne katkestuste uuesti lubamine sei();
Kõik AVR siinid on loetavad ja kirjutatavad, kui neid kasutada tavalises loogilises sisend-väljundrežiimis (inglise keeles input/output, ehk IO) . AVR siinid on nimetatud suurte ladina tähestiku algustähtedega A, B, C, jne. Mõnel AVR-il võib aga siin A puududa, kuigi B on olemas. Iga siin on 8-bitine ja iga biti jaoks on enamasti kontrolleri kestast välja toodud eraldi viik. Viikusid loendatakse arvudega alates nullist. Siini mõlema kasutussuuna jaoks on olemas kaks eraldi registrit. Lisaks on olemas iga siini kohta register siini reaalse toimimissuuna määramiseks, milles biti väärtus 1 näitab viigu kasutamist väljundina ja 0 sisendina. Kokku on iga siini kohta kolm registrit:
Vaja on siini B viigud 0-3 teha sisenditeks, viigud 4-7 väljunditeks, seada 5. viik kõrgeks ja lugeda 0-3 viigu väärtus muutujasse. C-keele programmi kood on järgnev:
#include <avr/io.h> int main() { unsigned char x; // Viigud 0-3 sisendiks, 4-7 väljundiks DDRB = 0xF0; // Viienda viigu kõrgeks seadmine PORTB |= (1 << PIN5); // 0-3 sisendviigu väärtuse lugemine x = PINB & 0x0F; }
Toodud näites on sisendeid kasutatud Hi-Z, ehk kõrge impendatsiga (inglise keeles high impedance) režiimis. Põhimõtteliselt on tegemist sisendiga, mis ei koorma peaaaegu üldse signaaliallikat. Seda režiimi võib vaja minna, kui viiku kasutatakse andmesiinina. Kui viik on kasutusel nupuga, lülilitiga või muus maad ning sisendit kokku ühendavas lahenduses, siis tasub sisendis kasutada pull-up takistit. Selleks tuleb sisendrežiimis seada kõrgeks vastava viigu väljundbitt - tulemusena lülitub toitepinge ja sisendi vahele takisti, mis hoiab sisendi pingenivood kõrgel, kui miski seda just alla ei tõmba. Pull-up takisti eesmärk on ära hoida sisendi “ujumine” (inglise keeles floating) staatilise elektri ja muude häirete tõttu. Pärast kontrolleri käivitumist on kõik IO siinid vaikimisi kõrge impedantsiga sisendrežiimis.
Enamasti on IO siinil olevaid viike peale loogiliste ühenduste kasutatud ka muu perifeeria tarbeks. Kui on soov kasutada viigu alternatiivfunktsiooni, tuleks tutvuda AVR-i andmelehega, kus on öeldud, mis režiimis peab IO viik olema. Näiteks ADC kanali sisendina kasutamiseks peaks viik olema sisendrežiimis ja PWM signaali genereerimiseks väljundrežiimis. Mõned perifeeriamoodulid määravad aga ise IO viigu režiimi.
Välised katkestused (inglise keeles external interrupt) on ühed lihtsaimad perifeeria funktsioonid. AVR-idel on tavaliselt 1 kuni 8 spetsiaalset viiku, mille loogilise väärtuse muutumisel või kindlal olekul tekitatakse programmis katkestus. Kuna enamasti kasutatakse seda funktsiooni kontrolleriväliste loogikasignaalide jälgimiseks, siis nimetataksegi vastavaid viike välise katkestuse viikudeks.
Välise katkestuse kasutamiseks tuleb viiku kasutada tavalises IO sisendrežiimis (võib ka väljundrežiimis kasutada, aga siis saab katkestust tekitada vaid kontroller ise). Välise katkestuse seadistusregistrites tuleb ära märkida, kas lubada katkestuste tekitamine ja mille peale seda teha. Võimalikke tekitajaid on neli:
Katkestuse tekitamiseks loogilise nulli valimisel tekitatakse katkestust järjest senikaua, kuni viigu väärtus on null, ja samal ajal põhiprogrammil töötada ei lasta.
Väliseid katkestusi on tööpõhimõttelt kahte liiki: kontrolleri taktiga sünkroniseeritud ja asünkroonsed. Sünkroniseeritud katkestused toimivad sisendite väärtuse meelespidamise teel, st et loogilised muutused leitakse kahel erineval taktil saadud väärtuste võrdlemise teel. Kui välise signaali loogilised muutused toimuvad kiiremini, kui käib töötakt, siis katkestused ei teki õigesti või ei teki üldse. Asünkroonsed katkestused ei sõltu kontrolleri taktist ja võimaldavad natuke kiiremini muutuvat välist signaali - loogilist nivood peab signaal hoidma vähemalt 50 ns. ATmega128-l on 4 sünkroniseeritud ja 4 asünkroonset välist katkestust.
Vaja on panna ATmega128 kesta viik number 9 ehk siini E viik 7 tekitama katkestust, kui selle väärtus muutub. Sellele viigule vastab väline katkestus INT7, mis on sünkroonne.
#include <avr/interrupt.h> // Välise katkestuse programm ISR(INT7_vect) { // Tee midagi } int main() { // Siini E viigu 7 muutmine sisendiks biti 7 nullimise teel DDRE &= ~(1 << PIN7); // Siini E viigule 7 pull-up takisti määramine sisendi ujumise vastu PORTE |= (1 << PIN7); // Väliste katkestuste seaderegistris katkestuse 7 // tekitajaks loogilise muutuse määramine EICRB = (1 << ISC70); // Välise katkestuse 7 lubamine EIMSK |= (1 << INT7); // Globaalne katkestuste lubamine sei(); // Lõputu programmitsükkel while (1) continue; }
Lisaks üksikute viikude tekitatavatele katkestustele on suurematel AVR-idel võimalik kasutada ka tervete gruppide viikude loogiliste väärtuste muutuste katkestusi. Neid katkestusi nimetatakse lihtsalt viigu muutuse katkestusteks (inglise keeles pin change interrupt). Rakenduvad nad siis, kui vähemalt ühe viigu väärtus grupis muutub.
Analoog-digitaalmuundur (inglise keeles analog to digital converter, lühend ADC) muundab analoogpinge väärtuse digitaalseks väärtuseks. AVR-i ADC analoogpinge sisend on lubatud 0-5,5 V piires. Digitaalne väärtus on 10-bitine, kuid selle täpsus on ±2 ühikut. Viga võib veelgi kasvada, kui kiibi toitepinget häirete eest ei kaitsta. ADC jaoks on AVR-il eraldi toite ja võrdluspinge viik. Eraldi toide on mürakindluse pärast ja see ei tohi kiibi toitepingest erineda rohkem kui 0,3 V. Võrdluspinge määrab maksimaalse digitaalse väärtuse. Ehk kui võrdluspinge on 3 V, siis sama pingega sisend annab väärtuseks 210 - 1 ehk 1023.
AVR ADC töötab võrdlusmeetodil (inglise keeles successive approximation). Lühidalt öeldes toimub mõõdetava pinge võrdlemine kindlate nivoopingetega ja tulemuste esitamine tõeväärtuste-, ehk bitijadana. See meetod võtab aga aega, sest iga biti leidmine lõppväärtuses toimub eraldi. AVR-il kulub töö ajal 13 takti ühe mõõtmise tegemiseks ja 25 takti kõige esimesel mõõtmisel (käivitusel). Need taktid pole aga kontrolleri töötaktid, vaid spetsiaalselt ADC üksuse jaoks sagedusjaguriga saadud. Maksimaalse täpsuse saamiseks peaks ADC takt olema 50-200 kHz. Kõrgemal taktil kaob täpsus, kuid vahel on ka mõõtmiste suur arv olulisem kui täpsus. Ühele mõõtmisele kuluvaks ajaks on AVR dokumentatsioonis antud 13-260 µs.
Mõõtetulemust saab kasutaja lugeda 8- ja 10-bitisena. Kuna AVR on 8-bitine, siis ADC mõõteväärtuste jaoks on sel kaks 8-bitist registrit. Seadistustes saab määrata, kas 10-bitisest väärtusest 2 esimest või 2 viimast bitti lähevad eraldi registrisse. Kui eraldatakse 2 noorimat ehk tulemust vähem iseloomustavat bitti, saab mõõtetulemuse 8-bitisena lugeda - sellist kombinatsiooni nimetatakse vasak-asetusega mõõtetulemuseks (left align). Teistpidist kombinatsiooni, kus kaht tulemusregistrit lugedes tekib 10-bitine arv, nimetatakse parem-asetusega mõõtetulemuseks (right align).
Mõõdetavaid analoogpinge sisendkanaleid on AVR-idel tavaliselt 8, ATtiny seerial üksikud, mõnel ATmega seeria kiibil 16, kuid muundureid on siiski üks. Erinevate sisendite kasutamiseks on kiibis multiplekser. Multiplekseri sisend on spetsiaalse registriga määratav. ADC üksusel on veel mõned omadused: muundamine protsessori magamisrežiimis müra vähendamiseks ja sisemise fikseeritud võrdluspinge (2,56 V, mõnel ka 1 V) kasutamise võimalus.
Vaja on mõõta ATmega128 ADC kanali 3 pinget vahemikus 0-5 V 8-bitise täpsusega.
#include <avr/io.h> int main() { unsigned char result; // Võrdluspingeks AREF viigu valimine // (eeldatavasti on see ühendatud +5V toiteahelasse) // Multiplekseriga kanali 3 valimine // Tulemus on vasak-asetusega ADMUX = (1 << REFS0) | (1 << ADLAR) | (3); // ADC üksuse käivitamine, teisendustakt 16 korda aeglasemaks töötaktist ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADSC); // Mõõtmise lõpetamise ootamine while (ADCSRA & (1 << ADSC)) continue; // 8-bitise tulemuse lugemine result = ADCH; }
Loendurid (inglise keeles counter), teatud mõttes taimerid (inglise keeles timer), on mikrokontrollerite ühed vajalikuimad lisafunktsioonid. Nende abil saab protsesse täpselt ajastada, signaale genereerida ja sündmusi loendada. Loenduri tööpõhimõte seisneb sisendtaktide arvu trigerite ahela abil binaarväärtuseks teisendamises. Ahela pikkusest oleneb maksimaalne loendatavate taktide arv, mida tähistatakse kahendkoodi pikkusega. AVR mikrokontrolleril on loendurid 8- ja 16-bitised. Kui loendur omab maksimaalset väärtust (8-bitiste puhul 255, 16-bitiste puhul 65535), tekib järgmise taktiga ületäitumine (inglise keeles overflow) ja loendur alustab uuesti nullist. Loenduri taktsignaal saab tulla mikrokontrolleri töötaktist ja sel juhul on võimalik selle sagedust sagedusjaguriga (inglise keeles prescaler) ka vähendada. Mõnel AVR-il on ka sisemine eraldiseisev taktsignaali generaator, mille sagedust saab sageduskordistiga tõsta. Sageduskordistiga on näiteks USB liidesega AVR-id. Loendurid erinevad ka rakendusvõimaluste ja töörežiimide poolest.
Loendurit, mille taktsignaal tuleb töötaktist ja mis ei ole väliselt millegagi liidestatud, võib nimetada tüüpiliseks loenduriks. Sel loenduril on lisaks hetkeväärtuse lugemisele vaid üks lisavõimalus - katkestuse tekitamine loenduri ületäitumisel. Tüüpilist loendurit või loendurit tüüpilises režiimis kasutatakse tavaliselt kindlate ajaintervallide järel mingi programmilõigu täitmiseks.
Vaja on 8 MHz taktsagedusel töötav ATmega128 10 ms (sagedus 100 Hz) ajavahemiku järel katkestust tekitama panna. Ülesandeks sobib 8-bitine loendur 0.
#include <avr/interrupt.h> // Loenduri 0 ületäitumine ISR(TIMER0_OVF_vect) { // Loendurile sellise väärtuse omistamine, // et järgmine ületäitumine saabuks 10 ms pärast. // Valem: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178 TCNT0 = 178; // Tee midagi, aga alles pärast loendurile uue väärtuse omistamist } int main() { // Kui esimest ületäitumise katkestust soovitakse ka 10 ms // pärast, tuleb loendur enne käivitamist algväärtustada. TCNT0 = 178; // Sagedusjaguri teguriks 1024 TCCR0 = 0x05; // Loenduri täitumise katkestuse lubamine TIMSK |= (1 << TOIE0); // Globaalne katkestuste lubamine sei(); // Lõputu programmitsükkel while (1) continue; }
Näites toodud loendurile omistatava väärtusega siiski täpselt 10 ms järel katkestust ei tekitata, sest vaja oleks loendurile omistada komakohaga väärtus, kuid see pole võimalik. Et täpset katkestuse intervalli saada, tuleb nii sagedusjaguri tegur kui loendurile täitumisel omistatav väärtus valida nii, et taktsagedus jaguks täpselt. Paraku pole see alati võimalik ja eriti just 8-bitise loenduri puhul, sest selle väärtuste skaala on üsna väike. Täpsema ja suurema intervalli tekitamiseks saab kasutada 16-bitist loendurit.
Kõik muud loendurid täiendavad tüüpilist loendurit. Seega kõigil loenduritel on tüüpilise loenduri tunnusjoon - ületäitumise katkestus.
Loenduri taktsignaalina saab kasutada ka mikrokontrollerivälist signaali (inglise keeles external clock source). Selleks on AVR mikrokontrolleril Tn viik, kus n tähistab loenduri numbrit. Välist taktsignaali ja polaarsust saab valida sagedusjaguri registriga. Välise taktika loenduril on muus osas samasugused omadused kui tüüpilisel loenduril.
Kuna loendurid võimaldavad mõõta aega, on keerukamatel AVR mikrokontrolleritel võimalus riistvaraliselt mõõta ka aega, mil toimus mingi sündmus. Seda loenduri osa nimetatakse sündmuse püüdjaks (inglise keeles input capture unit). AVR-is on valida kahe sündmuse vahel: spetsiaalse sisendviigu või analoogkomparaatori võrdlustulemuse loogilise väärtuse muutus. Kui toimub valitud sündmus, kirjutatakse loenduri väärtus spetsiaalsesse registrisse, kust selle võib soovitud ajal välja lugeda. Kui sündmuse toimumise aeg on pikem kui loenduri ületäitumise aeg, tuleb tarkvaraliselt lugeda ka loenduri ületäitumisi (näiteks ületäitumise katkestusega) ja need lõpptulemusse arvestada.
Vaja on 8 MHz taktsagedusel töötava ATmega128-ga mõõta välise 122 Hz - 100 kHz loogilise nelinurksignaali sagedust 1 Hz täpsusega. Programm on tehtud 16-bitise loendur 1 sündmuste püüdjaga.
#include <avr/interrupt.h> unsigned long frequency; // Sündmuse toimumise katkestus ISR(TIMER1_CAPT_vect) { // Loenduri nullimine esimese asjana TCNT1 = 0; // Tulemus on ainult siis arvestatav, kui // loendur pole vahepeal üle täitunud if (!(TIFR & (1 << TOV1))) { // Sageduse arvutamine perioodi pöördväärtusest. frequency = (unsigned long)8000000 / (unsigned long)ICR1; } else { // Sagedus on vähem kui 122 Hz frequency = 0; // Loenduri ületäitumise lipukese nullimine TIFR &= ~(1 << TOV1); } } int main() { // Tõusva frondi registreerimine, sagedusjaguri tegur 1 TCCR1B = (1 << ICES1) | (1 << CS10); // Sündmuse toimumise katkestuse lubamine TIMSK = (1 << TICIE1); // Globaalne katkestuste lubamine sei(); // Lõputu programmitsükkel while (1) continue; }
Programmis tekib välise signaali tõusva frondi ajal sündmuse katkestus. Katkestuse jooksul kontrollitakse, ega loenduri ületäitumine pole toimunud - see saab juhtuda kui signaali sagedus on alla 122 Hz (8 MHz / 216) ja sel juhul ei kajasta loenduri väärtus reaalset perioodi. Sagedus arvutatakse 32-bitiste arvudega pöördväärtusena perioodist. Esimese asjana aga nullitakse loendur, sest taimer töötab samal taktil mis protsessor ja iga instruktsiooni täitmine, mis toimub pärast välist sündmust, lühendab mõõdetavat perioodi ning sellest tulenevalt rikub ka mõõtetulemust. Maksimaalsele mõõdetavale sagedusele seab piiri katkestuse programmiosa tööaeg.
Sündmuste püüdmist ning nende aja registreerimist saab teha ka tarkvaraliselt. Saab kasutada väliseid või muid katkestusi ja nende tekkimise ajal lugeda loenduri väärtuse. Kuid riistvaraline sündmuste püüdmine on mõeldud eeskätt siiski programmist sõltumatuks töötamiseks ja suhteliselt lühiajaliste (või tihedate) sündmuste mõõtmiseks.
Peale signaali pikkuse mõõtmise saab keerukamate loenduritega ka signaali tekitada. Selleks on loenduril väärtuse võrdlemise üksus (inglise keeles output compare unit) ja võrdlustulemuse väljastusüksus (inglise keeles compare match output unit). Võrdlusüksusesse kuuluvad registrid sama bitilaiusega kui loendur ise ja mille väärtusi võrreldakse loenduri väärtusega selle töö ajal. Hetkel, mil loenduri väärtus saab võrdseks võrdlusüksuse registri väärtusega, saab tekitada katkestuse ja spetsiaalsete väljundviikude oleku muutuse. Väljundviigu oleku muutused tekitavadki signaali.
Väljastusüksuses on võimalik seadistada väljundviikude käitumist võrdusmomendil. Valida on viigu kõrgeks muutmise, madalaks muutmise ja ümbermuutumise vahel. Nende täpsem toime aga sõltub sellest, millist signaali genereerimise režiimi kasutada. Kui kasutusel on PWM signaali tekitamise režiim (järgmine peatükk), siis viik muutub loenduri täitumisel kas madalaks või kõrgeks, vastupidiselt sellele, mida viik teeb võrdusmomendil.
Mõnedel signaali genereerimise režiimidel on määratav ka loenduri suurim väärtus - loenduri füüsiline suurus jääb küll samaks, kuid mängus on võrdlusregister, mille väärtust ületades loendur nullitakse. Seda võimalust kasutades saab eespool toodud ülesandeid täpse ajalise katkestuse tekitamise kohta lahendada, kuid mõeldud on see pigem signaali perioodi muutmiseks. Vähe sellest - mõnes režiimis toimib loendur juurde ja maha lugedes.
Loendurid ja eriti just nende signaali genereerimise režiimid on ühed keerulisemad perifeeriamoodulid AVR-il. Kõigist neist kirjutamine läheks pikaks ja enamasti pole nende juures vaja ka kõike teada. Seetõttu on järgnevalt kirjeldatud vaid üht levinuimat PWM signaali robootikas. Ülejäänut saab juba AVR dokumentatsioonist järgi uurida.
Pulsilaius-modulatsioon (inglise keeles pulse width modulation, lühend PWM) on signaali tüüp, mille sagedus ja ühtlasi ka perioodid on konstantne (enamasti), kuid mõlema poolperioodi pikkus on muutuv. PWM signaale kasutatakse elektromehaaniliste, optiliste jms. seadmete juhtimiseks. Näiteks mudelismist tuntud servomootorite PWM signaal on 50 Hz sagedusega ja 1 ms kuni 2 ms pikkuse kõrge poolperioodiga.
Vaja on 8 MHz taktsagedusel töötava ATmega128-ga genereerida kaks kiirusreguleeritavate servomootorite signaali. Viiguga PB5 (OC1A) tuleb genereerida pulsipikkus 1 ms ja viiguga PB6 (OC1B) pulsipikkus 2 ms.
#include <avr/io.h> int main() { // Viigud väljundiks DDRB |= (1 << PIN5) | (1 << PIN6); // Väljundid A ja B võrdusmomendil madalaks, // "Fast PWM" režiim, sagedusjagur 8 TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11); TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11); // Suurim loenduri väärtus. Valem: // TOP = 8 MHz / 8 / 50 Hz ICR1 = 20000; // Esimese mootori poolperiood 1 ms, teisel 2 ms OCR1A = 1000; OCR1B = 2000; // Lõputu programmitsükkel while (1) continue; }
USART on universaalne sünkroonne jadaliides, UART aga selle lihtsustatud variant - universaalne asünkroonne jadaliides. Vahe seisneb selles, et USART kasutab peale andmeliinide ka taktsignaali liini, millega andmeid sünkroniseeritakse, UART mitte. AVR-i USART võimaldab täisdupleks-sidepidamist, 5- kuni 9-bitiseid andmesõnu (8 biti puhul sõna = bait), 1 või 2 stoppbitti, kolme paarsuse režiimi ja laia boodikiiruste valikut. AVR mikrokontrolleritel on üldiselt kuni 2 USART liidest, mõnel see ka puudub. Andmete edastamine toimub sõna kaupa, ehk AVR teeb riistavara tasandil kasutaja edastatud sõna bittideks ja edastab selle iseseisvalt ning vastupidi. Kasutaja juhib USART tööd seade-, oleku- ja andmeregistreid kirjutades ning lugedes.
Kõikide seadistuste jaoks on olemas vastavad registrid, mida on üsna lihtne andmelehe abil seadistada. Natuke keerulisem on boodikiiruse seadmine. Taktsignaal andmete edastamiseks genereeritakse töötaktist ja kasutaja saab valida teguri 1-st 4096-ni, millega töötakt läbi jagatakse. Täiendavalt jagatakse saadud taktisignaali olenevalt režiimist veel 2, 8 või 16-ga. Probleem on selles, et kõiki taktsagedusi ei saa jagada nii, et tekiks standardne boodikiirus. Mõnede mikrokontrolleri taktsageduste puhul on boodikiiruse erinevus soovitust ligikaudu 10%. AVR andmelehtedes on toodud tabelid tüüpilistest taktsagedustest, boodikiirustest ja nende saamiseks vajalikust jagamistegurist ning tekkida võivast veast.
Kuna andmete edastus toimub protsessorist sõltumata ja oluliselt aeglasemalt, tuleb enne saatmist veenduda, et liides on valmis uut sõna edastama. Selleks tuleb jälgida saatepuhvri valmisoleku olekubitti, mis näitab, kas sinna võib saatmiseks uue sõna kirjutada või mitte. Kui mikrokontroller käivitada, on see luba vaikimisi kohe olemas. Niipea kui sõna on saadetud ja puhvrisse pole uut sõna saatmiseks kirjutatud, muudetakse kõrgeks saatmise õnnestumise olekubitt.
Sõna saabumist tähistab samuti spetsiaalne olekubitt. Lisaks on olekubitid vastuvõtmisel tekkiva kaadri vea, paarsuse vea ja vastuvõtja puhvri ületäitumise tähistamiseks. Puhvri ületäitumine tekib näiteks siis, kui eelmist saabunud sõna pole vastuvõtu puhvrist välja loetud - seepärast on oluline saabuvad sõnad kiiresti programmi lugeda, näiteks katkestusega. Kokku on kolm võimalikku katkestuse põhjust: saatepuhvri valmisolek, saatmise õnnestumine ja vastuvõtmise õnnestumine.
Muide, saatepuhver ja vastuvõtupuhver on füüsiliselt küll erinevad registrid, kuid jagavad nad sama mäluaadressi ja neil on ühine nimi. Ühine andmeregister toimib nii, et sellesse kirjutades jõuab sõna saatepuhvrisse ja sellest lugedes tuleb see vastuvõtupuhvrist. Veel ühe täpsustusena tuleks arvestada, et 9-bitiste andmesõnade puhul edastatakse ja loetakse üheksandat bitti hoopis ühe seaderegistri kaudu.
Seadistada 8 MHz taktsagedusel töötav ATmega128 USART0 liides boodikiirusel 9600 bps asünkroonselt edastama 8-bitiseid sõnu 1 stopp-bitiga ja ilma paarsuse bitita. Saata märk “X”.
#include <avr/io.h> int main() { // Boodi kiiruseks 9600 bps seadmine. Valem: // Jagamistegur = taktsagedus / 16 / boodi kiirus - 1 // UBRR = 8000000 / 16 / 9600 - 1 = ~51 UBRR0H = 0; UBRR0L = 51; // Saatja lubamine UCSR0B = (1 << TXEN0); // Asünkroonse režiimi seadistamine, andmesõna pikkuseks 8 bitti // 1 stop-bitt, keelatud paarsuse bitt. UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Ootame kuni andmepuhver on tühi ehk eelmine sõna on saadetud // Selles näites ei oma see küll erilist mõtet, sest saadetakse // alles esimest märki, kuid seda tasub teha rohkemate korral. while (!(UCSR0A & (1 << UDRE))) continue; // Märgi kirjutamine puhvrisse, kust see ka teele saadetakse. UDR0 = 'X'; // Lõputu tsükkel while (1) continue; }
Mehhatroonika ja Robootika Kodulabor on ATmega128 mikrokontrolleril põhinev omavahel seotud moodulite komplekt, mis on komplekteeritud kaasaskantavasse kohvrisse. Kodulaboriga saab teha erinevaid mehhatroonika- ja robootikaalaseid eksperimente ja harjutusi alates lihtsast tule vilgutamisest kuni keeruka seadme ehitamiseni. Kodulabor on mõeldud eelkõige koolidele, sisaldades endas lisaks riistvarale ka metoodilist materjali ja harjutusülesandeid koos näidete ja lahendustega. Kodulabor on integreeritud oma veebikeskkonnaga, mis on suunatud õpilasele ja õpetajale ning võimaldab kasutajate omavahelist suhtlust. Lühidalt öeldes on kodulabor mobiilne töövahendite komplekt, mida kasutatakse õppe ja harjutamise eesmärgil kodus, koolis või töökohal.
Kodulabor on välja arendatud Tallinna Tehnikaülikooli ja Eesti ettevõtte poolt koostöös Euroopa partnerülikoolidega Leonardo da Vinci programmi toel. Kodulabori moodulid on komplekteeritud erinevatesse komplektidesse. Lihtsaim komplekt, millega saab teha esmaseid digitaalsete sisendite-väljundite eksperimente, on Kodulabori baaskomplekt. Andurite ja mootoritega eksperimenteerimiseks on vaja Andurite ja Mootorite lisakomplekti. Täiskomplekt sisaldab endas nii Kodulabori baaskomplekti, Andurite ja Mootorite lisakomplekti kui ka lisamooduleid.
Kodulabori baaskomplekti ja täiskomplekti saab edukalt kasutada lisaks eksperimentidele ka robotiehitamise baasplatvormina või muu mehhatroonikasüsteemi keskse juhtsüsteemina. Kodulabori versioonid on pidevas arengus ja aeg-ajalt tasub kontrollida, kas on ilmunud lisamooduleid või uuendusi. Samuti tasub kontrollida moodulite versiooni numbreid, mõningad harjutused ja näited võivad olla koostatud uuematele versioonidele. Oluline lisaväärtus Kodulaboril on tema veebiversioon Kauglabori näol. Kauglabor võimaldab Kodulabori riistvaraplatvormi kasutada läbi veebi.
Kodulabori veebikeskkond
http://home.roboticlab.eu
Kauglabori veebikeskkond
http://distance.roboticlab.eu
Tänapäevane inseneriõpe ei saa enam põhineda ühel konkreetsel õppeviisil, ammugi mitte enam klassikalisel ülikooli loeng-harjutus-tüüpi standardlahendusel. Tänapäeva õppija ei rahuldu enam rangelt ajastatud laboritundidega. Enamik noori (ja ka vanemaid õppijaid) elavad infoühiskonna täisväärtuslikku elu ja viidavad suure osa oma ajast Internetis, mis tähendab, et klassikaliste meetoditega õppimisele jääb järjest vähem aega. Selle tõttu tuleb inseneriõpe tuua samuti üle infoühiskonda ja teha see atraktiivseks kaotamata sama ajal kvaliteedis ja praktilise töö osakaalus.
Mehhatroonika ja robootika integreeritud õppe kontseptsioon sisaldab endas nii standardseid õppeabimaterjale kui ka uudseid lähenemisi, mis on metoodiliselt seotud ühtseks tervikuks.
Alljärgnev näide võib olla abiks koolile robootika õppesüsteemi käivitamiseks kui ka ideedeks rakendada erinevaid õppevõimalusi tehnikavaldkonna praktiliseks õppeks.
Õppe kontseptsioon sisaldab endas järgnevaid õppeabimaterjale:
Teoreetilised abimaterjalid koosnevad traditsioonilisest õpik-käsiraamatust ja harjutusülesannete kogust.
Praktiline osa koosneb Kodulaborist ja üle Interneti robotite programmeerimise keskkonnast - Kauglaborist. Kodulaborid moodustavad Kauglaboriga ühtse terviku, mis tähendab, et õppija saab kodus harjutada üksikuid funktsioone nagu näiteks, kuidas juhtida erinevaid mootoreid või kasutada andureid ja samal ajal on võimalus üle Interneti oma värskeid oskusi rakendada süsteemi juhtimiseks. Süsteemiks on reaalne seadmestik (näiteks mobiilne robot), mida saab programmeerida ja juhtida Kauglabori vahendusel. Robot on ehitatud samadest komponentidest, mis sisalduvad Kodulaboris, võimaldades nii omandatud oskusi kohe ka terviksüsteemi peal proovida. Roboti liikumisest ja tegemisest saab tagasisidet videokaamerate abil.
Õppeprotsessi ühe teema/laboritöö raames kirjeldab allolev skeem.
Teema algab sissejuhatava loenguga, mis võib toimuda klassikalise kontakttunnina, kaugloenguna (juhul kui õpetaja on eemal) või videoloenguna. Videoloeng on oluline ka juhul, kui toimub tavaloeng, võimaldades nii puudunud õpilastel loengumaterjalist osa saada või ka osalenud õpilastel soovi korral loengut üle vaadata. Teemat tutvustav loeng sisaldab endas praktilise näite koos läbi tegemist ja õppetajapoolset kommenteerimist. Teoreetilist osa toetab õpik ja harjutuste kogu teoreetiline osa.
Teema tutvustusele järgneb iseseisev praktiline töö. Praktiline töö koosneb näitelahenduse katsetamisest, selle muutmisest vastavalt “Soojendusülesandele” ja iseseisvast harjutusülesandest, mille määrab õpetaja praktiliste tööd “Harjutusülesannete” osast. Praktiline töö teostatakse Kodulaboriga või mõne muu robootika komplektiga, mida toetab käesolev harjutuste kogu, Kauglabor ja veebikeskkond. Olulisel kohal on siinjuures õpetajate ja õpilaste tugikeskkond ja võrgustik, mis peaks iseseisvale tööle igakülgset abi pakkuma. Foorumis saab küsida abi kaasõpilastelt ja ka juhendajatelt.
Praktilise harjutuse tulemused vormistatakse aruandeks ja saadetakse õpetajale või, kui kasutusel on e-õppe süsteem, laetakse koos töötavate masinkoodis lahendustega vastavasse süsteemi. Aruanne sisaldab tüüpiliselt töö kirjeldust ja lahenduse lähtekoodi, mis PEAB olema selgelt ja arusaadavalt kommenteeritud.
Ei ole mingi uudis, et infotehnoloogia tungimine igapäevaellu on muutnud paljude, kui mitte enamuse noorte õppimise stiili ja kommunikatsioonikanaleid. Tõenäoliselt saab õppija juba praegu olulise osa õpitava aine informatsioonist erinevate infotehnoloogia kommunikatsioonikanalite kaudu. Enne mingi probleemi lahendamist tehakse tihti kiire otsing internetist, leidmaks taustainformatsiooni või näitelahendusi. Kuna noorte igapäevasuhtlus ja tegevus on igati põimunud internetiga ja seal olevate erinevate võrgustikega, on igati loomulik, et koolitaja poolt pakutav õpetamismetoodika peab järgima üldisi trende ja leidma tee õppijani läbi tema poolt harjumuspärase suhtluskanali - interneti. Loomulikult ei välista interneti kasutamine traditsioonilisi õpetamise vorme, kuid ainuüksi nendest enam ei piisa.
Robootika ja mehhatroonika on tulevikku suunatud alad, mille õpetamisel tuleb samuti järgida tänapäeva trende ja uusi tehnoloogiaid. Samal ajal aga on see valdkond väga praktiline ja nõuab oskuste ning teadmiste omandamiseks praktilist katsetamist ja harjutamist. Kuigi on olemas ka virtuaalseid ülesandeid, ei asenda see praktilisi oma käega tehtud tegevusi. Järgnevalt püüame pakkuda ühe võimaliku praktilise juhendi, kuidas viia läbi ühte robootika ainet, kus on kasutusel erinevaid õpetamise vorme integreeriv lähenemine. Metoodika eeldab, et õpetajal on võimalus kasutada modulaarset praktilist robootika õppekomplekti, antud juhul Kodulaborit.
Mida pidada silmas õppeaine alustamisel….
Optimaalse õpilaste arvu laborikomplektiga tegutsemiseks määrab suuresti ära juba arvutikasutamise piirang. See tähendab, et ühe arvuti taha mahub enamasti kuni 3 inimest, nii et veel kõik saavad arvutis toimuvast aktiivselt osa võtta. Suurema arvu juures ei näe osa õpilasi enam kirjutatavat koodi, nii et neil hakkab igav ning tunnitööga enam ei tegeleta.
Praktiline töö on jagatud laboritöödeks, kus iga labori juures tuleb lahendada ülesanne programmiliselt ning tulemus vormistada aruandena. See võimaldab tööd õpilaste vahel jagada. Näiteks üks vastutab programmikoodi eest, teine aruande kirjutamise eest, kolmas riistvara ühendamise eest. Aruandes endas võib nõuda näiteks lisaks programmikoodile ka lahenduse kirjeldust tekstina, kasutatava algoritmi lahtiseletavat diagrammi, vastuseid käsitletud teema kohta käivatele küsimustele ja õpilaste nägemust labori plussidest ja miinustest. Viimane on hea võimalus uurida õpilaste tagasisidet sellest, kas ülesanne oli liiga keeruline või lihtne, kui praktiline või huvitav ülesanne tundus, mida õpiti juurde jms.
Kindlasti tasub laborikomplekti käsitlev esimene programmeerimisülesanne koos läbi teha. Samaaegselt õpetajaga, kes selgitab toimingute tausta ja lahendab ülesannet ekraanil, teevad õpilased demonstreeritud ülesannet koos kaasa. Kogu protsess võiks olla ka kirja pandud etapiliselt, et mahajääjad või puudujad saavad juhendi järgi võimalusel ka ise tegutseda. Labori läbiviimise üks võimalik variant on järgnevalt välja toodud etappidena, mis omakorda võivad ka varieeruda.
Ülesannete lahendamisel võib alati tekkida grupp (grupid), kes on teistest aeglasem või alustasid hiljem. Sellisel juhul on tavaliselt probleemiks õpetaja tähelepanu koondumine mahajäänud grupi abistamisele ning teised peavad ootama ja igavlema, kuni mahajääja grupp on järele jõudnud. Analoogselt tekib probleem, kui klassis on üks grupp, kes jõuab töödega valmis teistest kiiremini. Mõlema probleemi lahendamiseks on võimalus kasutada kirjapandud ülesandeid või laborijuhendeid. Kuna kogu töö protsess ja nõutud osad on kirja pandud, siis saavad grupid töötada iseseisvalt ning õpetajal on võimalus abistada neid, kellel tekib probleeme edasijõudmisega. Lisaks on erineva raskusastmega ülesandeid, mida saab jagada vastavalt grupi võimekusele või boonusülesandena nendele, kes on normülesanded juba ära jõudnud lahendada.
Kui õpetaja peab oluliseks, et kõik oskaksid programmeerida ning saaksid programmikoodist aru, siis võib õpetaja nõuda, et õpilased vahetaksid teatud osaülesande järel kohad, nii et igaüks saaks proovida programmeerimist. Teine võimalus on ülesande hindamisel küsida programmikoodi lahenduse kohta selgitust ükskõik milliselt grupi liikmelt ning viimase vastus määrab kogu grupiliikmete hinde. See sunnib gruppi töötama ühtsena ning hoolitsema, et kõik grupi liikmed saaksid aru, kuidas lahenduse üksikasjad töötavad. Kui selline lähenemine tundub ebaõiglasena, võib iseseisva töö kaitsmise organiseerida nii, et grupp peab lahendama õpilaste arvuga võrdse arvu töid. Iga õpilane peab kaitsma ühe töö. Millise, selgub alles kaitsmise käigus.
Tihtipeale võivad programmi koodi kompileerimisel või riistvara valesti käsitlemisel tekkida mingid tüüpvead. Nende sümptomid tasub kindlasti kirja panna koos lahendusega, kuna sama viga, millele lahenduse leidmine võttis tunde, võidakse õpilaste poolt korrata. Tüüpprobleemide lahendused saab koondada Kodulabori tugikeskkonna foorumisse.
Motivatsiooni tõstmiseks ja kogu õppeprotsessi huvitavamaks muutmiseks on üks võimalus tekitada võistlusmoment, kus õpilastel tuleb mingile probleemile leida lahendus, mida kursuse lõpus ühiselt testitakse. Lahenduse headus peab olema mõõdetav (aeg, kaugus vms.). Võib tekitada ka erinevaid hindamiskriteeriume, nn. väljanägemine, optimaalne lahendus, huvitavaim tehniline lahendus jms. Ülesannet annab kindlasti siduda ka reaalse elu probleemidega (nt patareide sorteerija). Samas on võimalus kasutada ka mobiilseid platvorme, et lahendada hobirobootika tüüpülesandeid nagu joonejälgimine, labürindi läbimine jms.
Järgnevalt on toodud näiteks tüüpiline laboritöö kirjeldus, mida võib kasutada praktilise töö lähteülesandena.
Laboratoorne töö Nr 3. Andurid ja analoog-digitaalmuundur
Juhendaja: Raivo Sell
Töö eesmärk
Tutvuda analoog-digitaalmuunduri tööpõhimõtte ja analoogsignaalide muundamisega, kasutades AVR ATMega128 8-bitist mikrokontrollerit. Lisaks tutvuda erinevate analoogväljundiga anduritega. Teha läbi lihtne harjutus analooganduri kasutamisest.
Tööks vajalikud vahendid
Kodulabori baasversioon, Andurite ja Mootorite lisakomplekt, AVR tarkvara.
Töö käik
Aruanne
Tehtud töö kohta tuleb esitada elektrooniline aruanne, mis sisaldab:
Aruanne peab sisaldama nime, labori numbrit, teostamise kuupäeva, kaasosaliste nimesid (kui olid). Aruanne peab olema lühike, kuid sisutihe. Hinnatakse kvaliteeti, mitte kvantiteeti! Olge valmis lahenduse demonstreerimiseks juhendajale ja Teie poolt loodud programmikoodi kommenteerimiseks. Aruanded laadida üles e-õppe keskkonda vastava ülesande juurde. Labori aruande esitamise tähtaeg on 1 nädal pärast töö tegemist.
Kirjandus
Robootika Kodulabori moodulid on jagatud erinevatesse komplektidesse, võimaldades valida sobivaima sõltuvalt õpilase või kooli eesmärkidest. Lihtsaim komplekt on Kodulabori baaskomplekt, mis sisaldab endas kõike vajalikku mikrokontrolleri kasutamiseks ja lisaks Digitaal-sisend/väljundite plaati koos LCD ekraaniga. Baaskomplektiga saab kasutada Mootorite ja Andurite lisakomplekti, mis sisaldab erinevat tüüpi mootoreid, andureid ja nende tarvikuid. Lisakomplekt töötab koos Kodulabori baaskomplektiga. Iseseisvalt lisakomplekti kasutada ei saa, kuna see ei sisalda mikrokontrollerit. Kodulabori täiskomplekt sisaldab endas Kodulabori baaskomplekti ja Andurite ja Mootorite lisakomplekti täies mahus ning lisaks veel kolme moodulit, milleks on Kommunikatsioonimoodul, RFID moodul ja Masinnägemise moodul. Täiskomplekt sobib rohkem õpetajale. Õpilastele ja kaasaskandmiseks on olulisel mugavam ja mõistlikum kasutada Kodulabori baaskomplekti üksi või koos Andurite ja Mootorite lisakomplektiga.
Sisaldab kõiki komponente Kodulabori baaskomplektist ja Andurite ja Mootorite lisakomplektist ning lisaks järgmisi mooduleid:
Kodulabori keskseks mooduliks (Kontrollermooduliks) on arendusplaadile paigaldatud mikrokontroller ATmega128. Lisaks mikrokontrollerile on plaadil veel mitmesuguseid perifeeriaseadmeid, pingealaldi ja ühenduspistikud. Kontrollermooduli plaat sisaldab endas järgmisi komponente:
Kontrollermooduli plaat on varustatud alaldiga ja pingestabilisaatoriga. Sisendpingeks sobib plaadile 6-15 V. Voolukadude minimeerimiseks on soovitatav kasutada 6-9 V pingeallikat. Toite ühendamisel peab plaadil toite LED põlema hakkama. Kui see ei sütti, võib põhjus olla puudulikus toites, ühendamata jäänud toite-jumperis (toitepesa kõrval) või hoopis lühises Kontrollermooduli plaadil või temaga ühendatud seadmes. Mikrokontrollerit saab programmeerida nii ISP kui JTAG liidese kaudu. Kodulabori komplektiga kaasasolev JTAG-ICE programmaator toetab lisaks lihtsale programmi pealelaadimisele ka programmikoodi silumist. JTAG-ICE programmaatorit võib kasutada ka ISP režiimis. Programmeerimise viigud on ühendatud läbi multiplekseri, mis võimaldab kontrolleril töö ajal vastavaid viike kasutada ka teiste funktsioonide jaoks.
Kontrollermooduli plaat on varustatud oleku-LED-iga, mis on ühendatud mikrokontrolleri viiguga PB7. LED süttib, kui viik seada madalasse olekusse (loogiline 0). Seda on hea kasutada lihtsa indikaatorina. ATmega128 mikrokontroller on varustatud kahe jadaliidesega, mille signaalid on MAX232 muunduriga teisendatud RS-232 nivoole. Ühe jadaliidese (UART1) jaoks on standardne RS-232 DB-9 pistik, teise jaoks piikriba.
Plaadil on olemas lisaks veel eraldi 4 Mb Atmel AT45DB041B välkmälu. Mälu on ühendatud SPI liidese kaudu mikrokontrolleriga ja seda võib kasutada andmete salvestamiseks, juhul kui need peavad säilima ka pärast toite eemaldamist mikrokontrollerilt.
Nr | Viik | Alternatiivfunktsioon / kirjeldus | |
---|---|---|---|
1 | PD7 | T2 | Taimer/Loendur2 taktsignaali sisend |
2 | PD6 | T1 | Taimer/Loendur1 taktsignaali sisend |
3 | PD5 | XCK1 | USART1 taktsignaali sisend/väljund |
4 | PD4 | IC1 | Taimer/Loendur1 sündmuste püüdja sisend |
5 | PD3 | INT3/TXD1 | Väline katkestus 3 või UART1 andmete väljund |
6 | PD2 | INT2/RXD1 | Väline katkestus 2 või UART1 andmete sisend |
7 | PD1 | INT1/SDA | Väline katkestus 1 või TWI andmesignaal |
8 | PD0 | INT0/SCL | Väline katkestus 0 või TWI taktsignaal |
9 | VCC | - | +5 V |
10 | GND | - | Maa |
11 | PB7 | OC2/OC1C | Taimer/Loendur2 või Taimer/Loendur1 võrdlustulemuse väljastusüksus (C) |
12 | PB6 | OC1B | Taimer/Loendur1 võrdlustulemuse väljastusüksus B |
13 | PB5 | OC1A | Taimer/Loendur1 võrdlustulemuse väljastusüksus A |
14 | PB4 | OC0 | Taimer/Loendur0 võrdlustulemuse väljastusüksus |
15 | PB3 | MISO | SPI master andmete sisend / SPI slave väljund |
16 | PB2 | MOSI | SPI master andmete väljund / SPI slave sisend |
17 | PB1 | SCK | SPI taktsignaal |
18 | PB0 | SS | SPI slave valik |
19 | PE7 | INT7/IC3 | Väline katkestus 7 või Taimer/Loendur3 sündmuste püüdja sisend |
20 | PE6 | INT6/T3 | Väline katkestus 6 või Taimer/Loendur3 taktsignaali sisend |
21 | PE5 | INT5/OC3C | Väline katkestus 5 või Taimer/Loendur3 võrdlustulemuse väljastusüksus C |
22 | PE4 | INT4/OC3B | Väline katkestus 4 või Taimer/Loendur3 võrdlustulemuse väljastusüksus B |
23 | PE3 | AIN1/OC3A | Komparaatori negatiivne sisend või Taimer/Loendur3 võrdlustulemuse väljastusüksus A |
24 | PE2 | AIN0/XCK0 | Komparaatori positiivne sisend või USART0 taktsignaali sisend/väljund |
25 | PE1 | PDO/TXD0 | ISP Programmeerimisliidese väljund või UART0 andmete väljund |
26 | PE0 | PDI/RXD0 | ISP Programmeerimisliidese sisend või UART0 andmete sisend |
Nr | Viik | Alternatiivfunktsioon / kirjeldus | |
---|---|---|---|
1 | GND | - | Maa |
2 | VCC | - | +5 V |
3 | PA0 | AD0 | Välismälu-liidese aadressi- ja andmebitt 0 |
4 | PA1 | AD1 | Välismälu-liidese aadressi- ja andmebitt 1 |
5 | PA2 | AD2 | Välismälu-liidese aadressi- ja andmebitt 2 |
6 | PA3 | AD3 | Välismälu-liidese aadressi- ja andmebitt 3 |
7 | PA4 | AD4 | Välismälu-liidese aadressi- ja andmebitt 4 |
8 | PA5 | AD5 | Välismälu-liidese aadressi- ja andmebitt 5 |
9 | PA6 | AD6 | Välismälu-liidese aadressi- ja andmebitt 6 |
10 | PA7 | AD7 | Välismälu-liidese aadressi- ja andmebitt 7 |
11 | - | - | Pole ühendatud |
12 | - | - | Pole ühendatud |
13 | PG2 | ALE | Välismälu-liidese aadressi lukustussignaal |
14 | - | - | Pole ühendatud |
15 | PC6 | A14 | Välismälu-liidese aadressi- ja andmebitt 14 |
16 | PC7 | A15 | Välismälu-liidese aadressi- ja andmebitt 15 |
17 | PC4 | A12 | Välismälu-liidese aadressi- ja andmebitt 12 |
18 | PC5 | A13 | Välismälu-liidese aadressi- ja andmebitt 13 |
19 | PC2 | A10 | Välismälu-liidese aadressi- ja andmebitt 10 |
20 | PC3 | A11 | Välismälu-liidese aadressi- ja andmebitt 11 |
21 | PC0 | A8 | Välismälu-liidese aadressi- ja andmebitt 8 |
22 | PC1 | A9 | Välismälu-liidese aadressi- ja andmebitt 9 |
23 | PG0 | WR | Välismälu kirjutussignaal |
24 | PG1 | RD | Välismälu lugemissignaal |
25 | - | - | Pole ühendatud |
26 | - | - | Pole ühendatud |
Nr | Viik | Alternatiivfunktsioon / kirjeldus | |
---|---|---|---|
1 | VCC | - | +5 V |
2 | GND | - | Maa |
3 | REF | AREF | ADC võrdluspinge sisend |
4 | GND | - | Maa |
5 | PF0 | ADC0 | ADC sisendkanal 0 |
6 | GND | - | Maa |
7 | PF1 | ADC1 | ADC sisendkanal 1 |
8 | GND | - | Maa |
9 | PF2 | ADC2 | ADC sisendkanal 2 |
10 | GND | - | Maa |
11 | PF3 | ADC3 | ADC sisendkanal 3 |
12 | GND | - | Maa |
13 | PF4 | ADC4/TCK | ADC sisendkanal 4 või JTAG taktsignaal |
14 | GND | - | Maa |
15 | PF5 | ADC5/TMS | ADC sisendkanal 5 või JTAG režiimivalik |
16 | GND | - | Maa |
17 | PF6 | ADC6/TDO | ADC sisendkanal 6 või JTAG andmete väljund |
18 | GND | - | Maa |
19 | PF7 | ADC7/TDI | ADC sisendkanal 7 või JTAG andmete sisend |
20 | GND | - | Maa |
Kontrollermooduli ühendamisel teiste moodulite ning seadmetega on esimeseks ja viimaseks tegevuseks toite eemaldamine ja ühendamine. Ajal kui plaat on pingestatud, on ohtlik seadmeid ühendada. Mooduleid ja seadmeid tuleb omavahel ühendada ettevaatlikult ja liigset jõudu kasutamata, kuna ribakaabliga võib vale käsitlemise tulemusena kontaktid kergesti kõveraks painutada. Programmaatori ühendamisel veenduge, et kaabel saaks õiget pidi. JTAG-ICE programmaatori puhul on ribakaabel suunatud plaadist eemale (punane triip toitepesa pool).
Digitaalne sisend-väljundmoodul on mõeldud lihtsamateks harjutusteks ja elementaarseks protsessi juhtimiseks. Moodulil on kolm nupp-lülitit ja kolm valgusdioodi (LED) mida saab kasutada AVR sisend-väljundviikudega. Lisaks lihtsatele valgusdioodidele on moodul varustatud ka LED numberindikaatoriga ja LCD ekraanide väljunditega. Digitaalset moodulit on mugav kasutada koos teiste moodulitega, võimaldades juhtida näiteks mootoreid ja kuvada andurite lugemeid. Moodul on varustatud:
Digitaalne sisend-väljundmoodul on Kontrollermooduli plaadiga ühendatud ühe ribakaabliga porti PA/PC/PG, mis koondab endas 8-viigulisi porte PA ja PC ning 3-viigulist porti PG. Lisaks saab moodul ribakaabli kaudu ka toite (+5 V). Kui moodul on õigesti ühendatud, peab moodulil olev väike roheline LED +5V_OK põlema minema. Kui LED ei sütti, võib põhjuseks olle ribakaabli vale ühendamine.
Moodul on varustatud kolme nupuga: S1, S2 ja S3, mis on ühendatud vastavalt PC0, PC1, PC2 viikudega. Nuppude teine ots on läbi kaitsetakistite ühendatud maaga (loogiline 0). Moodulil olevad 5 mm LED-id: LED1, LED2 ja LED3 on ühendatud vastavalt PC3, PC4 ja PC5 viikudega. LED-ide teine ots (anood) on ühendatud toitega (loogiline 1).
Digitaalne sisend-väljundmoodul on varustatud ühe 7-segmendilise numberindikaatoriga, mis on ühendatud kolme mikrokontrolleri väljundviiguga läbi ajuri A6275. Ajuri andmesignaal (S-IN) on ühendatud viiga PC6, taktisignaal (CLK) viiga PC7 ja lukustussignaal (LATCH) viiguga PG2.
Digitaalmooduli plaadil on eraldi välja toodud port PA. See on ühendatud samaaegselt kahte erinevasse viikude gruppi, kus esimene grupp on ühendatud läbi nivoomuunduri, võimaldades ühendada 3,3 V pingel töötavaid seadmeid (näiteks graafiline LCD) ja teine grupp on ühendatud otse porti PA (5 V nivoo) ning on joondatud vastavalt standardse tekstilise LCD viikude järgi. Eraldi on välja toodud port PG kaks kasutamata viiku - PG0 ja PG1, kuhu on võimalik ühendada lisaseadmeid, nagu näiteks ultraheli andur (alates mooduli versioonist 3.3). NB! Ultraheli anduri ühendamisel jälgida toite ja signaali kaablite viike, mida ei tohi omavahel segamini ajada. Signaali kaabel tuleb ühendada viikudega, mis on plaadil tähistatud 1 ja 2. Toitekaabel tuleb ühendada nii, et anduri maa (must juhe) oleks ühendatud plaadil oleva maa viiguga, mis on tähistatud märgiga GND.
Mooduli ühendamine on soovitatav teostada alltoodud järjekorras. Enne ühendamist veenduda, et Kontrollermooduli toide oleks lahti ühendatud.
LCD moodul on moodul, mis hõlmab endas Digitaalse sisend-väljundmooduli ühendusi ja erinevat tüüpi LCD ekraane. Digitaalse mooduli külge on võimalik ühendada 5 V nivool töötavaid alfabeetilisi LCD ekraane ja 3,3 V nivool töötavaid graafilisi LCD ekraane (alates Digitaalmooduli versioonist 3.2). Alfabeetilise ekraani kontrastsuse reguleerimiseks on Digitaalmooduli plaadil väike potentsiomeeter (LCD_BG). Graafilise LCD ekraani kontrastsust reguleeritakse tarkvaraliselt. LCD ekraanid on ühendatakse porti PA. Korraga saab kasutada ainult ühte LCD ekraani.
Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja enne ühendamist veenduda, et Kontrollermooduli toide on lahti ühendatud.
Andurite moodul koosneb integreeritud andurite ja madalpääsu filtri plaadist ning kaugusanduritest.
Anduri moodul on varustatud:
Andurid on ühendatud läbi silla (inglise keeles jumper), võimaldades mikrokontrollerisse suunata kas välise anduri signaali (ühendatud pistikusse CON2) või plaadil oleva anduri signaali. Vaikimisi on analoogsisenditega (ADC0-ADC3) ühendatud kõik plaadil olevad andurid. Andurite mooduli plaat võimaldab lisaks plaadil olevatele anduritele analoog-digitaalmuunduri sisenditesse ühendada ka väliseid analoogväljundiga andureid. Selleks saab kasutada kanaleid ADC4-ADC7, mis on välja toodud pistikust CON2. Tähelepanu tuleks pöörata aga asjaolule, et ATmega128 kasutab samu ADC4-ADC7 viike (PF4-PF7) ka JTAG programmaatori tööks. Mõlemat funktsiooni korraga kasutada ei saa, mikrokontrolleri saab seadistada kasutama vaid üht neist. Kui soovitakse sellegipoolest kasutada väliseid andureid koos JTAG programmaatoriga, tuleb sildade abil ADC0-ADC3 kanalid plaadil olevatelt anduritel välistele ümber lülitada.
Madalpääsu RC filtri saab koostada analoogsisendite 0-3 vahele (viigud PF0-PF3). Madalpääsu filtri koostamiseks paigutatakse vastavatesse pesadesse takisti ja kondensaator. Vaikimisi on madalpääsu filter koostatud kanalile PF0. Takisti väärtuseks on 10 kΩ ja kondensaatori väärtuseks 100 nF.
Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja enne ühendamist veenduda, et Kontrollermooduli toide on lahti ühendatud.
Mootorite moodul koosneb mootorite juhtplaadist ja erinevatest mootoritest. Mootoriplaat on projekteeritud AVR ATmega128 kontrolleriplaadiga ühendamiseks, kuid seda saab edukalt kasutada ka teiste mikrokontrollerite ja mootoritega, kuna sisaldab H-sildu (L293D), mis on mootorite juhtimisel üldlevinud.
Mootoriplaat eraldab mootorite toited juhtsignaalidest ning võimaldab ühe ribakaabliga ühendada kõik juhtsignaalid kontrollerplaadiga.
Moodul võimaldab juhtida erinevaid mootoritüüpe ning kõigil tüüpidel võib olla erinev toitepinge. Mooduli (ühendus)võimalused:
Mootorite mooduli toitepistik (PWR):
Viik | Ühenduspunkt | Pinge | Vool |
---|---|---|---|
1 | DC mootorid | kuni 36 V | kuni 600 mA |
2 | Bipolaarne samm-mootor | kuni 36 V | kuni 600 mA |
3 | Servomootorid | 4,8 - 6 V | kuni 1 A |
4 | Unipolaarsed samm-mootorid | kuni 50 V | kuni 500 mA |
5 | Loogika toide (valitav JP1 abil) | 5 V | |
6 | Maa (GND) |
NB! Pinge ja vool sõltuvad eelkõige kasutatavast mootorist ja ei tohi ületada mootori lubatavaid piirväärtusi. Kodulabori komplektis sisalduvate mootorite toide on üldjuhul 5 - 6 V ja vastavalt sellele on kaasasoleva harukaabli väljundpinged limiteeritud 5 või 6 V.
Mootori konkreetsed margid ja mudelid võivad Kodulabori komplektides varieeruda, kuid igas komplektis on alati 1 alalisvoolumootor, 1 samm-mootor (unipolaarne või bipolaarne) ja 1 RC servomootor.
Allpool on toodud võimalikud mootorid, mis esinevad Kodulaborite komplektides.
Mootorite mooduli plaat tuleb Kontrollermooduli plaadiga ühendada ühe ribakaabliga kontrollerimooduli porti PE-PB-PD. Mootorite toited ühendatakse eraldi PWR pistikuga, kus igale mootori tüübile on võimalik anda erinev toitepinge, sõltuvalt kasutatavast mootori tüübist. Plaadil olevaid kiipe on võimalik toita välise toiteallikaga või otse kontrollerplaadilt. Selle määrab plaadil olev sild JP1. Kui sild ühendab viigud 1 ja 2, siis kiipide toide võetakse otse Kontrollermoodulist. Kiipide korrektse toite olemasolu saab kontrollida plaadil oleva väikese rohelise LED +5V abil. Mootoriplaadil on eraldi välja toodud ka UART ühendus, mis võimaldab läbi mootoriplaadi ühendada UART protokolliga ühilduvaid seadmeid.
Alalisvoolu mootorid ühendatakse pistikute gruppi DC1. Iga paari külge on võimalik ühendada üks mootor - kokku 4 mootorit. Mootori pistikuga 3 on paralleelselt ühendatud koodrite ENC1 ja ENC2 pistikud. Kui soovitakse kasutada mootoreid koos koodritega, siis mootoripistikut 3 samaaegselt kasutada ei saa (tarkvaraliselt muudetakse see sisendiks). Mootoreid juhitakse üldlevinud kahe integreeritud H-silla kiipidega L293D, mis mõlemad on võimelised juhtima samaaegselt kahte mootorit. Mootorid võib asendada ka muude täituritega (näiteks pieso heligeneraator, relee, jms.), mida saab juhtida digitaalsete signaalidega ja millede maksimaalne vool ei ületa 500 mA.
AVR viik | Juhtsignaal | AVR viik | Juhtsignaal |
---|---|---|---|
PB4 | Mootor 1 1A | PD6 | Mootor 3 1A |
PB7 | Mootor 1 2A | PD7 | Mootor 3 2A |
PD0 | Mootor 2 1A | PD4 | Mootor 4 1A |
PD1 | Mootor 2 2A | PD5 | Mootor 4 2A |
Mootoriplaat toetab kahe erinevat tüüpi samm-mootori kasutamist. Plaadile on võimalik ühendada 2 unipolaarset samm-mootorit ja 1 bipolaarne samm-mootor. Bipolaarset samm-mootorit juhitakse H-sillaga L293D ja unipolaarset samm-mootorit transistorite jadaga ULN2803. Mootorite juhtsignaalide mustrid genereeritakse tarkvaraliselt. Samm-mootorite ühendamisel on oluline jälgida mähiste järjekorda. Unipolaarse samm-mootori toiteotsad ühendatakse viikudesse 1 ja 2. Kui tegemist on viie juhtmelise unipolaarse samm-mootoriga, siis toite ots ühendatakse viiku 2 ja viik 1 jääb vabaks. Samm-mootorite ühendused:
Pesa viik | Mähise ots | Unipolaar 1 | Unipolaar 2 | Bipolaar |
---|---|---|---|---|
1 | 1 | + toide | + toide | |
2 | 2 | + toide | + toide | |
3 | 1a | PE0 | PE4 | PB0 |
4 | 2a | PE1 | PE5 | PB1 |
5 | 1b | PE2 | PE6 | PB2 |
6 | 2b | PE3 | PE7 | PB3 |
RC servomootorid ühendatakse Mootorite mooduli plaadi pistikutesse PWM1 ja PWM2. Mootorid ühendatakse nii, et signaali juhe (tavaliselt kollane või valge) jääb viiku 1 (plaadi ääre pool). Sama-aegselt on võimalik kasutada kahte servomootorit. Mootorite juhtsignaalid on ühendatud otse kontrolleri taimerite väljundviikudega.
AVR viik | Juhtsignaal |
---|---|
PB5(OC1A) | PWM1 |
PB6(OC1B) | PWM2 |
Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja kontrollerplaadi toitepistik ühendada alati kõige viimasena.
Kodulabori teek moodustub mitmetest C-keele päisefailidest (“.h” laiendiga) ja ühest staatiliselt C-keele teegi failist (“.a” laiendiga). Teegi installeerimisel kopeeritakse kõik teegi failid AVR-GCC alamkaustadesse, kust kompilaator nad lihtsalt üles leiab. Kasutaja teeki või selle osasid oma rakenduse kausta kopeerima ei pea. Järgnevalt on kirjeldatud teegi funktsionaalsust. Sellest, kuidas kodulabori teeki reaalselt Windowsi või Linuxi operatsioonisüsteemiga kasutada, räägib esimene praktiline harjutus.
Kodulabori veebilehel on vabalt kättesaadav Kodulabori teegi lähtekood mida on võimalik kohandada vastavalt oma projekti vajadustele. Allalaetavas teegis on ka lisafunktsioone mida käesolev raamat ei kirjelda.
Bitioperatsioonide teek on üldkasutatav makrofunktsioonide kogum tüüpiliste bititehete teostamiseks. Seda kasutavad kõik teised teegid, kuid seda võib kasutada ükskõik milliste registrite või andmete puhul, sest makrofunktsioonidel pole kindlat andmetüüpi. Funktsioonid sobivad nii 8-, 16- kui ka 32-bitiste muutujate ning registrite jaoks.
Bitiindeksiks loetakse biti järjekorranumbrit, alustades kõige vähemtähtsast (inglise keeles least significant bit, lühend LSB). Loendamine algab nullist. 8-bitiste arvude puhul on bitiindeksi väärtus 0-7, 16-bitiste puhul 0-15 ja 32-bitiste puhul 0-31.
Bitiindeksi teisendamine bitimaskiks. Parameetrid:
Muutujas kindla biti kõrgeks seadmine. Parameetrid:
Muutujas kindla biti madalaks seadmine. Parameetrid:
Muutujas kindla biti soovitud olekusse seadmine. Parameetrid:
Muutujas kindla biti oleku ümberpööramine (madal kõrgeks ja vastupidi). Parameetrid:
Väärtuse kindla biti kõrgeloleku kontroll. Parameetrid:
Väärtuse kindla biti madaloleku kontroll. Parameetrid:
Muutujas b kolmanda biti kõrgeks seadmine ja viimase ümberpööramine.
#include <homelab/bit.h> int main(void) { unsigned char b = 0x00; bit_set(b, 2); bit_invert(b, 7); }
Viikude teek on ette nähtud AVR digitaalsete sisend- ja väljundviikudega opereerimiseks. Teegi eesmärk on lihtsustada AVR viikude kasutamist. Kasutaja saab programmis luua soovitud viigu kohta käiva muutuja, millele ta omistab spetsiaalse makro-funktsiooniga füüsilise viigu aadressi. Seejärel saab muutuja abil välja kutsuda erinevaid funktsioone viigu suuna ja olekute muutmiseks ning nende lugemiseks.
Määrates viigu füüsilise siini (pordi) ja indeksi ära ainult ühe korra ja ühes kohas, on füüsiliste muudatuste korral lihtne programmi muuta. Näiteks, kui algul kasutatakse indikaatorina ühte LED-i, võib lihtsa tarkvara muudatusega teist LED kasutama hakata. Viigu muutujatest võib luua ka massiive, näiteks siinide koostamiseks.
Näide sellest, kuidas ühe viigu väärtus teha sõltuvaks teisest. Programmis omandab viik PC3 viigule PC0 vastupidise väärtuse:
#include <homelab/pin.h> pin output_pin = PIN(C, 3); pin input_pin = PIN(C, 0); int main(void) { bool value; // Viigu väljundiks seadistamine pin_setup_output(output_pin); // Viigu pull-up takistiga sisendiks seadistamine pin_setup_input_with_pullup(input_pin); // Lõputu tsükkel while (true) { // Sisendviigu väärtuse lugemine value = pin_get_value(input_pin); // Väljundviigule vastupidise väärtuse omistamine pin_set_to(output_pin, !value); } }
Analoog-digitaalmuunduri teek on AVR ADC mooduli kasutamise lihtsustamiseks. Teegi muundamise funktsioonid on blokeeruvad, ehk nende väljakutsumisel jääb protsessor muundamise lõppu ootama. Muundamise aeg sõltub ADC taktijagurist.
Näites seatakse analoog-digitaalmuundur töövalmis ja loetakse kahelt sisendkanalilt pinge. Kanali 0 pingemuundamise väärtus loetakse muutujasse x ja kanali 1 väärtus kümnekordse ümardamise tulemusena muutujasse y.
#include <homelab/adc.h> int main(void) { unsigned short x, y; // Analoog-digitaalmuunduri seadistamine // Võrdluspinge tuleb AVCC viigult. Muunduri töötakt // on 8 korda madalam kontrolleri taktist. adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Kanali 0 muundatud väärtuse lugemine muutujasse x x = adc_get_value(0); // Kanali 1 muundatud ja keskmistatud väärtuse lugemine muutujasse y y = adc_get_average_value(1, 10); }
Tegu on AVR universaalse jadaliidese kasutamise teegiga. Võimaldab asünkroonset andmete kirjutamist ja lugemist.
Makrofunktsiooni USART mooduli asünkroonse režiimi boodikiiruse registri väärtuse arvutamiseks. Parameetrid:
Jadaliidese asünkroonseks seadistamine. Parameetrid:
Blokeeruv sümboli saatmise funktsioon. Funktsioon ootab, kuni saatmise puhver tühjeneb ja kirjutab sinna saatmiseks uue sümboli. Parameetrid:
Blokeeruv teksti saatmise funktsioon. Parameetrid:
Sisendpuhvris andmete olemasolu kontroll. Parameetrid:
Sisendpuhvrist sümboli lugemine. Enne lugemist peab veenduma, et puhvris on sümbol. Parameetrid:
Sisendpuhvri sümboli olemasolu kontroll ja selle lugemise ühisfunktsioon. Parameetrid:
Jadaliidese seadmistamine töötab asünkroonselt 8 andmebiti, ühe stoppbiti ja ilma paarsuse kontrollita boodikiirusel 9600. Programm saadab teksti, ootab, kuni saabub sümbol ja loeb selle siis välja.
#include <homelab/usart.h> // port on jadaliides 0 usart port = USART(0); int main(void) { char c; // Jadaliidese seadistamine usart_init_async(port, USART_DATABITS_8, USART_STOPBITS_ONE, USART_PARITY_NONE, USART_BAUDRATE_ASYNC(9600)); // Teksti saatmine usart_send_string(port, "Tere\n"); // Sissetuleva sümboli ootamine while (!usart_has_data(port)) {} // Sümboli lugemine c = usart_read_char(port); }
Käesolev taimerite teek katab suure osa ATmega128 taimerite funktsionaalsusest. Kuna AVR taimerid on erinevate kiipide vahel päris erinevad, siis ei saa nende kasutamiseks kirjutada universaalseid funktsioone. Ka kirjeldatavad ATmega128 funktsioonid on suures osas lihtsalt primitiivsed registri muutmise või lugemise funktsioonid, kuid siiski on nad loetavamad kui registrid.
Näites seadistatakse taimer 0 tavalisse loendamise režiimi ja lubatakse ületäitumise katkestus.
#include <homelab/timer.h> #include <avr/interrupt.h> // Katkestuse programmilõik ISR(TIMER0_OVF_vect) { } int main(void) { // Taimer 0 normaalrežiimi, taktijagur 32 timer0_init_normal(TIMER0_PRESCALE_32); // Taimer 0 ületäitumise katkestuse lubamine timer0_overflow_interrupt_enable(true); // Globaalne katkestuse lubamine sei(); }
Tegu on tarkvaraliste ja riistvaraliste viite tekitamise funktsioonide teegi osaga. Viite funktsioone välja kutsudes jääb programm neid ettenähtud ajaks täitma ja muu programmi, välja arvatud katkestuste, täitmine peatub.
Viitefunktsioonid pole eelnevalt kompileeritud, sest mikrokontrolleri taktsagedus võib erinevates rakendustes erineda. Need kompileeritakse iga kord uuesti.
Mõlemat liiki viitefunktsioonide kasutamise näide:
#include <homelab/delay.h> int main(void) { // Tarkvaraline viide 100 ms sw_delay_ms(100); // Riistvaraline viide 100 ms hw_delay_ms(100); }
Seotud mooduliga: [HW] Sisend-väljundmoodul
See teek on spetsiaalselt loodud kodulabori digitaalsel sisend-väljundmooduli plaadil asuva indikaatori kasutamiseks. 7-segmendilise indikaatoriga saab kuvada numbreid 0 kuni 9.
Indikaatori juhtviikude seadmistamine väljundiks.
Soovitud numbri kuvamine indikaatoriga. Parameetrid:
Näites on number 5 kuvamise protseduur.
#include <homelab/module/segment_display.h> int main(void) { // 7-segmendilise indikaatori seadistamine segment_display_init(); // Indikaatoril numbri 5 kuvamine segment_display_write(5); }
Seotud mooduliga: [HW] LCD moodul
See teegi osa sisaldab kodulabori alfabeetilise LCD kasutamise funktsioone.
#include <homelab/module/lcd_alpha.h> int main(void) { // Ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Kursori (nähtamatu) teise rea algusesse viimine lcd_alpha_goto_xy(0, 1); // Teksti kuvamine lcd_alpha_write_string("Tere"); }
Seotud mooduliga: [HW] LCD moodul
See teegi osa sisaldab kodulabori graafilise LCD kasutamise funktsioone. Kuigi LCD on graafiline, puuduvad teegist hetkel siiski kujundite joonistamise funktsioonid.
#include <homelab/module/lcd_gfx.h> int main(void) { // Ekraani seadistamine lcd_gfx_init(); // LCD ekraani puhastamine lcd_gfx_clear(); // Kursori (nähtamatu) ekraani keskele viimine lcd_gfx_goto_char_xy(5, 2); // Teksti kuvamine lcd_gfx_write_string("Tere"); }
Seotud mooduliga: [HW] Mootorite moodul
Mootorite teek võimaldab juhtida kodulabori mootorite moodulit ja mootoreid, mis sinna ühenduvad. Olemas on alalisvoolu-, samm- ja servomootorite juhtimise funktsioonid.
Ühe alalisvoolu mootorikontrolleri juhtviikude seadistamine väljundiks. Parameetrid:
Alalisvoolu mootorikontrolleri juhtkäsk. Parameetrid:
Bipolaarse mootorikontrolleri juhtviikude seadistamine väljundiks.
Bipolaarse samm-mootori mootorikontrolleri pool-sammumise juhtkäsk. Funktsioon on blokeeruv ehk seda täidetakse seni, kuni soovitud arv samme on tehtud. Parameetrid:
Ühe servomootori juhtviikude väljundiks seadistamine ja taimer 1 seadistamine PWM režiimi. Parameetrid:
Servo-mootori juhtkäsk. Kui juhitakse positsioneerivat servomootorit, siis muutub rootori asend, kui lõputult pöörlevat, siis muutub pöörlemise kiirus. Parameetrid:
Järgnev näide demonstreerib kõiki teegi funktsioone. Järjest seadistatakse mootorikontrollerid ja liigutatakse mootoreid.
#include <homelab/module/motors.h> int main(void) { // Alalisvoolu mootorikontrollerite 0 ja 1 seadistamine dcmotor_init(0); dcmotor_init(1); // Bipolaarse samm-mootori kontrolleri seadistamine bipolar_init(); // Servomootorite 0 ja 1 juhtsignaalide seadistamine servomotor_init(0); servomotor_init(1); // Üks alalisvoolu mootor pöörlema ühtpidi, teine teistpidi dcmotor_drive(0, -1); dcmotor_drive(1, +1); // Samm-mootori pööramine 100 kraadi ühele poole ja seejärel // 2 korda kiiremini teisele poole bipolar_halfstep(1, 100, 50); bipolar_halfstep(-1, 100, 25); // Servomootorite vastassuunda keeramine servomotor_position(0, -100); servomotor_position(1, +100); }
Seotud mooduliga: [HW] Andurite moodul
See teegi osa sisaldab kodulabori andurite kasutamise funktsioone.
Termistori temperatuuri arvutamine Celsiuse kraadides ADC muunduri väärtusest. Funktsioon põhineb teisendustabelil. Parameetrid:
IR kaugusanduri väljundpinge ADC väärtuse sentimeetriteks ümberarvutamise funktsioon. Parameetrid:
Ultraheli-kaugusanduri mõõtmise teostamise funktsioon. Funktsioon tekitab SRF04 kaugusmõõdiku päästikuimpulsi ja mõõdab kajaimpulsi saabumise aega. Aja põhjal arvutatakse objekti kaugus. Mõõtmine võtab aega kuni 36 ms. Funktsioon eeldab 14.7456 MHz mikrokontrolleri taktsagedust. Parameetrid:
#include <homelab/module/sensors.h> // Ultraheli kaugusmõõdiku juhtviigud pin pin_trigger = PIN(G, 1); pin pin_echo = PIN(G, 0); int main(void) { unsigned short adc_value = 400; // näidisväärtus signed short distance; // IR kaugusanduri ADC väärtuse sentimeetriteks teisendamine distance = ir_distance_calculate_cm(GP2Y0A21YK, adc_value); // Ultraheli-kaugusanduriga mõõtmine distance = ultrasonic_measure(pin_trigger, pin_echo); }
Praktilised näited on üles ehitatud ühtse läbiva stiiliga ja võimalikult konkreetsed. Iga näide algab lühikese teoreetilise taustaga, andes nii vajalikud põhiteadmised harjutuses järgnevale praktilisele osale. Praktiline osa sisaldab endas tarkvara lähtekoodi kommenteeritud näidet. Üldjuhul on koodinäites kasutatud Kodulabori teeki, aga mõne näite puhul ka otsest registrite seadistamist. Natuke erineva struktuuri ja eesmärgiga on esimene peatükk, mis kirjeldab vajaliku tarkvara paigaldamist ja seadistamist. Näited on toodud Windowsi ja Linuxi keskkondade jaoks. Järgnevad peatükid ja praktilised näited sobivad mõlema operatsioonisüsteemi ja arendustarkvara jaoks.
Ülesehitus
Praktiliste näidete peatükkide juures on toodud loetelu näite läbimiseks vajalikest eelteadmistest. Loetelus on viited raamatu teistele peatükkidele, mis on tähistatud teemakohaste ikoonidega:
Näidete baastarkvara
Nagu eespool öeldud, on praktilised koodinäited koostatud Kodulabori teegi baasil. Teeki on kirjutatud enimkasutatavad AVR spetsiifilised operatsioonid ja Kodulabori moodulitega seotud protseduurid. Teegi kasutamine tähendab, et kasutaja ei pea moodulite töölepanekuks kirjutama riistvaralähedast, registritega toimetavat programmikoodi, kuigi see võimalus on alati olemas. Riistvaraga suhtleva tarkvara eraldamine näidetest ja harjutusülesannetest võimaldab kasutajal keskenduda oma algoritmi loomisele, mitte riistvaraga seotud eripäradele.
Näidete koodistiil
Näidisprogrammid on kirjutatud ühes stiilis, et programmikood oleks ülevaatlikum. Ühtne stiil teeb programmi loetavaks ja välistab kergemate süntaksivigade tekkimist. Kindlat stiili on soovitatav järgida ka harjutusülesannete tegemisel. Stiili peamised iseloomustajad:
AVR mikrokontrolleri programmeerimiseks on vaja koodi kirjutamise keskkonda, vastava keele kompilaatorit ja kompileeritud programmi kontrollerisse laadimise tarkvara. Mugavaim on kasutada kõigeks selleks spetsiaalset integreeritud arenduskeskkonda (IDE). AVR mikrokontrollerit on võimalik programmeerida paljudes erinevates programmeerimiskeeltes: assembler, C, C++, Pascal, Basic jne. Käesolev raamat on suunatud C-keele kasutamisele mikrokontrolleri programmeerimisel. AVR mikrokontrolleri C-keeles programmeerimiseks on olemas tasuta tarkvara nii Linuxi kui ka Windowsi operatsioonisüsteemidele, mille mõlema kasutamist järgnevad peatükid ka tutvustavad.
Kogu tarkvara harjutuste läbimiseks leiab Kodulabori veebilehelt.
Järgnev juhend kirjeldab AVR arenduskeskkonna installeerimist ja kasutamist Windowsi operatsioonisüsteemis.
Enne paigaldamist tuleks hankida alljärgnev tarkvara kas tootja kodulehelt või Kodulaboriga kaasas olevalt plaadilt.
1. AVR Studio
AVR Studio 4 on IDE (lühend inglise keeles Integrated Development Environment), milles toimub tarkvara kirjutamine ja mikrokontrollerisse laadimine. AVR Studio leiab selle tootja Atmeli kodulehelt.
2. WinAVR
WinAVR on GNU-GCC kompilaator AVR mikrokontrolleritele. See on vabavara, mille leiab Sourceforge veebilehelt. WinAVR pakub installeerimisel välja kataloogi nime, mis sisaldab ka versiooni numbrit, kuid kataloog tuleks manuaalselt seada hoopis:
C:\WinAVR
3. Kodulabori teek
Kodulabori teek sisaldab programmi lihtsustavaid funktsioone AVR ja kodulabori komplekti osade kasutamiseks. Teegi viimase versiooni leiab kodulabori veebilehelt. Teek tuleb kindlasti installeerida samasse kataloogi, kus on WinAVR.
4.. Virtuaalne COM pordi ajur
Ajur võimaldab arvutiga ühendada JTAG ICE programmaatori. Ajur tuleb installeerida enne programmaatori arvutiga ühendamist. Installeri nimi on “CDM x.xx.xx.exe”, kus “x” tähistab versiooni. Seejärel tuleb ühendada programmaator arvutiga USB liidese kaudu ja lasta Windows-il teostada automaatne paigaldus. Olekuribal peaks nägema umbes sellist teadet.
Sõltuvalt sellest, kui palju virtuaalseid jadaporte on arvutisse eelnevalt paigaldatud ja kasutusele võetud, paigaldab Windows automaatselt järgmise järjekorranumbriga virtuaalpordi. Uus järjekorranumber genereeritakse ka USB pordi vahetamisel. AVR Studio mõned versioonid tunnevad JTAG ICE programmaatori ära ainult jadaportides COM1…COM9 ja silumise funktsiooni lubavad kasutada ainult jadaportides COM1…COM4. Kasutajal on võimalus pordi järjekorranumbrit muuta, kasutades Device manager töövahendit. Vaata veebilehelt protseduuri.
AVR programmi kirjutamiseks tuleb luua uus projekt, mis tüüpiliselt sisaldab endas palju erinevaid faile: programmikoodi(e), päisefaile, kompileeritud programmi jne. Selleks et projektid oleks korrektselt eristatavad, tuleks iga projekti jaoks luua uus kataloog (seda võimalust pakub uue projekti loomise abimees).
Uue projekti loomiseks tuleb läbida järgmised sammud:
1. Avada AVR Studio ja vajutada nupule uus projekt (New Project). Juhul kui vastav aken automaatselt ei avane, valida menüüst Project - New project. Pärast sobivat sisestust vajutada nupule Next.
2. Avaneb aken, kus tuleb märkida kompilaatori ja failide algseaded. Kompilaatoriks valida AVR GCC ja paremas akna osas sisestada projekti nimi ning algkoodi faili nimi. Algkoodi faili nimi peaks kindlasti lõppema laiendiga “.c”. Aknas on võimalik veel märkida valikud automaatseks projekti nimega kataloogi ja algkoodi faili tekitamiseks. Mõlemad valikud on mõistlik ära märkida. Samuti tuleks näidata kataloog, kuhu vastav projektikataloog tekitatakse. Pärast valikute tegemist vajutada nupule Next.
NB! Kui kompilaatori valikus puudub AVR GCC, siis ei ole WinAVR korrektselt paigaldatud ja seda tuleks enne C-keele programmi kirjutamist kindlasti teha.
3. Järgnevalt avaneb aken, kus tuleb märkida kasutatav silumise platvorm ja mikrokontrolleri tüüp. Kodulaboris on silumise platvormina kasutusel JTAG ICE programmaator ja mikrokontrolleriks on ATmega128. Projekti lõplikuks loomiseks vajutada nupule Finish.
4. Nüüd avaneb juba programmeerimise kasutajaliides, kuhu saab hakata kirjutama uut programmi lähtekoodi.
5. Enne koodi kompileerimist tuleb määrata projekti seaded. Olulisemad seaded on kontrolleri taktsagedus ja kompilaatori optimeerimismeetod. Kodulabori kontrolleri taktsagedus on 14,7456 MHz ehk 14745600 Hz. See sagedus tuleb hertsides määrata Project → Configuration Options → General aknas. Optimeerimise meetodiks jätta -Os, kui ei ole vajadust just teiste järgi.
6. Kodulabori teegi kasutamine AVR Studio-ga eeldab, et see on tarkvara paigaldamise juhendi kohaselt süsteemi paigaldatud. Iga projekti korral tuleb teek projekti seadetest Project → Configuration Options → Libraries lisada lingitavate objektide nimekirja.
Kui objekt libhomelab.a nimekirjast puudub, siis ei ole kodulabori teek korrektselt süsteemi paigaldatud.
Kui arenduskeskkond on esimest korda paigaldatud ja seadistatud, on mõistlik testida, kas kõik sai tehtud õigesti. Selleks on lihtsaim viis teha üks väike programm, see ära kompileerida ja laadida kontrollerisse.
1. Ühendada programmaator ATMega128 plaadiga. Ühendamisel kontrollida, et programmaator saab ühendatud õigesse pesasse (JTAG) ja õigetpidi (kaabel on suunatud kontrolleri plaadist eemale - vaata järgmist pilti). Peale programmaatori ühendada ka kontrolleri toide (kontrolleri plaadil peab süttima väike roheline LED). Sisestada lihtne C-kood:
#include <avr/io.h> #include <homelab/delay.h> int main(void) { // Viigu PB7 seadmine väljundiks DDRB = 0x80; // Lõputu tsükkel while (true) { // Viigu PB7 inverteerimine PORTB ^= 0x80; hw_delay_ms(500); } }
Kompileerida programm käsuga Build (kiirklahv F7) ja kontrollida, et kompileerimine õnnestuks. Selleks peab teadete aknasse tekkinud kompilaatori väljundi lõpp olema järgmine:
Build succeeded with 0 Warnings...
2. Avada koodi laadimise aken nupust Tools → Program AVR → Auto Connect. Tulemuseks peaks avanema kompileeritud faili mikrokontrollerisse laadimise aken. Kontrollige, et avatud oleks kaart Program.
Kui eespool toodud aken ei avane ja avaneb aken Connection Failed, siis puudub ühendus programmaatoriga. Esmalt tuleks kontrollida, kas mikrokontrolleril on järel toide ja kas programmaator on ühendatud õigesti (JTAG pistikusse, kaabel õiges suunas). Kui see on korras, siis tuleks kontrollida, mis COM pordi numbri on Windows programmaatorile omistanud. Kui see on suurem 9-st, siis ei pruugi tarkvara seda leida ja pordile tuleb omistada väiksem järjenumber.
3. Programmaatori aknas sisestada Flash-sektsioonis tekstikasti Input HEX File kompileeritud fail. Seda saab teha “…” nuppu vajutades. Kompileeritud fail asub tavaliselt projekti alamkataloogis default ja see on sama nimega, mis projekt, kuid laiendiga “.hex”, näiteks “labor1.hex”. Pärast õige faili valimist vajutada nupule Program, mis laeb valitud programmi kontrollerisse. Kui kõik õnnestus, tekib programeerimiskeskkonna allosasse teade:
OK Reading FLASH input file.. OK Setting device parameters for jtag programming ..OK Entering programming mode.. OK Erasing device.. OK Programming FLASH .. OK Reading FLASH .. OK FLASH contents is equal to file.. OK Leaving programming mode.. OK
Prorammi mõjul peaks kontrolleri plaadil olev LED PB7 perioodiliselt süttima ja kustuma. Kui programm töötab, on tarkvara paigaldatud edukalt ja esimene projekt tehtud. Palju õnne!
Programmi silumiseks (inglise keeles debugging) nimetatakse vigade otsimist programmist. Selleks on loodud eraldi vahendid - silurid (inglise keeles debugger), mis võimaldavad programmi täita samm-sammult, peatades seda soovitud kohtades. Selline programmi täitmine võimaldab igas programmi faasis kontrollida muutujate väärtusi, registrite sisusid ja programmi täitmise järjekorda. Eriti oluline on silumise võimaluse kasutamine keerukamate programmide juures, kus vea põhjust on tihti keeruline otsida. Mikrokontrollerite puhul on veel oluline, et tarkvara samm-sammult täitmine toimub reaalselt kontrolleris ja võimaldab nii lisaks registrite väärtuste vaatamisele näha ka reaalsete väljundite muutumist. Siluri kasutamiseks on eelkõige vaja kahte tingimust: kasutatav mikrokontroller peab silumist toetama ja olemas peab olema ka vajalik riistvara - silumist toetav JTAG programmaator. Odavamad programmaatorid, mis kasutavad ISP programmeerimise liidest, võimaldavad laadida kontrollerisse küll kompileeritud programmi, kuid ei võimalda silumist.
Programmi käivitamiseks siluri režiimis AVR Studio-ga tuleks see esmalt kompileerida nupuga Build (kiirklahv F7) ja käivitada kompileeritud programm käsuga Run (kiirklahv F5). Programmi lähtekoodi võib enne seda soovitud kohtadele lisada katkestuspunkte (inglise keeles break point) (kiirklahv F9). Kui programmi täitmine jõuab katkestuspunktini, peatatakse programmi töö, võimaldades nii uurida mikrokontrolleri olekut sellesse punkti jõudmisel. Programmi täitmist võib jätkata jällegi käsuga Run või siis kasutada käskhaaval täitmist käsuga Step Into (kiirklahv F11).
Mõnikord tekib vajadus AVR programmis kasutada ujukoma-arve. Nendega arvutamiseks ja nende esitamiseks printf-tüüpi funktsioonidega tuleb projekti seadistustes teha järgmised muudatused:
1. Avada projekti seaded menüüst Project → Configuration Options. Seadete kaardil Libraries tuleb sinna, kuhu on lisatud kodulabori teegi objekt libhomelab.a, järgi lisada ka libprintf_flt.a ja libm.a.
2. Seejärel tuleb avada Custom Options kaart ja valida [All files] sektsioon. Parempoolsesse kasti lisada read “-lprintf_flt” ja “-lm”. [Linker Options] sektsiooni lisada rida “-uvfprintf”.
3. Vajutada OK ja sulgeda seadete aken.
Järgnev juhend kirjeldab AVR arenduskeskkonna installeerimist ja kasutamist Ubuntu 9.10 operatsioonisüsteemis.
Installeerida järgnev tarkvara:
1. Linuxi tarkvarapaketid
Installeerimiseks kasutada terminali käsurida:
sudo apt-get install gcc-avr avrdude avr-libc
või graafilist paketihaldustarkvara (nt. Ubuntu tarkvarakeskus või Synaptic pakihaldur).
2. Kodulabori teek
Teek lihtsustab programmikoodi kirjutamist, kuna madalama taseme funktsioonid on selles juba valmis kirjutatud. Teegi installeerimiseks salvestada arvutisse kodulabori kodulehelt fail nimega Homelab library vX.X.run, kus X.X asemel on versiooni number, ning käivitada see järgmise käsuga:
sudo sh homelab_library_vX.X.run
Veendu, et kodulabori teegi allalaadimine ja installeerimine õnnestus.
3. KontrollerLab
KontrollerLab on IDE (inglise keeles Integrated Development Environment) ehk integreeritud arenduskeskkond tarkvara kirjutamiseks, kompileerimiseks, pealelaadimiseks jms. Salvestada KontrollerLab tarkvarapakett kausta (nt ~/Dokumendid/AVR/KontrollerLab/) ning terminali aknas käivitada käsk selles kaustas:
sudo dpkg -i kontrollerlab*.deb
Kui tekib probleeme paketisõltuvuses, siis käivitada järgnev käsk, mis installeerib puuduvad paketid:
apt-get install –f
Ühendada programmaator arvutiga ning kontrollida, kas arvuti tunneb seadme ära. Terminali aknasse kirjutada käsk lsusb, mis näitab nimekirja ühendatud USB seadmetest. Programmaatori nimi on “Future Technology Devices International, Ltd FT 232 USB-Serial (UART) IC”.
Saamaks teada, millise pordi taha on programmaator ühendatud, kontrollida /dev kataloogi, kasutades käske cd /dev (määrab /dev kui aktiivse kataloogi) ja dir (kuvab kataloogi sisu). Kuna tegu on USB-Serial liidesega, siis on ta märgitud ttyUSBx-na, kus x märgib liidese numbrit. Kui eelnevalt ei ole mingeid teisi USB-serial seadmeid ühendatud, siis on see number 0.
AVR programmi kirjutamiseks tuleb luua uus projekt, mis tüüpiliselt sisaldab endas palju erinevaid faile, nn. programmi algkoodi, päisefaile kompileeritud programmi jne. Selleks et projektid oleks korrektselt eristatavad, tuleks iga projekti jaoks luua uus kataloog (seda võimalust pakub ka uue projekti loomise abimees).
Uue projekti loomiseks järgi järgmisi samme:
1. Avada KontrollerLab (Rakendused → Programmeerimine → KontrollerLab) ning valida ülevalt menüüst File → New → New project. Avaneb aken, kus tuleb määrata projekti asukoht ning Location-väljale kirjutada projektifaili nimi. Toodud näites on loodud eraldi kataloog ../Homelab/blinkingLED/, kus hoitakse kõik näiteprogrammi (vilkuva LED) jaoks loodavad failid eraldi.
2. Kuna projekt on esialgu tühi, siis tuleb sellele juurde lisada C-fail, kuhu koodi saaks kirjutada. Valida menüü File → New → New. Avaneb faili lisamise aken, kus valida C source ja määrata faili nimi.
3. Seadistada KontrollerLabi projekt vastavalt kodulabori riistvarale. Valida menüü Project → Configure Project, mispeale kuvatakse projekti seadistamise aken avatuna Common-kaardil. Määrata protsessoriks (CPU) ATmega128, taktsageduseks (clock) 14745600,0 Hz ning loodavate HEX ja MAP failide nimed. Vajutades nuppu Set as default, määrab see hetke seadistused KontrollerLabis ka kõikide edaspidi loodavate projektide seadistusteks. Kuna sõltumata projektist jääb kodulabori riistvara samaks, siis on mõttekas määratagi sisestatud parameetrid vaikimisi parameetriteks. Samas jäävad ka KontrollerLabi poolt loodavate väljundfailide (HEX, MAP) nimed samaks. Siinkohal on kaks võimalust: igas projektis muuta HEX faili nime või panna mingi universaalsem nimi (nt out.hex), mis sobiks kõikidele projektidele. Hetkel on võetud teine variant, nii et projekti vahetamisel ei pea väljunfailide nimesid muutma.
NB! Kuna KontrollerLab programmis ei saa korrektselt teeki lisada Linker kaardil, siis tuleb Kodulabori teegi lisamine seadistada siin, kirjutades map faili nime taha -lhomelab .
Compiler kaardil seadistada kompilaatori sätted, nagu näidatud juuresoleval pildil. Enne OK vajutamist määrata ka siin sisestatud parameetrid vaikimisi säteteks.
4. Seadistada programmaatori sätted, valides menüü Project → Configure Programmer. Choose Programmer-kaardil valida AVRDUDE ning AVR DUDE kaardil määrata programmaatori tüübiks jtagmkI ja ühendusliideseks eelnevalt leitud port /dev/ttyUSBx (vt programmaatori peatükki). Määrata ka siin seadistatud parameetrid vaikimisi säteteks.
5. Seadistada tekstiredaktori sätted nii, et tabulaatorit tõlgendataks 4 tühikuna. See on vajalik, kui juhtutakse lähtefaili avama mõne muu tekstiredaktoriga, mis tõlgendab tabulaatorit teisiti kui KontrollerLab. Sel juhul võib koodi liigendus muutuda, nii et inimese jaoks on kood raskesti jälgitav. Selleks, et seda ei juhtu, valida menüü Settings → Configure Editor ja avanenud aknas vasakult Editing. Märgi linnuke kasti “Insert spaces instead of tabulators” sisse. Samuti määra tabulaatori laiuseks 4 tühikut.
6. Seadista avanenud alamaknad KontrollerLabis oma käe järgi ning kirjuta mingi lihtne programm keskkonna testimiseks. Näitena on toodud vilkuva LED programm.
Kui arenduskeskkond on esimest korda paigaldatud ja seadistatud, on mõistlik testida, kas kõik sai tehtud õigesti. Selleks on lihtsaim viis teha üks väike programm, see ära kompileerida ja laadida kontrollerisse.
1. Ühendada programmaator ATMega128 plaadiga. NB! Kontrollida, et programmaator on ühendatud õigesse pistikusse (JTAG) ja õigetpidi (kaabel on suunatud kontrolleri plaadist eemale - vaata järgmist pilti). Pärast programmaatori ühendamist ühendada kontrolleri toide (kontrolleri plaadil peab süttima väike roheline LED).
2. Sisestada lihtne C-kood ja kompileerida see (compile).
#include <avr/io.h> #include <homelab/delay.h> int main(void) { // Viigu PB7 seadmine väljundiks DDRB = 0x80; // Lõputu tsükkel while (true) { // Viigu PB7 inverteerimine PORTB ^= 0x80; hw_delay_ms(500); } }
Veendu, et väljundaknasse tuleb teade “File compiled successfully”. Kui annab teate “Error(s) occurred: ”, siis kontrollida, et koodi sisestamisel ei ole tehtud mõnd kirjaviga.
3. Koodi pealelaadimiseks valida ignite käsk. Kui kõik õnnestub, siis väljundaknas viimase reana annab KontrollerLab teate “Project built and uploaded successfully”. Kontrolli, et punane LED hakkas perioodiliselt vilkuma (500 ms põleb, 500 ms on kustus).
Kui LED töötab, nii nagu eespool kirjeldatud, on tarkvara paigaldatud edukalt ja esimene programm kompileeritud. Palju õnne!
Mõnikord tekib vajadus AVR programmis kasutada ujukoma-arve. Nendega arvutamiseks ja nende esitamiseks printf-tüüpi funktsioonidega tuleb projekti seadistustes teha järgmised muudatused:
1. Avada projekti seaded menüüst Project → Configure Project ning valida Linker kaart. Märgistada Linker flags sektsioonis esimene linnuke (vt ka juuresolevat pilti).
2. Vajutada OK ja sulgeda seadete aken.
Järgnevad peatükid tutvustavad lihtsaimat mikrokontrolleri funktsiooni - digitaalseid viike. Viigud on mikrokontrolleri metallist kontaktid, kõnekeeles jalad, mille kaudu saab edastada ja vastu võtta digitaalseid pingeväärtusi. Kui viik seadistada programmis sisendiks, saab selle kaudu mikrokontrollerilt lugeda lülitite või muude lihtsamate andurite olekut. Kui viik seadistada väljundiks, saab selle kaudu süüdata valgusdioode või juhtida elektriseadmeid.
Peaaegu kõigi tüüpiliste mikrokontrollerite viigud võimaldavad lihtsaid sisend/väljundfunktsioone täita, kuid tavaliselt on neil viikudel ka alternatiivfunktsioone. Enne alternatiivfunktsioonidega tegelemist, millest räägivad eraldi peatükid, on aga kasulik neid viike lihtsamate ülesannete täitmiseks tundma õppida.
Vajalikud teadmised: [HW] Kontroller, [HW] Digitaalne moodul, [ELC] LED takisti, [AVR] Registrid, [AVR] Sisendid-väljundid, [LIB] Viikude teek
Valgusdiood on pooljuht, mis päripinge andmisel kiirgab valgust. Valgusdioodi nimetatakse ingliskeelse lühendiga LED (Light-Emitting Diode). On olemas erineva värvusega dioode ja dioodide kombinatsioone, millega saab tekitada ka valget valgust. Valgusdioodil on nagu tavalisel dioodilgi kaks kontakti - anood ja katood. Valgusdioodi joonistel on anood tähistatud + ja katood - sümboliga.
Päripingestamisel rakendatakse LED anoodile positiivne ja katoodile negatiivne pinge. LED päripinge sõltub selle värvusest – pikema lainepikkusega LED-ide (punased) puhul on see ~2V, lühema lainepikkusega (sinised) on see ~3V. Tavaliselt on LED-ide võimsus mõnikümmend millivatti, sellest tulenevalt peab ka vool samas suurusjärgus olema. Suurema pinge või voolu rakendamisel LED-ile on oht see läbi põletada.
Kui LED-e kasutatakse spetsiaalselt valgustamiseks, on mõistlik kasutada eri elektriskeeme nendele täpselt õige pinge ja voolu tekitamiseks. Tihti kasutatakse LED-e aga indikaatoritena ja neid toidetakse otse mikrokontrolleri viikudelt. Kuna mikrokontrollerite toitepinge on enamasti kõrgem LED-ide päripingest ja ka voolutugevus on suurem, siis LED-iga järjestikku tuleb lisada takisti, mis piirab voolu ja tekitab vajaliku pingelangu. Takisti arvutusvalemid leiab elektroonika peatükist.
LED-e toodetakse mitmesugustes kestades. Kõige levinumatel „jalgadega“ LED-idel on 3 mm või 5 mm läbimõõduga ümmargune kest ja 2 pikka metallist viiku. Pikem viik tähistab anoodi, lühem katoodi. Pindliides kestas (SMD) LED-idel on polaarsuse tähistamiseks põhja all T-kujuline tähis, kus T katus tähistab anoodi ja teravik katoodi asukohta.
Kodulabori kontrollerimoodulil on üksik punane LED, mille anood on läbi takisti ühendatud +5 V toitega ja katood ATmega128 viiguga PB7. Selleks et kontrollerimooduli LED-i põlema süüdata ja kustutada, tuleb PB7 viik väljundiks defineerida ning seda vastavalt madalaks ja kõrgeks seada. Ehk siis viigu kõrges olekus LED ei põle ja madalas põleb. Põhimõtteliselt võib LED-e ka teistmoodi ühendada, nii et anood on mikrokontrolleri viiguga ja katood maaga ühendatud (kusagil vahel peab ka takisti olema) – sellisel juhul viigu kõrges olekus LED põleb ja madalas olekus ei põle.
Kõik kodulabori praktilised näited, kaasa arvatud LED süütamise näide, kasutavad kodulabori viikude teeki. Viikude teegis on pin-andmetüüp, mis sisaldab viiguga seotud registrite aadresse ja viigu bitimaski. Kui programmi tekitada pin-tüüpi muutuja ja see kohe programmi alguses PIN-makrofunktsiooniga algväärtustada, saab selle muutuja abil viiku kogu programmi ulatuses vabalt kasutada, ilma et peaks oskama registreid kasutada. Järgnevalt on toodud 2 näiteprogrammi, mis teevad täpselt sama asja, kuid üks neist on kirjutatud kodulabori teegi baasil, teine mitte.
// // Kodulabori kontrollerimooduli LED testimise programm. // Põhineb kodulabori teegil. // #include <homelab/pin.h> // // LED viiguga seotud parameetrite määramine muutujale // pin debug_led = PIN(B, 7); // // Põhiprogramm // int main(void) { // LED-i viigu väljundiks seadmine pin_setup_output(debug_led); // LED-i põlema panek pin_clear(debug_led); }
// // Kodulabori kontrollerimooduli LED testimise programm. // Põhineb otsesel registrite muutmisel. // #include <avr/io.h> // // Põhiprogramm // int main(void) { // LED viigu väljundiks seadmine DDRB |= (1 << 7); // LED põlema panek PORTB &= ~(1 << 7); }
Esimene näide kasutab viikude teeki (pin.h fail). Esmalt luuakse programmis pin-tüüüpi debug_led-nimeline muutuja, mis hoiab infot LED viigu kohta. Põhiprogrammis toimub selle viigu väljundiks seadmine läbi pin_setup_output-funktsiooni ja seejärel selle viigu madalaks määramine pin_clear-funktsiooniga, mille tulemusena LED süttib. Teises näites muutujaid ei kasutata, LED väljundiks määramine ja süütamine toimub viigu siini B suuna- ja väljundregistrite väärtuste muutmise teel. AVR-iga rohkem kursis olev lugeja märkab kindlasti, et tegelikult pole LED põlema paneku käsku kummaski näites vaja anda, kuna vaikimisi on AVR väljundite väärtus nagunii 0, kuid seda on siikohal tehtud korrektsuse pärast.
Mis siis viikude teegi ja registrite kasutamise vahe on? Vahe on kasutusmugavuses - teegiga on see lihtsam, sest ei pea registrite nimesid ja nende toimet peast teadma. Kõige olulisem teegi eelis on aga kohandatavus. Registreid kasutades tuleb viigu muutmiseks kogu programmis registrite nimed ja bitimaskid muuta, teegi puhul tuleb seda teha vaid programmi alguses, seal kus viigu muutuja algväärtustatakse. Otsesel registrite kasutamisel on üks näiline eelis - viigu kasutamine on vahetu ja see ei toimu läbi programmimälu ja aeganõudvate funktsioonide. Tegelikult on aga uuemad AVR-GCC kompilaatori versioonid niivõrd taibukad, et teisendavad teegi funktsioonid täpselt sama vahetuks registrite manipuleerimise käskudeks, nagu oleks seda otse programmis tehtud. Täpsustuseks tuleb öelda, et kompilaatori teisendusoskus kehtib ainult konstantsete üksikmuutujate kohta, mitte töö ajal muutuvate muutujate ja massiivide kohta.
Peale kontrollerimooduli asuvad LED-id ka digitaalsel sisend-väljundmoodulil. Need on elektriliselt ühendatud samamoodi nagu kontrollerimooduli LED, ehk katood on ühenduses AVR viiguga . Punane LED on ühenduses viiguga PC5, kollane viiguga PC4 ja roheline PC3. Nende kodulabori teegi põhine näidisprogramm näeb välja järgmine:
// // Kodulabori digitaalse sisend-väljundmooduli // LED-ide testimise programm. // #include <homelab/pin.h> // // LED-ide viikude määramine // pin led_red = PIN(C, 5); pin led_yellow = PIN(C, 4); pin led_green = PIN(C, 3); // // Põhiprogramm // int main(void) { // LED-ide viikude väljundiks seadmine pin_setup_output(led_red); pin_setup_output(led_yellow); pin_setup_output(led_green); // Rohelise LED põlema panek pin_clear(led_green); // Punase ja kollase LED kustutamine pin_set(led_red); pin_set(led_yellow); }
Vajalikud teadmised: [HW] Digitaalne moodul, [AVR] Registrid, [AVR] Sisendid-väljundid, [LIB] Viikude teek, [PRT] Valgusdiood
Lüliti on elektromehhaaniline seade elektriahela kokku- ja lahtiühendamiseks. Lüliteid on erinevaid, kuid tüüpiline mehhaaniline lüliti koosneb klemmidest, mida saab omavahel mehhaaniliselt ühendada. Klemmide ühenduse korral on elektriahel suletud ja lülitit võib läbida elektrivool. Kui klemmid on lahti, on elektriahel avatud ja elektrivool lülitit läbida ei saa.
Lülititega saab otseselt elektriahelaid pingestada, kuid neid saab kasutada ka anduritena. Lüliti anduri funktsioonis on ka selle harjutuse teema, seepärast on vaatluse alt välja jäetud spetsiifilised kõrgepinge ja suure voolu lülitid. Lülitid erinevad ka kontaktide arvu ja nende ühendamise meetodilt. On olemas kahe kontaktiga lüliteid, kuid ka duubellüliteid, kus ühendatakse kontaktide paarid. On surunupp-, ?klahv-, liug- ja tumblerlüliteid ning lüliteid, mis vajutades ei sulge elektriahelat, vaid katkestavad.
Eri liiki lülititel on erinev skemaatiline tähis. Edaspidi on toodud tüüpilisemad elektroonikaskeemides kasutatavad lülitid ja nende elektrilised tähised:
Lüliti kasutamiseks andurina mikrokontrolleri juures ühendatakse lüliti üks kontakt mikrokontrolleri viiguga, mis määratakse programmis sisendiks. Kui toimub kontakti ühendamine maa- või toitepotentsiaaliga, muutub ka mikrokontrolleri viigule vastava siini biti väärtus. Loogiline variant on kasutada tumbler-lülitit, mis võimaldab üht kontakti ühendada valitud kontaktiga (antud juhul siis maa või toitega), kuid see pole päris nii lihtne. Põhjus on selles, et ümberlülitamise hetkel ei ole kontaktid omavahel ühenduses. See hetk on väga lühike (millisekundites), kuid sellesama hetke jooksul pole mikrokontrolleri sisendviik kuhugi ühendatud ja sel on määramata väärtus. Elektromagnetiliste häirete tõttu (mis on igas skeemis ja igal pool) võib mitte kuhugi ühendatud sisendviik täiesti suvalistel ajahetkedel omada 0 või 1 väärtust.
Häired teevadki lülitite kasutamise keerukamaks. Üks peamine meetod määramata olekute vältimiseks on mikrokontrolleri sisend läbi takisti ühendada kas maa- või toitepotentsiaaliga. Sellises funktsioonis olevat takistit nimetatakse inglise keeles kas pull-down- või pull-up-takistiks. Tavaliselt jääb pull-up- või pull-down-takistite takistus mõnest kilo-oomist ühe mega-oomini. Kui lüliti on avatud, jääb sisendile pinge, millele takisti on ühendatud, kui lüliti sulgeda, rakendub sisendile lüliti pinge, sest lüliti takistus on palju väiksem kui takisti oma. Sisuliselt on tegu pingejaguriga.
Pull-up- või pull-down-takistiga võib andurina kasutada ka lihtsat kahekontaktilist lülitit, nii et lüliti ühendab sisendi ühe potentsiaaliga ja takisti teisega. Tavaliselt on mikrokontrolleritel ka sisseehitatud pull-up- või pull-down-takisti kasutamise võimalus, mistõttu ei pea skeemi eraldi takistit lisamagi. Näiteks AVR mikrokontrollerites on IO viikudel 20 kuni 50 kilo-oomised pull-up takistid.
Olgu öeldud, et mehhaaniliste lülititega kaasneb siiski veel üks probleem – kontaktide põrkumine. See põhjustab lülitamise hetkel mitmeid väga lühiajalisi väärlülitusi. Seda teemat on käsitletud järgmises peatükis. Selle peatüki näiteid probleem praktiliselt ei mõjuta.
Kodulabori digitaalsel sisend-väljundmoodulil on kolm surunupp-lülitit. Lülitid ühendavad mikrkontrolleri viike maaga, kuid mitte otse, vaid läbi takisti – seda põhjusel, et juhuslikul mikrokontrolleri viikude väljundiks määramisel neid nupuvajutusel ei lühistataks. Lülititel on ka pull-up-takistid, kuid need on palju suurema takistusega kui kaitsetakistid, nii et nupu allavajutamisel jääb vastavale mikrokontrolleri viigule ikkagi 0V lähedane pinge.
Lülitid asuvad viikudel PC0, PC1 ja PC2. Lülitite oleku lugemiseks tuleb mikrokontrolleri vastavad viigud määrata sisendiks. AVR siseseid pull-up-takisteid ei pea tööle rakendama, sest, nagu öeldud, on viikudel juba välised takistid. Kui nupp alla vajutada, on viigule vastaval siinil biti väärtus 0, kui nupp lahti lasta, siis väärtus 1. Selleks et näha, kas mikrokontroller sai nupuvajutusest aru, võib kasutada LED indikaatoreid.
Nuppude kasutamise näidiskood põhineb kodulabori viikude teegil, mida on tutvustatud valgusdioodi näites:
// // Kodulabori digitaalse sisend-väljundmooduli // nuppude testimise programm. // #include <homelab/pin.h> // // LED-ide ja nuppude viikude määramine // pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; pin buttons[3] = { PIN(C, 2), PIN(C, 1), PIN(C, 0) }; // // Põhiprogramm // int main(void) { unsigned char i; // LED-ide viikude väljundiks ja nuppude // viikude sisendiks seadmine for (i = 0; i < 3; i++) { pin_setup_output(leds[i]); pin_setup_input(buttons[i]); } // Lõputu tsükkel while (true) { // Igale nupule vastab üks LED, mis süttib nuppu alla vajutades for (i = 0; i < 3; i++) { pin_set_to(leds[i], pin_get_value(buttons[i])); } } }
Toodud näites on LED-id ja nupud defineeritud massiivina – see võimaldab neid kasutada for-tsüklis. Programmi käivitamisel määratakse LED-ide viigud väljundiks ja nuppude omad sisendiks. Programmisiseses lõputus tsüklis toimub pidev nuppude oleku pärimine ja neile vastavate LED-ide oleku määramine. Esimene nupp süütab rohelise LED, teine kollase ja kolmas punase.
Selle näite puhul võib tähelepanelikum õppur märgata, et kompileeritud programm on oma lihtsusest hoolimata natuke suurem kui arvata võiks. Põhjus on selles, et LED-ide ja nuppude viigud on defineeritud massiivina, kuid nagu valgusdioodi harjutuses öeldud, kompilaator viikude massiive ei optimeeri (lihtsusta). Kompileeritud programm oleks kompaktsem, kui kõigi LED-ide ja nuppude kasutamine käiks individuaalselt, ilma for-tsüklita, kuid siis oleks jällegi programmi lähtekood pikem ja monotoonsem. Kolme nuppude ja LED-ide paari puhul on raske eelistada üht või teist lähenemist, kuid nende arvu kasvades muutub üksikute koodiridade lisamine järjest ebaefektiivsemaks, ja mõistlikumaks osutub massiividega meetod.
Vajalikud teadmised: [HW] Digitaalne moodul, [AVR] Sisendid-väljundid, [LIB] Viikude teek, [LIB] Viite teek, [PRT] Lülitite näide
Nii nagu lüliteid tutvustavas peatükis öeldud, eksisteerib mehhaaniliste lülititega kontaktide põrkumise probleem, mida siin materjalis on nimetatud väreluseks. Kuna kontaktid on tehtud metallist, millel on teatav elastsus, siis kontaktide ühendamise või lahti-ühendamise hetkel need põrkuvad ning tulemusena tekib hulga väärlülitusi. Lülituste arv ja kestus sõltub lülitist, kuid enamasti jääb see mõne millisekundi piiresse. Kui lülitit kasutatakse mõne elektriseadme töölelülitamiseks, siis pole see suur probleem, kuid kui lüliti on kasutusel seadme juhtimiseks, võib mitmekordne vajutamine kahjulik olla.
Põhiline sädelust välistav meetod on filtreerimine. Filtreerida saab nii elektriliselt kui ka tarkvaraliselt. Elektriliseks filtreerimiseks tuleb lüliti järgi lisada madalpääsfilter – näiteks RC filter - mis silub pingemuutusi ja sellest tulenevalt mikrokontrolleri viik ei omanda hetkelisi väärtusi. RC filter on toodud kõrvaloleval joonisel? Tarkvaraline filtreerimine toimub põhimõttel, et viigu, kuhu lüliti on ühendatud, väärtust loetakse mitmel korral ja kui kõikidel kordadel on viigu väärtus sama, siis sellest järeldatakse, et lüliti omab kindlat asendit ning tegu pole sädelusega. Igasugusel filtreerimisel peab aga arvestama viitega, mis tekib oleku kindlaksmääramisega.
Kodulabori lülititel ei kasutada elektrilist filtreerimist, sest siis ei saaks harjutada tarkvaralist väärlülituste elimineerimise ülesannet. Harjutus koosneb kahest osast. Esimese ülesande eesmärk on demonstreerida digitaalse sisend-väljundmooduli nuppude kontaktide põrkumist. Selleks on järgmine programm, mis iga nupuvajutuse peale paneb põlema järgmise LED. Väär-nupuvajutuste tõttu süttivad LED-id aga mitmeid kordi ja näib, et lausa suvaliselt.
// // Kodulabori digitaalse sisend-väljundmooduli // nuppude põrkumise demonstreerimise programm. // #include <homelab/pin.h> // // LED-ide ja nupu viikude määramine // pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; pin button = PIN(C, 0); // // Põhiprogramm // int main(void) { unsigned char new_value, old_value = 0; unsigned char index, counter = 0; // LED-ide viikude väljundiks seadmine for (index = 0; index < 3; index++) { pin_setup_output(leds[index]); } // Nupu viigu sisendiks määramine pin_setup_input(button); // Lõputu tsükkel while (true) { // Nupu oleku lugemine new_value = pin_get_value(button); // Kontroll, kas nupp vajutati alla, // ehk kas uus olek on 1 ja vana 0 if ((new_value) && (!old_value)) { // Loenduri suurendamine ja mooduli 3 võtmine counter = (counter + 1) % 3; // Loenduri väärtusele vastava LED-i süütamine for (index = 0; index < 3; index++) { pin_set_to(leds[index], index != counter); } } // Peame vana olekut meeles old_value = new_value; } }
Tarkvaraliseks filtreerimiseks on mitmeid meetodeid. Seda võib teha lihtsalt ja keeruliselt, mõlemal juhul oma eeliste ja puudustega. Kui programm on selline, et nupuvajutusi oodatakse harva, võib pärast nupu allavajutamise registreerimist lisada pika pausi, mis välistab reageerimise põrkumisest tekkinud lülitustele. Samas tuleb sellise lahenduse puhul arvestada, et kui kasutaja hoiab nuppu pikalt all, reageerib programm ka nupu lahtilaskmisel tekkinud väärlülitustele. Töökindlam on programm, mis kontrollib nupu olekut teatud aja jooksul mitu korda (mida rohkem ja mida pikema aja jooksul, seda kindlam). Järgnevalt on toodud digitaalse sisend-väljund-laiendusmooduli nupu filtreeritud väärtuse lugemise funktsioon:
// // Funktsioon mõne IO laiendusplaadi lüliti filtreeritud väärtuse lugemiseks // unsigned char pin_get_debounced_value(pin button) { unsigned char buffer = 0xAA; unsigned char timeout = 100; // Ootame, kuni nupu olek on selgunud või oleku selgitamine aegunud while (timeout-- > 0) { // 8-kohalise (bitise) olekupuhvri pidamine // Kõik eelmised olekud (bitid) nihutatakse vasakule // ja paremale lisatakse uus olek (bitt). buffer <<= 1; buffer |= (pin_get_value(button) ? 0x01 : 0x00); // Kui kõik 8 bitti on kõrged, siis // nupp on kindlasti alla vajutatud if (buffer = 0xFF) { return 1; } // Kui kõik 8 bitti on madalad, siis // nupp on kindlasti üleval if (buffer = 0x00) { return 0; } // Paus 1 millisekund // See funktsioon sisaldub kodulabori teegis sw_delay_ms(1); } // Kui olekut ei õnnestunud välja selgitada, siis oletame, // et nuppu ei vajutatud return 0; }
See funktsioon kasutab viite tekitamise funktsiooni, millest räägib lähemalt vastav harjutusülesanne. Siinkohal pole viite funktsiooni kohta vaja suurt midagi teada peale selle, et see tekitab 1-millisekundilise viite iga nupu oleku lugemise tsükli lõpus. Kui nupp on kaheksal lugemise korral samas asendis, tagastab see loetud asendi. Kogu protseduur võib nupu ebastabiilsuse korral kesta kuni 100 ms. Funktsioon sisaldub juba viikude teegis, nii et näite läbimiseks ei pea seda oma programmi lisama. Selle proovimiseks tuleb ülesande esimest poolt natukese muuta – kaasata programmi viite tekitamise teek ja kohas, kus nupu väärtust otse loeti, kasutada filtriga funktsiooni. Tulemus on järgmine:
// // Kodulabori digitaalse sisend-väljundmooduli // nuppude põrkumise filtreerimise programm. // #include <homelab/delay.h> #include <homelab/pin.h> // // LED-ide ja nupu viikude määramine // pin leds[3] = { PIN(C, 5), PIN(C, 4), PIN(C, 3) }; pin button = PIN(C, 0); // // Põhiprogramm // int main(void) { unsigned char new_value, old_value = 0; unsigned char index, counter = 0; // LED-ide viikude väljundiks seadmine for (index = 0; index < 3; index++) { pin_setup_output(leds[index]); } // Nupu viigu sisendiks määramine pin_setup_input(button); // Lõputu tsükkel while (true) { // Nupu oleku lugemine new_value = pin_get_debounced_value(button); // Kontroll, kas nupp vajutati alla, // ehk kas uus olek on 1 ja vana 0 if ((!new_value) && (old_value)) { // Loenduri suurendamine ja mooduli 3 võtmine counter = (counter + 1) % 3; // Loenduri väärtusele vastava LED süütamine for (index = 0; index < 3; index++) { pin_set_to(leds[index], index != counter); } } // Peame vana olekut meeles old_value = new_value; } }
Kui nüüd programmi proovida, siis LED-id süttivad täpselt sellises järjekorras nagu kasutaja nupplülitit vajutab.
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Käesolev peatükk tutvustab mikrokontrollerite ajastuse võimalusi - taimereid ja viiteid. Need on abiks rakendustes, kus on vaja mõõta aega, tekitada pause või protsesse täpselt ajastada. Oma olemuselt on taimerid ja viited ühest küljest erinevad asjad, teisest küljest sarnased. Taimerid on mikrokontrolleri füüsilised moodulid, mis töötavad mikrokontrolleri protsessorist sõltumatult, viited on aga tarkvaralised programmilõigud, mis just nimelt kulutavad protsessori tööaega. Samas tinglikult öeldes töötavad nad mõlemad mikrokontrolleri töötakte lugedes.
Mõlemal meetodil on omad head ja vead, millest lähemalt räägivad nende kohta käivad harjutused. Korrektsuse huvides võib öelda, et algselt olid taimerid ikkagi eraldiseisvad integraallülitused elektriskeemis, mitte osa mikrokontrollerist. Eraldiseisvad taimerite kiibid pole ka tänapäeval kuhugi kadunud, sest mõnes rakenduses pole mikrokontrollerit ennast vajagi ja mõned taimerid on võimekamad kui mikrokontrollerisse integreeritud.
Taimerid on ka lihtsast aja loendamise seadmest arenenud keerukateks signaalide vastuvõtmise või genereerimise süsteemideks. Nad moduleerivad ja demoduleerivad signaale ning nad on võimelised taktsignaali kordistama või jagama. On olemas ka spetsiaalsed aeg-digitaalmuundurid (TDC, inglise keeles time-to-digital converter), mis suudavad registreerida aega pikosekundites. Siinkohal piirduvad harjutused siiski lihtsamate taimeritega.
Vajalikud teadmised: [HW] controller, [AVR] AVR arhitektuur, [LIB] Viikude teek, [LIB] Viite teek
Tihti on mikrokontrollerite programmis vaja tekitada viiteid, et tegevusi ajastada või nende lõppu oodata. Üks idee poolest lihtsamaid meetodeid mikrokontrolleri tegevuses paus tekitada on selle protsessor mingi muu tegevusega üle koormata - näiteks panna see lugema suuri numbreid. Protsessori taktsagedusest saab välja arvutada, mitmeni see numbreid loendama peaks, et kindlat ajalist viidet tekitada. Teoreetiliselt tekitaks siis mingi arvu loendamine nullist protsessori taktsageduse väärtuseni hertsides viite üks sekund. Praktikas see päris nii lihtne ei ole ning põhjuseid on mitmed.
Kui mikrokontrolleri protsessor arvutab arvudega, mille kahendkuju on sama lai kui selle sisemine siin (AVR puhul 8-bitti), siis protsessoritel võtab üks aritmeetiline tehe, näiteks arvu liitmine ühega, aega 1 protsessori töötakt. Selleks et arvutada tuhandete või miljonitega, peab arv olema 16- või 32-bitine ja nende arvutamiseks kulub 8-bitistel protsessoritel rohkem kui 1 töötakt. Niisiis, suurte arvude puhul peab tundma protsessori sisemust - täpsemalt selle käsustikku.
Kuna kõrgtaseme keeles (näiteks C-keeles) programmeerides ei kirjutata programmi otse käsustiku baasil, peab tarkvaralise viite tekitamiseks tundma ka kompilaatorit, mis programmi masinkoodi teisendab. Just sellest sõltub, mitu instruktsiooni (ja sellest tulenevalt mitu takti) kulub aritmeetilisteks arvutusteks. Keerukust lisab veel asjaolu, et kompilaator võib programmi masinkoodi teisendada mitut moodi - näiteks tehes masinkoodi võimalikult mälusäästlikuks või võimalikult kiiresti täidetavaks. Neid kompilaatori tegevusi nimetatakse optimeerimiseks. Erinevate optimeerimise režiimidega tuleb ka tarkvaralise viite masinkood ja selle ajaline kestus erinev.
Järgnevalt on toodud näide tarkvaralise viite tekitamisest AVR mikrokontrolleriga. Kirjutatud on C-keele programmilõik, mis loendab for-tsüklis muutujat x nullist sajani. Iga tsükli sees toimub ühe mittemidagitegeva tühiinstruktsiooni täitmine. Seda on seal vaja, kuna tsükli sisu tühjaks jättes optimeerib kompilaator tsükli programmist üldse välja, sest see on tema arvates kasutu.
unsigned char x; // Tsükkel seni kuni x on 100 for (x = 0; x < 100; x++) { // Tühiinstruktsiooniga nop asm volatile ("nop"); }
Siinkohal on aga toodud sama C-keele programmilõik pärast kompileerimist. Vasakpoolsed 2 heksadetsimaalarvu on masinkood ja paremal on assemblerkeeles käsk koos operandi(de)ga. Masinkood ja assemblerkeel on üks-üheselt seotud, assembler on lihtsalt masinkoodi inimesele loetaval kujul esitamiseks. Kompileerimisel on kasutatud programmi pikkuse optimeerimist (kompilaatori parameeter -Os).
80 e0 ldi r24, 0x00 ; r24 registrisse arvu 0 laadimine 00 00 nop ; Tühioperatsioon 8f 5f subi r24, 0xFF ; r24 registrist 255 lahutamine, ehk +1 liitmine 84 36 cpi r24, 0x64 ; r24 registri võrdlemine arvuga 100 e1 f7 brne .-8 ; Kui võrdlus oli väär, siis siire 8 baiti tagasi
Kompileeritud kujul on näha, mis tegelikult C-keele tsüklist saab, ja selle järgi saab arvutada, mitu takti ühe tsükli perioodi puhul kulub. Infot instruktsioonide toime ja tööaja kohta leiab AVR käsustiku andmelehest. Antud näites kulub ühes tsükli perioodis 4 instruktsiooni täitmiseks 4 takti, sest kõik instruktsioonid võtavad ühe töötakti. Lisaks kulub enne tsüklit 1 takt laadimisinstruktsiooni jaoks ja tsüklist väljudes 1 lisatakt. Oletades, et kontrolleri töötakt on 14,7456 MHz, võib välja arvutada kogu programmilõigu tekitatud ajalise viite:
(1 + 100 * 4 + 1) / 14745600 = 27.26 μs
Näites tekitatud viide on mikrosekundites ja kasutav muutuja on 8-bitine, seega on ka masinkood üsna lihtne. Selleks et tekitada pausi millisekundites, on vaja loendada palju suuremaid arve ja siis läheb ka masinkood pikemaks. Võib kasutada ka üksteise sees töötavaid tsükleid, kuid selle meetodi puhul pole kogu viide lineaarses sõltuvuses tsüklite arvust, sest iga tsükli tasemega tekivad pisikesed lisaviited.
Käesoleva harjutuse eesmärk ei ole siiski masinkoodi tasandil täpset tarkvaralist viidet tekitada, sest see on üsna peen töö ja pealegi on viite tekitamiseks avr-libc ja kodulabori teegis juba funktsioonid olemas. Need tulevad ka näites kasutusele.
Tarkvaralise viite puhul on aga oluline teada, et hoolimata oma põhimõttelisest lihtsusest on see äärmiselt ebaefektiivne meetod energiatarbe seisukohast. Kõigil neil taktidel, mil mikrokontroller tegeleb kasutu loendamisega, kulub energiat. Patareidega rakenduses ei ole seega soovitatav pikki tarkvaralisi viiteid teha, vaid tuleks kasutada raudvaralisi taimereid, mis töötavad iseseisvalt ning äratavad protsessori uneolekust üles, kui on vaja midagi teha.
Järgnev programmikood käib tarkvaralise viite funktsiooni sw_delay_ms kohta, mis tekitab parameetriga count etteantud viite millisekundites. Funktsioon kasutab omakorda avr-libc teegi poolenisti assemblerkeeles kirjutatud funktsiooni _delay_ms. Põhjus, miks harjutuses pole kohe _delay_ms kasutatud, on selles, et _delay_ms puhul võivad pikkade viidetega probleemid tekkida. sw_delay_ms-funktsioon võimaldab aga probleemideta kuni 65535 ms viidet.
// // Tarkvaraline viide millisekundites // void sw_delay_ms(unsigned short count) { // Viite muutuja nullini loendamine while (count-- > 0) { // 1ms viide spetsiaalse funktsiooniga _delay_ms(1); } }
Toodud funktsiooni kasutamiseks on järgnev programm, mis tekitab lõputus tsüklis kaks viidet: 100 ms ja 900 ms. Lühema viite jooksul LED põleb ja pikema ajal on kustunud - tulemusena LED perioodiliselt vilgatab.
// // Kodulabori tarkvaralise viite demonstratsioonprogramm. // Programm vilgutab ~1 sekundi järel hetkeks LED-i. // #include <homelab/pin.h> #include <homelab/delay.h> // // Test LED-i viigu määramine // pin debug_led = PIN(B, 7); // // Põhiprogramm // int main(void) { // LED-i viigu väljundiks seadmine pin_setup_output(debug_led); // Lõputu tsükkel while (true) { // LED põlema panek pin_clear(debug_led); // Tarkvaraline paus 100 millisekundit sw_delay_ms(100); // LED kustutamine pin_set(debug_led); // Tarkvaraline paus 900 millisekundit sw_delay_ms(900); } }
Kuigi näib, et LED vilgatab tõesti täpselt 1 sekundi järel, on aeg tegelikult siiski natuke pikem, sest LED ja viite funktsioonide väljakutsumine võtavad ka aega.
Vajalikud teadmised: [HW] controller, [AVR] AVR taimerid, [LIB] Viikude teek, [LIB] Viite teek, [LIB] Loendurite teek, [PRT] Tarkvaralise viite harjutus
Tarkvaraline viide pole ainus meetod pausi tekitada. Sama asja saab teha ka taimeriga. Taimer on riistvaraline kindla sagedusega suurenev või vähenev loendur. Loenduri taktsignaali saab enamasti tekitada mikrokontrolleri töötaktist või mingist välisest taktist. Taktsignaali sagedust saab üldjuhul ka läbi jagada, et väiksem taktsagedus saavutada - seda tehakse taktijaguriga, mida inglise keeles nimetatakse kui prescaler. Oluline on siinkohal siiski fakt, et fikseeritud taktsagedusega loenduri väärtus on lineaarses sõltuvuses ajast. Aja saab välja arvutada, korrutades loenduri taktisignaali perioodi loenduri väärtusega.
AVR loendurid saab panna loenduri ületäitumisest (inglise keeles overflow) või kindla väärtuse saavutamisest (inglise keeles compare match) teavitama. Ületäitumine tekib hetkel, kui loendur on omistanud maksimaalse võimaliku väärtuse ja alustab uuesti nullist loendamist. Väärtuse saavutamise kontroll toimub loenduri suurendamise hetkel selle uut väärtust kasutaja poolt määratud väärtusega võrreldes. Sündmuse tekkimise korral seatakse AVR olekuregistrites vastavad bitid automaatselt kõrgeks.
Kui nüüd loendur ära seadistada nii, et mingi sündmus tekib kindla aja pärast, siis piisabki soovitud viite saamiseks olekubiti kõrgeks minemise ootamisest. Erinevalt tarkvaralisest viitest ei sõltu taimerite töö kompilaatorist, mis teeb nende kasutamise töökindlamaks. Samas võib AVR loendurite mitmekesisuse (või ka segasuse) tõttu nende seadistamine üsna tülikas tunduda. Olenevalt mikrokontrolleri taktsignaalist võib ka juhtuda, et see ei jagu täpselt soovitud viite perioodiga ja viide ei ole täpne.
Allpool olev programmikood on aga taimeril põhinev viitefunktsioon, mida on natuke lihtsustatud. Loendamise põhimõte on sama mis tarkvaralise viite funktsioonilgi - tekitatakse soovitud arv 1 ms pikkuseid viiteid. Viite tekitamiseks on kasutusel ATmega128 8-bitine loendur 0. Eelnevalt on juba välja arvutatud, et 14.7456 Mhz taktsageduse puhul peab loenduri taktsignaal olema vähemalt 64 korda jagatud, et 1 ms jooksul 8-bitine loendur üle ei täituks. See, mis väärtust loendur omama peab, et ületäitumine toimuks 1 ms järel, on esitatud avaldise kujul ja omistatud muutujale timer_start. Nimetatud taktsageduse puhul peaks siis loenduri väärtus 25.6 olema, kuid kuna murdarve kasutada ei saa, siis loenduri algväärtuseks saab 26. Siin tekib paraku ka viga viite ajas, kuid see on üsna väike (-1.7 μs).
Tsüklis toimub loenduri algväärtustamine ja ületäitumise lipukese nullimine (sellesse 1 kirjutades). Seejärel oodatakse, kuni loendur loendab algväärtusest 256-ni, ehk ületäitumiseni. Ületäitumise hetkel läheb ületäitumise lipuke kõrgeks ja 1 ms viide ongi toimunud. Funktsiooni lõpus taimer peatatakse.
// // Riistvaraline viide millisekundites // void hw_delay_ms(unsigned short count) { // Taimeri algväärtuse arvutamine register unsigned char timer_start = 256 - F_CPU / 1000 / 64; // Taimeri käivitamine timer0_init_normal(TIMER0_PRESCALE_64); // Viite muutuja nullini loendamine while (count-- > 0) { // Taimeri algväärtustamine timer0_set_value(timer_start); // Ületäitumise lipukese nullimine timer0_overflow_flag_clear(); // Ületäitumise ootamine while (!timer0_overflow_flag_is_set()) { asm volatile ("nop"); } } // Ületäitumise lipukese nullimine timer0_overflow_flag_clear(); // Taimeri peatamine timer0_stop(); }
Järgnevalt on toodud samasugune programm nagu tarkvaralise viite näiteski. Lühemal 100 ms poolperioodil LED süüdatakse, pikemal 900 ms poolperioodil kustutatakse. Tulemusena vilgatab LED iga sekundi järel. Paraku pole ka selles näites periood täpselt 1 sekund, sest programmi täitmine igas tsüklis võtab ka aega. Täpseks ajastuseks tuleb kasutada 16-bitist taimerit koos katkestustega .
// // Kodulabori raudvaralise viite demonstratsioonprogramm. // Programm vilgutab ~1 sekundi järel hetkeks LED. // #include <homelab/pin.h> #include <homelab/delay.h> // // Test LED viigu määramine // pin debug_led = PIN(B, 7); // // Põhiprogramm // int main(void) { // LED viigu väljundiks seadmine pin_setup_output(debug_led); // Lõputu tsükkel while (true) { // LED põlema panek pin_clear(debug_led); // Riistvaraline paus 100 millisekundit hw_delay_ms(100); // LED kustutamine pin_set(debug_led); // Riistvaraline paus 900 millisekundit hw_delay_ms(900); } }
Vajalikud teadmised: [HW] Digitaalne moodul, [AVR] AVR katkestused, [AVR] AVR loendurid, [LIB] Viikude teek, [LIB] Viite teek, [LIB] Taimerite teek, [PRT] Tarkvaralise viite harjutus
Käesoleva praktilise harjutuse eesmärk on demonstreerida katkestuste kasutamist loendurite näitel. Katkestused on mikrokontrolleris esinevatele sündmustele reageerivad programmilõigud. Katkestusi kasutatakse tavaliselt kiiresti sündmusele reageerimiseks, kuid neid võib kasutada ka mitme paralleelse protsessi täitmiseks, täpselt ajastatud tegevuseks ning voolu säästmiseks. Näiteks on katkestuste abil võimalik panna vilkuma LED, mille vilkumise sagedus ei sõltu sellest, mis programmis parasjagu toimub.
Järgnev programm näitab, kuidas seadistada loendurit katkestust tekitama. Programmis on kasutusel 2 digitaalse mooduli LED, millest punase olekut muudetakse perioodiliselt tarkvaralise viitega ja roheline, mille olekut muudetakse katkestuse tekkimisel. Tarkvaralise viitega LED vilgutamise kohta on olemas eraldi harjutus ja seda siinkohal selgitatud pole. Põhieesmärk on selgitada loendurite teegi ja katkestuste kasutamist.
Programmi alguses toimub 16-bitise loendur/taimer 1 seadistamine timer1_init_ctc-funktsiooniga. Selle funktsiooni abil seatakse loendur CTC (inglise keeles Clear Timer on Compare Match-režiimi, kus taimeri maksimaalseks väärtuseks pole mitte 216 - 1, vaid see on valitav. Antud juhul määratakse maksimaalseks väärtuseks ICR1 registri väärtus. Loenduri jaguriks on 1024 ja ICR1 väärtuseks 14400, mille tulemusena 14.7456 Mhz taktsageduse puhul on loenduri perioodiks täpselt 1 sekund. Seda on lihtne arvutada valemist:
f = 14745600 Hz / 1024 / 14400 = 1
Pärast loendur 1 maksimaalse väärtuse saavutamise katkestuse lubamist tuleb katkestuse tekkimine lubada ka globaalselt, ehk siis üle kogu mikrokontrolleri. Globaalseks katkestuste lubamiseks on sei- ja keelamiseks cli-funktsioon. Nende funktsioonide ja katkestuste programmilõigu defineerimiseks peab programmi kaasama ka avr/interrupt.h-päisefaili. Katkestuse programmilõik defineeritakse makrofunktsiooniga ISR, mille parameetriks on katkestuse vektori nimi. Loendur 1 väärtuse saavutamise katkestuse vektori nimi on TIMER1_CAPT_vect.
// // Kodulabori loenduri katkestusega vilkuva LED näide. // Võrdluseks katkestusega vilkuvale LED-ile // töötab paralleelselt ka tarkvaralise viitega vilkuv LED. // #include <homelab/pin.h> #include <homelab/delay.h> #include <homelab/timer.h> #include <avr/interrupt.h> // // LED-ide viikude määramine // pin led_red = PIN(C, 5); pin led_green = PIN(C, 3); // // Katkestus // ISR(TIMER1_CAPT_vect) { // Rohelise LED oleku muutmine pin_toggle(led_green); } // // Põhiprogramm // int main(void) { // LED-ide viikude väljundiks seadmine pin_setup_output(led_red); pin_setup_output(led_green); // Taimeri seadistamine CTC režiimi timer1_init_ctc( TIMER1_PRESCALE_1024, TIMER1_CTC_TOP_ICR); // Taimeri maksimaalne väärtus 14400 mis // teeb perioodi pikkuseks 1s // Valem: 14.7456Mhz / 1024 = 14400 timer1_set_input_capture_value(14400); // Väärtuse saavutamise katkestuse lubamine timer1_input_capture_interrupt_enable(true); // Globaalne katkestuste lubamine sei(); // Lõputu tsükkel while (true) { // Tarkvaraline paus 1000 millisekundit sw_delay_ms(1000); // Punase LED oleku muutmine pin_toggle(led_red); } }
Programmi käivitades on näha, et hoolimata sellest, mida mikrokontroller põhiprogrammis teeb, toimuvad katkestused ja roheline LED vilgub.
Kui programmil lasta töötada mõni minut, tuleb välja oluline aspekt, mida tarkvaralise viite harjutuses nii lihtsalt näha polnud. Kuigi punast LED vilgutavas tsüklis olev viide on 1000 ms, siis tegelik aeg, mis kulub iga tsükli täitmiseks, on natukese suurem. Põhjus on selles, et ka LED oleku muutmine, viite funktsiooni väljakutsumine ja tsükli täitmine võtavad protsessoril mõned taktid täitmise aega. Tulemusena jääb punase LED vilkumine rohelise LED vilkumisest pidevalt maha. Just sel põhjusel ei ole soovitatav ka kellaaja loendureid ja muid täpselt ajastatud tegevusi teha viitega, vaid loenduri katkestustega.
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Üks lihtsamaid meetodeid mikrokontrolleri töötamises veendumiseks on lisada programmi koodilõik, mis vilgutab LED-i või mitut. Tihtipeale jääb sellest aga väheks, sest vaja oleks edastada rohkem infot kui LED-iga võimalik, ning mõni rakendus eeldab kasutajaliidest, kus kuvatakse tekste või numbreid. Siinkohal tulevad appi kõiksugu indikaatorid ja ekraanid, kus saab kuvada numbreid, tekste või lausa pilte. Arvuti monitor on üks tuntumaid info kuvamise seadmeid, mille kasutamises tüüpiline programeerija vaevalt et midagi erilist näeb, kuid mikrokontrolleritega tuleb iga piksli ekraanile saamisega kõvasti vaeva näha.
Järgnevad peatükid tutvustavad lihtsamat liiki näidikuid ja ekraane - LED segmentidega indikaatorit ja kaht liiki monokromaatilist LCD ekraani. Peale nende kasutatakse mikrokontrolleritega aktiivselt ka LED maatrikseid ja tänapäeval levinud värvilisi orgaanilisi LED (OLED) ekraane. Kunagi olid levinud ka höögniidiga numberindikaatorid, kus iga numbri jaoks oli eraldi helendav hõõgniit. Olemas on ka elektromehaanilised ekraanid, kus erinevat värvi tahkudega segmente pööratakse füüsiliselt. Viimase ajal on järjest populaarsem elektrooniline paber, mis imiteerib trükist. Esmased e-paberid (lühend elektroonilisest paberist) koosnesid erinevat värvi külgedega kuulikestest, mida pöörati elektriväljas. Uuemad e-paberid sisaldavad aga pisikesi kapsleid, kus kahte värvi erinevalt laetud osakesi mõjutatakse elektriväljaga kas põhja vajuma või pinnale jääma.
Vajalikud teadmised: [HW] Digitaalne moodul, [LIB] Viite teek, [LIB] Indikaatori teek, [PRT] Valgusdiood
7-segmendiline LED numberindikaator on seitsmest number 8 kujuliselt paigutatud valgusdioodist koosnev näidik. Vastavaid LED-e (segmente) süüdates või kustutades saab nendega kuvada numbreid nullist üheksani ning mõningaid tähti.
Elektriliselt on kõigi LED-ide anoodid ühendatud ühise anoodi viiguga ca. LED-e süüdatakse nende katoode (a, b, c…) lülitades. Tavaliselt kasutatakse mitut numberindikaatorit, et kuvada mitmekohalisi arve - selleks puhuks on indikaatorid varustatud ka koma(punkti) segmendiga dp. Kokkuvõttes on ühel indikaatoril siiski 8 segmenti, kuid nimetatakse neid ikkagi numbrisegmentide arvu järgi 7-segmendilisteks.
LED numberindikaatoreid on lihtne kasutada, sest neid võib juhtida kasvõi otse mikrokontrolleri viikudelt, kuid on ka spetsiaalseid draivereid. LED numberindikaatoreid on erinevat värvi, nad võivad olla väga eredad ja väga suured. Kogu ladina tähestiku kuvamiseks on olemas ka lisasegmentidega indikaatoreid.
Digitaalse mooduli plaadil on üks 7-segmendiline LED numberindikaator. Seda juhitakse läbi järjestikliidesega draiveri A6275. Draiveri järjestikliides on sarnane SPI-ga, kus kasutatakse ka taktsignaali ja andmesignaali. Erinevalt SPI-st pole kasutusel kiibi valikut (chip-select), kuid selle asemel on andmete lukustussignaal (latch). Nimetatud kolm liini on ühendatud ATmega128-ga järgevalt:
Andmed edastatakse bitthaaval andmeviigu kaudu. Iga kord, kui taktsignaal kõrgeks läheb, nihutatakse nihkeregistri sisu paremale ja kõige vasakpoolsemasse pesasse loetakse andmeviigult tulev bitt. Niiviisi laaditakse nihkeregistrisse 8 bitti. Kui lukustussignaal kõrgeks seada, laetakse nihkeregistri väärtus lukustusregistrisse, kus see jääb püsima kuni uue laadimiseni. Iga lukustusregistri pesa (bitt) on läbi voolulülituse seotud ühe numberindikaatori segmendiga. Segment põleb kõrge bitiväärtuse korral.
Numbrite kuvamiseks kodulabori digitaalse mooduli indikaatoril on kodulabori teeki kirjutatud järgnev funktsionaalsus:
// // Viikude seadistus // static pin segment_display_latch = PIN(G, 2); static pin segment_display_data_out = PIN(C, 6); static pin segment_display_clock = PIN(C, 7); // // Märgikaart. // Bitid tähistavad segmente. Madalaim järk A, kõrgeim DP. // static const unsigned char segment_char_map[11] = { 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111100, 0b00000111, 0b01111111, 0b01100111, 0b01111001 // E like Error }; // // 7-segmendilise indikaatori käivitamine // void segment_display_init(void) { // Set latch, data out and clock pins as output pin_setup_output(segment_display_latch); pin_setup_output(segment_display_data_out); pin_setup_output(segment_display_clock); } // // 7-segmendilisel indikaatoril numbri kuvamine // void segment_display_write(unsigned char digit) { unsigned char map; signed char i; // Numbri kontroll if (digit > 9) { digit = 10; } // Number segmentide kaardiks. map = segment_char_map[digit]; // Lukustussignaal maha pin_clear(segment_display_latch); // Bittide saatmine. Kõrgeim järk esimesena. for (i = 7; i >= 0; i--) { // Viigu seadmine vastavalt kaardi biti väärtusele pin_set_to(segment_display_data_out, bit_is_set(map, i)); // Taktsignaal kõrgeks hetkeks pin_set(segment_display_clock); _delay_us(1); // Taktsignaal madalaks pin_clear(segment_display_clock); _delay_us(1); } // Lukustussignaal peale pin_set(segment_display_latch); }
Numbrite ja “E” tähe kuvamiseks segmentidena on loodud konstantne massiiv segment_char_map, kus kõigi kaheksa segmentide põlemine on tähistatud bitiga 1 ja kustumine bitiga 0. Bitid kõrgemast madalamaks (binaarkujul vasakult paremale) tähistavad segmente DP, G, F, E, D, C, B, A. Draiveri juhtliides on teostatud tarkvaralise SPI-ga ehk andmesideviike programmis tarkvaraliselt juhtides. segment_display_init-funktsiooniga seatakse kõik kolm viiku väljundiks. Märgi kuvamiseks on segment_display_write-funktsioon, mis leiab massiivist märgi segmendikaardi ja edastab kõigi segmentide väärtused bitthaaval draiverile. Taktsignaali sageduseks on tarkvaraliste pausidega saadud ligikaudu 500 kHz.
Järgnevalt on toodud konkreetsem numberindikaatori kasutamise näiteprogramm. Programmis kasutatakse teegi eelnevalt kirjeldatud funktsioon. Programm loeb ligikaudu sekundilise intervalliga numbreid nullist üheksani. Selline loendamine on saavutatud hoopis suuremast arvust mooduli võtmisega.
// // Kodulabori sisend-väljundmooduli 7-segmendilise // LED indikaatori näidisprogramm // #include <homelab/module/segment_display.h> #include <homelab/delay.h> // // Põhiprogramm // int main(void) { int counter = 0; // 7-segmendilise indikaatori seadistamine segment_display_init(); // Lõputu tsükkel while (true) { // Loenduri üheliste väärtuse näitamine segment_display_write(counter % 10); // Loendamine väga pikalt counter++; // Paus 1 sekund sw_delay_ms(1000); } }
Vajalikud teadmised: [HW] LCD moodul, [LIB] Alfabeetilise LCD teek, [LIB] Viite teek, [PRT] Perioodilise katkestuse harjutus
Alfabeetiline LCD on vedelkristall-ekraan (inglise keeles liquid crystal display), mis on ette nähtud tähtede ja numbrite kuvamiseks. Inglise keeles nimetatakse seda kui alphanumeric LCD. Lihtsamates vedelkristall-ekraanides kasutatakse läbipaisvate elektroodide vahele paigutatud vedelat kristalli, mis muudab elektriväljas läbiva valguse polarisatsiooni. Elektroode katavad veel polarisatsioonifiltrid, mis tagavad, et kogu ekraani saab läbida vaid ühtpidi polariseeritud valgus. Kui vedelkristall elektrivälja mõjul polarisatsiooni muudab, siis valgus ekraani või selle osa (segmenti) läbida ei saa ning see paistab tume.
Põhiline iseloomustaja on alfabeetilise LCD juures tema segmentide paigutus. Ekraan on jagatud paljudeks indikaatoriteks. Igal indikaatoril on kas piisavalt palju segmente tähtede ja numbrite kuvamiseks või moodustub see väikesest ruudukujuliste segmentide (pikslite) maatriksist. Näiteks 5×7 pikslisest maatriksist piisab kõigi numbrite, ladina tähestiku ja täppidega tähtede kuvamiseks. Indikaatoreid on tavaliselt 1-4 rida ja 8-32 tulpa. Igal indikaatoril on väike vahe sees, täpselt nagu tekstis tähtedelgi.
Alfabeetiline LCD ekraan koosneb peale ekraani enda veel ka kontrollerist, mis vastavalt sideliidesest tulevatele käskudele juhib ekraani segmente. Kontrollerisse on eelnevalt sisse programmeeritud tähekaart, kus igal tähel, numbril või märgil on oma järjekorranumber ehk indeks. Ekraanil teksti kuvamine toimub põhimõtteliselt kontrollerile tähtede indekseid saates. Tegelikkuses tuleb LCD kontrolleritele ka mitmeid juhtkäske saata, enne kui midagi kuvama saab hakata. LCD ekraanide kasutamiseks tuleb tutvuda nende andmelehega, sest neid on väga erinevaid.
Alfabeetilised LCD ekraanid on üldjuhul passiivmaatriksiga, kus segmentide elektrivälja uuendamine toimub kordamööda. Sellest tulenevalt on passiivmaatriksiga ekraanid aeglasemad ja kehvema kontrastiga kui aktiivmaatriks-ekraanid kus iga segmendi laengut juhib eraldi transistor. LCD ekraane on nii peegelduva taustaga kui taustvalgustusega, vahel isegi mitme erinevat värvi taustvalgustusega. Segmendi värve on alfabeetlistel LCD ekraanidel enamasti siiski üks - enamasti must, kuid esineb ka valge ja värvilise kirjaga ekraane.
Kodulabori digitaalse mooduli külge ühendub 2×16 märgine alfabeetiline LCD WC1602A. Ekraani juhtimiseks on 4-bitine andmesiin ja 3 juhtviiku, kuid selle suhtlusprotokoll on liiga mahukas, et siinkohal lahti seletada. Lihtsuse huvides on ekraani kasutamiseks kodulabori teegis olemas vastavad funktsioonid.
Esimene asi, mis ekraani kasutamiseks teha tuleb, on see seadistada. Vastavaks otstarbeks on lcd_alpha_init-funktsioon, millega saab määrata ekraanile ka vilkuva kursori. Ekraanil on olenemata sellest, kas seda on näha või mitte, pidevalt üks aktiivne kursori positsioon, kuhu järgmine täht sisestatakse. Seega tuleb enne teksti sisestamist viia kursor soovitud asukohale. Kursori asukoha muutmiseks on lcd_alpha_goto_xy ja teksti kuvamiseks lcd_alpha_write_string-funktsioon. Kõik alfabeetilise LCD funktsioonid on lahti seletatud selle teegis.
Järgnev programmikood demonstreerib alfabeetilise LCD kasutamist kellana. Kellaaeg algab alates 00:00:00 ja suureneb iga sekundiga (ligikaudu). Kuna aja lugemine toimub viite funktsiooniga, siis pole see päris täpne. Ebatäpsust selgitab perioodilise katkestuse harjutus. Programm loeb sekundeid ja teisendab need arvutuste abil minutiteks ja sekunditeks. Kellaaja kujule viimiseks on kasutusel C-keele standardfunktsioon sprintf.
// // Kodulabori alfabeetilise LCD kasutamise näide. // LCD-le kuvatakse kellaaeg programmi algusest alates. // #include <stdio.h> #include <homelab/module/lcd_alpha.h> #include <homelab/delay.h> // // Põhiprogramm // int main(void) { int seconds = 0; char text[16]; // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Programmi nimi lcd_alpha_write_string("Aja loendur"); // Lõputu tsükkel while (true) { // Sekundite teisendamine kellaaja kujule // hh:mm:ss sprintf(text, "%02d:%02d:%02d", (seconds / 3600) % 24, (seconds / 60) % 60, seconds % 60); // Kellaaja teksti kuvamine LCD teise rea alguses lcd_alpha_goto_xy(0, 1); lcd_alpha_write_string(text); // Sekundi suurendamine 1 võrra seconds++; // Riistvaraline paus 1000 millisekundit hw_delay_ms(1000); } }
Vajalikud teadmised: [HW] LCD moodul, [LIB] Graafilise LCD teek, [LIB] Viite teek, [PRT] Alfabeetiline LCD
Graafiline LCD on vedelkristall-ekraan, millega saab peale teksti ka kujundeid kuvada. Selle ehitus sarnaneb alfabeetilisele LCD-le, põhiline erinevus seisneb selles, et graafilisel ekraanil on kõik pikslid jaotatud üle ekraani ühe suure maatriksina. Kui tegu on monokromaatilise graafilise LCD ekraaniga, siis piksel on üks pisike ruudukujuline segment. Värvilistel ekraanidel moodustab üks piksel kolmest alampikslist, millest igaüks laseb läbi värvifiltri kas punast, rohelist või sinist valgust. Kuna alampikslid on lähestikku, paistavad need kui üks piksel.
Monokromaatilised graafilised ekraanid on tavaliselt passiivmaatriksiga, suured värvilised ekraanid, kaasa arvatud arvutiekraanid, on aktiivmaatriksiga. Kogu tausta- ja pikslite värvi puudutav info on graafilistel LCD-del sama mis alfabeetilistelgi - ehk siis leidub palju variante. Ning sarnaselt alfabeetiliste ekraanidega on ka graafilistel ekraanidel eraldi kontroller, mis hoolitseb sideliidese kaudu info vastuvõtmise ja segmentide elektrivälja tekitamise eest. Kui alfabeetilisele LCD ekraanile piisab teksti kuvamiseks märkide indeksite saatmisest, siis graafilised ekraanid ise tähti ei moodusta - kõik tekstid ja pildid tuleb kasutajal ise pikselhaaval tekitada.
Kodulabori komplekti kuulub mõõtudega 84 x 48 pikslit monokromaatiline graafiline LCD ekraan. See ekraan on sama, mida kasutatakse Nokia 3310 mobiiltelefonides. Ekraani küljes on Philipsi PCD8544 kontroller, millega saab suhelda läbi SPI-taolise järjestikliidese. Eraldi juhitav on veel ekraanimooduli taustvalgustus. Ekraaniga suhtlemine pole kuigi keeruline, kuid funktsioonide suure arvu tõttu pole siinkohal seda lahti seletatud. Kodulabori teegis on olemas funktsioonid selle kasutamiseks.
Graafilise LCD teegi funktsioonid on sarnased alfabeetilise LCD omadele. Esmalt tuleb ekraan käivitada lcd_gfx_init-funktsiooniga. Pärast käivitust on soovitatav ekraan, õigemini kontrolleri mälu, puhastada lcd_gfx_clear-funktsiooniga. Teeki on sisse kirjutatud tähekaart kogu ladina tähestiku, numbrite ja üldkasutatavate märkidega. Tähe kõrgus on 7 ja laius 5 pikslit. Iga tähe vahe on horisontaalselt 6 ja vertikaalselt 8 pikslit, ehk kokku mahub ekraanile 6 rida ja 14 tulpa tähti. Tähe või teksti kuvamiseks tuleb eelnevalt lcd_gfx_goto_char_xy funktsiooniga määrata selle asukoht. Tähe kuvamiseks on lcd_gfx_write_char- ja teksti kuvamiseks lcd_gfx_write_string-funktsioon.
Järgnevalt on toodud näide aja loenduri kohta. Programm loendab sekundeid (ligikaudu), minuteid ja tunde. Aja tekstiks teisendamiseks on kasutusel sprintf-funktsioon.
// // Kodulabori graafilise LCD kasutamise näide. // LCD-le kuvatakse kellaaeg programmi algusest alates. // #include <stdio.h> #include <homelab/module/lcd_gfx.h> #include <homelab/delay.h> // // Põhiprogramm // int main(void) { int seconds = 0; char text[16]; // LCD ekraani seadistamine lcd_gfx_init(); // Ekraani puhastamine lcd_gfx_clear(); // Taustavalgustuse tööle lülitamine lcd_gfx_backlight(true); // Programmi nime kuvamine lcd_gfx_goto_char_xy(1, 1); lcd_gfx_write_string("Aja loendur"); // Lõputu tsükkel while (true) { // Sekundite teisendamine kellaaja kujule // hh:mm:ss sprintf(text, "%02d:%02d:%02d", (seconds / 3600) % 24, (seconds / 60) % 60, seconds % 60); // Kellaaja teksti kuvamine lcd_gfx_goto_char_xy(3, 3); lcd_gfx_write_string(text); // Sekundi suurendamine 1 võrra seconds++; // Riistvaraline paus 1000 millisekundit hw_delay_ms(1000); } }
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Andurid on seadmed, mis teisendavad mingi füüsikalise suuruse, näiteks temperatuuri, valgustugevuse, jõu, kiirenduse jne. inimesele või masinale arusaadavale kujule. Nende abil saab mikrokontrolleri programm infot ümbritsevast keskkonnast ja selle põhjal otsuseid teha. Andureid on palju erinevat liiki, Wikipedias on näiteks loetletud ligikaudu 195 andurit. Mikrokontrolleritega saab siiski ühendada vaid andureid, mille väljundiks on elektriline signaal. Elektrilise väljundsignaali järgi võib andurid aga jagada väga üldiselt kahte tüüpi: analoog- ja digitaalandurid.
Analooganduris muutub füüsikalise suuruse muutudes mõni selle elektriline väärtus, tavaliselt kas pinge või takistus. Kuna mikrokontrollerid on digitaalsed seadmed, siis analooganduri info edastamiseks kontrollerile tuleb see digitaalseks teisendada. Selleks kasutatakse peamiselt mikrokontrolleritesse sisse ehitatud analoog-digitaalmuundureid.
Kui analoogandur juba sisaldab info digitaliseerijat, nimetatakse seda digitaalseks anduriks. Peale digitaliseerimise võivad digitaalsed andurid infot ka normeerida, andurit kalibreerida ja palju muid funktsioone täita. Digitaalse anduri info edastamine mikrokontrollerile võib toimuda mitmel viisil - lihtsamal juhul loogiliste signaalidega, keerukamal juhul mõne andmesideliidese kaudu. Järgmised harjutused tutvustavad siiski lihtsamaid ja robootikas levinuimaid andureid.
Vajalikud teadmised: [HW] Andurite moodul, [HW] Digitaalne moodul, [ELC] Pingejagur, [AVR] ADC, [LIB] ADC teek, [LIB] Indikaatori teek
Potentsimeeter on kolme kontaktiga muuttakisti, mille kahe äärmise kontakti vahel on fikseeritud takistus ja äärmiste ning keskmise konktakti vahel muutuv takistus. Potentsiomeeter on põhimõtteliselt ka pingejagur, kus takistid moodustuvad äärmiste kontaktide ja keskmise kontakti vahel.
Tüüpiline potentsiomeeter koosneb voolu juhtiva pinnaga takistist ja sellel liuglevast liikuvast kontaktist ehk liugurist. Mida lähemal on liugur takisti servale, seda väiksem on liuguri ja selle serva vaheline takistus ning vastupidi. Takisti rolli võib täita kas suure eritakistusega materjal või takistustraadist keritud mähis. Potentsiomeetreid on olemas nii lineaarse kui ka logaritmilise takistuse ja positsiooni suhtega. Suurem osa potentsiomeetritest on keeratavad (näide kõrvaloleval pildil), kuid eksisteerib ka liugtakisteid. Potentsiomeetrite eriliik on digitaalsed potentsiomeetrid,milles takistuse reguleerimine toimub mikroskeemi sees vastavalt juhtsignaalidele.
Kodulabori andurite moodulil asub pööratav 4,7 kΩ potentsiomeeter. Potentsiomeeter on ühendatud maa ja +5 V potentsiaalide vahele ning liugur ühendub mikrokontrolleri analoog-digitaalmuunduri kanaliga 3. Selliselt ühendatuna saab potentsiomeetri väljundpinget reguleerida vahemikus 0 kuni 5 V. Kui ka AVR-i analoog-digitaalmuunduri võrdluspinge võtta AVCC viigult, saab potentsiomeetri väljundpinge digitaalse väärtuse kogu selle reguleerimispiirkonna ulatuses. AVR ADC kasutamiseks on kodulabori teegis kirjutatud järgmised funktsioonid:
// // Seadistuse andmetüübid // typedef enum { ADC_REF_AREF = 0x00, ADC_REF_AVCC = 0x01, ADC_REF_2V56 = 0x03 } adc_reference; typedef enum { ADC_PRESCALE_2 = 0x01, ADC_PRESCALE_4 = 0x02, ADC_PRESCALE_8 = 0x03, ADC_PRESCALE_16 = 0x04, ADC_PRESCALE_32 = 0x05, ADC_PRESCALE_64 = 0x06, ADC_PRESCALE_128 = 0x07 } adc_prescale; // // ADC käivitamine // void adc_init(adc_reference reference, adc_prescale prescale) { // ADC töötamise lubamine, sagedusjaguri valimine ADCSRA = bit_mask(ADEN) | (prescale & 0x07); // Võrdluspinge valimine ADMUX = (reference & 0x03) << REFS0; } // // ADC määratud kanali väärtuse muundamine // unsigned short adc_get_value(unsigned char channel) { // Kanali määramine ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Muundamise alustamine bit_set(ADCSRA, ADSC); // Muundamise lõpu ootamine while (bit_is_set(ADCSRA, ADSC)) { asm volatile ("nop"); } // Tulemuse tagastamine return ADCW; }
Funktsioon adc_init tuleb välja kutsuda programmi alguses, millega seatakse AVR-i ADC töövalmis. Valida tuleb võrdluspinge kas AREF või AVCC viigult või hoopis sisemine fikseeritud 2.56 V pinge. Lisaks tuleb määrata muunduri töötakt, täpsemalt sagedusjaguri tegur, millega jagatakse läbi mikrokontrolleri töötakt. Kõrgema taktiga käib muundamine kiiremini, kuid võib kannatada mõõtmistäpsus. Mõõtmiseks on adc_get_value funktsioon, millega saab valida kanali ja mis tagastab 16-bitise täisarvuna 10-bitise mõõtmistulemuse. Mõõtmisfunktsioon on blokeeruv ehk see tagastab väärtuse alles siis, kui mõõtmine on tehtud.
Näiteprogrammis kasutatakse just selgitatud analoog-digitaalmuunduri ja 7-segmendilise LED numberindikaatori teeki. 10-bitine analoog-digitaalmuunduri väärtus korrutatakse kümnega ja jagatakse 1024-ga, et saada väärtus vahemikus 0 kuni 9. Väärtus 10 ei saa tekkida, sest C-keeles arvutatakse jagatises täisosa väärtus, mitte ümardatud tulemus. Täpsema mõõtetulemuse saamiseks kasutatakse muunduri tulemuse keskmistamise funktsiooni. Tulemusena näitab töötav programm vastavalt potentsiomeetri asendile indikaatoril numbreid 0 kuni 9.
// // Kodulabori andurite mooduli potentsiomeetri // näidisprogramm. 7-segmendilisel numberindikaatoril // kuvatakse potentsiomeetri asendit. // #include <homelab/adc.h> #include <homelab/module/segment_display.h> // // Kanali valimine // // 1 = fototakisti // 2 = termotakisti // 3 = potentsiomeeter // #define ADC_CHANNEL 3 // // Põhiprogramm // int main(void) { int value; // 7-segmendilise indikaatori seadistamine segment_display_init(); // ADC muunduri seadistamine adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Lõputu tsükkel while (true) { // Kanali 4-kordselt ümardatud väärtuse lugemine value = adc_get_average_value(ADC_CHANNEL, 4); // Näidu sajandike näitamine segment_display_write(value * 10 / 1024); } }
Vajalikud teadmised: [HW] Andurite moodul, [HW] Alfabeetilise LCD moodul, [ELC] Pingejagur, [AVR] ADC, [LIB] ADC teek, [LIB] Alfabeetilise LCD teek, [LIB] Andurite teek
Termistor on takisti, mille takistus temperatuuriga muutub. Termistore on kahte liiki: positiivse ja negatiivse temperatuuri koefitsiendiga. Positiivse koefitsiendiga termistori takistus temperatuuri tõustes kasvab ja negatiivsel väheneb. Vastavad lühendatud ingliskeelsed nimed on neil PTC (positive temperature coefficient) ja NTC (negative temperature coefficient).
Termistori kasutamise teeb keeruliseks tema takistuse temperatuurisõltuvuse mittelineaarsus. Lineaarne on sõltuvus vaid väikestes vahemikes, mitmekümnekraadise ja suurema mõõtepiirkonna arvutamiseks sobib Steinhart-Hart-i kolmandat järku eksponentsiaalne võrrand. NTC termistoride jaoks on olemas järgmine B-parameetriga lihtsustatud Steinharti-Harti võrrand:
kus:
B-parameeter on koefitsient, mis tavaliselt antakse termistori andmelehes. Samas on see ainult teatud temperatuurivahemikes piisavalt konstantne, näiteks 25–50 °C või 25–85 °C. Kui mõõdetav temperatuurivahemik on suurem, tuleb olemasolul kasutada andmelehel antud võrrandit.
Termistori takistuse? mõõtmiseks kasutatakse tavaliselt pingejagurit, kus ühe takisti asemel on termistor ja sisendpinge on konstantne. Mõõdetakse pingejaguri väljundpinget, mis muutub koos termistori takistuse muutusega. Pinget rakendades läbib termistori aga elektrivool, mis termistori selle takistuse tõttu soojendab ja seega omakorda takistust muudab. Termistori soojenemisest tekkivat viga saab arvutuslikult kompenseerida, kuid lihtsam on kasutada suurema takistusega termistorit, mis soojeneb vähem.
Piiratud ressurssidega ja suurt täpsust mittenõudvates rakendustes kasutatakse eelnevalt väljaarvutatud temperatuuri tabelit. Tabelis on üldjuhul kirjas kindla vahemikuga temperatuurinäitude vastavus anduri takistuse, pinge või analoog-digitaalmuunduri väärtusega. Tabeli puhul on kogu eksponentsiaalne arvutus eelnevalt ära tehtud ja programmis tuleb vaid mõõdetud parameetrile vastav rida üles otsida ja temperatuur välja lugeda.
Kodulabori anduri moodul on varustatud 10 kΩ nimitakistusega NTC tüüpi termistoriga. Temperatuuril 25-50 °C on termistori B-parameeter 3900. Termistori üks viik on ühendatud +5 V toitega ja teine mikrokontrolleri analoog-digitaalmuunduri kanaliga 2 (viik PF2). Sama mikrokontrolleri viigu ja maaga on ühendatud ka tavaline 10 kΩ takisti, mis koos termistoriga moodustab pingejaguri. Kuna tegu on NTC termistoriga, mille takistus väheneb temperatuuri kasvades, siis samas tõuseb ka pingejaguri väljundpinge.
Temperatuuri leidmiseks on AVR-i peal otstarbekas kasutada temperatuuri ja analoog-digitaalmuunduri väärtuste teisendustabelit. Mõistlik on leida soovitud temperatuurivahemikust igale kraadile vastav analoog-digitaalmuunduri väärtus, sest vastupidine tabel läheb 10-bitise ADC väärtuste hulga tõttu liiga suureks. Tabeli tegemiseks on soovitatav kasutada mõnd tabelarvutuse programmi (MS Excel, Openoffice Calc vmt). Eespool toodud NTC termistorite jaoks kohandatud Steinharti-Harti valemiga saab leida temperatuurile vastava termistori takistuse. Takistusest saab arvutada pingejaguri väljundpinge ning sellest omakorda ADC väärtuse. Leitud väärtused saab järgneval viisil programmi sisse kirjutada:
// // Temperatuuri ADC väärtuseks teisendamise tabel. // Iga massiivi element tähistab ühte Celsiuse kraadi. // Elemendid algavad -20 kraadist ja lõpevad 100 kraadiga. // Kokku on massiivis 121 elementi. // const signed short min_temp = -20; const signed short max_temp = 100; const unsigned short conversion_table[] = { 91,96,102,107,113,119,125,132,139,146,153, 160,168,176,184,192,201,210,219,228,238,247, 257,267,277,288,298,309,319,330,341,352,364, 375,386,398,409,421,432,444,455,467,478,489, 501,512,523,534,545,556,567,578,588,599,609, 619,629,639,649,658,667,677,685,694,703,711, 720,728,736,743,751,758,766,773,780,786,793, 799,805,811,817,823,829,834,839,844,849,854, 859,863,868,872,876,880,884,888,892,896,899, 903,906,909,912,915,918,921,924,927,929,932, 934,937,939,941,943,945,947,949,951,953,955 };
Et tabelist ADC väärtuse järgi temperatuur leida, võib kasutada järgmist algoritmi:
// // ADC väärtuse teisendamine Celsiuse kraadideks. // signed short thermistor_calculate_celsius(unsigned short adc_value) { signed short celsius; // Tabeli tagurpidi läbikäimine for (celsius = max_temp - min_temp; celsius >= 0; celsius--) { // Kui tabeli väärtus on sama või suurem kui // mõõdetud tulemus, siis temperatuur on vähemalt // sama kõrge kui elemendile vastav temperatuur if (adc_value >= conversion_table[celsius])) { // Kuna tabel algab nullist, aga elementide // väärtus -20 kraadist, siis tuleb väärtust nihutada return celsius + min_temp; } } // Kui väärtust ei leitud, tagastatakse minimaalne temperatuur return min_temp; }
Algoritm otsib tabelist vahemikku, kuhu ADC väärtus jääb, ja saab teada selle vahemiku aluspiiri järjekorranumbri. Järjekorranumber tähistab kraade, sellele tuleb ainult algtemperatuur otsa liita ja nii saadaksegi 1 kraadi täpsune temperatuur.
Toodud teisendustabel ja funktsioon on juba olemas kodulabori teegis, nii et käesolevas harjutuses neid ise kirjutama ei pea. Teisendamise funktsioonil on teegis nimeks thermistor_calculate_celsius. Arvestama peab, et teisendus kehtib ainult kodulabori andurite moodulil asuva termistori kohta. Muu termistori kasutamiseks tuleb ise teisendustabel luua ja kasutada teegi juhendis kirjeldatud keerukamat funktsiooni. Harjutuse näidisprogrammiks on termomeeter, mis mõõdab temperatuuri Celsiuse kraadides ja kuvab seda alfabeetilisel LCD ekraanil.
// // Kodulabori andurite mooduli termistori // näidisprogramm. // LCD ekraanil kuvatakse temperatuur. // #include <stdio.h> #include <homelab/adc.h> #include <homelab/module/sensors.h> #include <homelab/module/lcd_alpha.h> // // Põhiprogramm // int main(void) { unsigned short value; signed short temperature; char text[16]; // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Programmi nimi lcd_alpha_write_string("Termomeeter"); // ADC muunduri seadistamine adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Lõputu tsükkel while (true) { // Termistori pinge 4-kordselt ümardatud väärtuse lugemine value = adc_get_average_value(2, 4); // ADC väärtuse kraadideks ümberarvutamine temperature = thermistor_calculate_celsius(value); // Temperatuuri tekstiks teisendamine // Kraadi märgi kuvamiseks on oktaalarv 337 sprintf(text, "%d\337C ", temperature); // Teksti kuvamine LCD teise rea alguses lcd_alpha_goto_xy(0, 1); lcd_alpha_write_string(text); } }
Vajalikud teadmised: [HW] Andurite moodul, [HW] Alfabeetilise LCD moodul, [ELC] Pingejagur, [AVR] ADC, [LIB] ADC teek, [LIB] Alfabeetilise LCD teek, [PRT] Tarkvara paigaldamine
Fototakisti on andur, mis muudab oma elektrilist takistust sõltuvalt temale peale langeva valguse intensiivsusest. Mida intensiivsem on valgus, seda rohkem tekib vabu laengukandjaid ning seda väiksemaks jääb elemendi takistus. Fototakisti kaks välist metallkontakti ulatuvad läbi keraamilise alusmaterjali valgustundliku kileni, mis oma geomeetria ja materjali omaduse poolest määravad elektrilised takistuslikud omadused. Kuna fototundlik materjal on iseloomult suure takistusega, siis peenikese käänulise rajaga elektroodide vahel saavutatakse madal elemendi kogutakistus keskmise valguse intensiivsuse juures. Nii nagu inimese silm, on ka fototakisti tundlik kindlale valguse lainepikkuse vahemikule. Fotoelemendi valikul tuleb sellega kindlasti arvestada, kuna vastasel juhul ei pruugi see rakenduses kasutatavale valgusallikale üldse reageeridagi. Siinkohal olgu ära toodud nähtava valguse lainepikkused jaotatuna lihtsustatult värvide järgi.
Värv | Lainepikkuse vahemik (nm) |
---|---|
Lilla | 400 – 450 |
Sinine | 450 – 500 |
Roheline | 500 – 570 |
Kollane | 570 – 590 |
Oranž | 590 – 610 |
Punane | 610 – 700 |
Fototakistil on kindlasti määratud ka töötemperatuuri vahemik. Kui tahta lasta anduril töötada erinevatel temperatuuridel, siis tuleb sisse viia kindlasti täpsustavad teisendused, kuna anduri takistuslik omadus sõltub välistemperatuurist.
Võrdluseks ka mõningad valgustugevuse väärtused:
Keskkond | Valgustugevus (lux) |
---|---|
Täiskuu | 0,1 |
Hämarus | 1 |
Auditoorium | 10 |
Klassiruum | 30 |
Päikesetõus või -loojang | 400 |
Haigla operatsioonisaal | 500 - 1000 |
Otsene päikesevalgus | 10000 |
Kodulabori andurimoodul on varustatud VT935G fototakistiga. Selle üks viik on ühendatud +5 V toitega ja teine mikrokontrolleri analoog-digitaalmuunduri kanaliga 1 (viik PF1). Sama mikrokontrolleri viigu ja maaga on ühendatud ka tavaline 10 kΩ takisti, mis koos fototakistiga moodustab pingejaguri. Kuna fototakisti elektriline takistus väheneb temale peale langeva valguse intensiivsuse kasvades, siis mõõdetav pinge mikrokontrolleri viigu peal kasvab valguse intensiivsuse kasvades. Tasuks arvestada, et kodulaboris kasutatav fototakisti reageerib kõige intensiivsemalt kollasele ja oranžile valgusele.
VT935G andur ei olegi tegelikult mõeldud konkreetseks mõõteseadmeks, pigem üldiste valgustingimuste määramiseks - näiteks kas ruumis põleb lamp või mitte. Sel juhul tuleb lihtsalt mõõta anduri takistus poolpimedas ruumis, see programmi kirja panna ja selle abil võrrelda mõõdetavat - kas on heledam või pimedam.
Käesoleva harjutus on aga natukese keerulisem ja hinnatakse valguse intensiivsust ka luksides. Selle tegemiseks on kasutusel ligikaudne arvutusvalem ja ujukoma arvud. Ujukoma arvud on C-keeles float- ja double-tüüpi arvud, millega saab esitada murdarve. Nende puuduseks on suhteliselt suur ressursinõudlikkus. Arvutites on nende arvutamiseks spetsiaalne riistvara, 8-bitisel AVR mikrokontrolleril tehakse arvutused tarkvaras, mis võtab palju programmimälu ja aega. Kui puudused pole kriitilised, on ujukoma arvud väärt kasutamist.
Fototakisti valguse intensiivsuse ja elektritakistuse vahelise seose kohta annab anduri andmeleht ligikaudse valemi. Nagu kõrvalolevalt graafikult näha, on logaritmskaalas intensiivsus ja takistus ligikaudu lineaarses seoses ning moodustavad sirge võrrandi, sest kehtib teisendus:
log(a/b) = log(a) - log(b)
Seost iseloomustab γ faktor (sirge tõus), mis VT935G anduril on 0.9. Teada on ka joone ühe punkti andmed: 18.5 kΩ takistus (RA) 10 lux valguse intensiivsuse (EA) juures. Seega, olemas on 1 punkti koordinaadid ja sirge tõus ning iga muu punkti arvutamiseks piisab vaid ühest koordinaadist. Ehk kui mõõta anduri takistus (RB), saab joone võrrandist arvutada andurile langeva valguse intensiivsuse (EB). Avaldame joone võrrandist EB:
log(EB) = log(RA/RB) / γ + log(EA)
EB = 10log(RA/RB) / γ + log(EA)
Sellega on takistusest valguse intensiivsuse arvutamise valem olemas. Takistust otse aga mikrokontrolleriga mõõta ei saa - selleks on fototakisti pingejaguris, mille väljundpinge teisendab analoog-digitaalmuundur konkreetseks arvuks (ADC). Takistuse leidmiseks tuleb kõigepealt arvutada ADC väärtusest pingejaguri väljundpinge (U2), arvestades ka muunduri võrdluspinget (Uref). Valem on selline:
U2 = Uref * (ADC / 1024)
Pingejaguri valemist (vaata pingejaguri peatükki) saab leida skeemis ülemise fototakisti takistuse (R1):
R1 = (R2 * U1) / U2 - R2
Järgnevalt on pinge ja takistuse arvutamisel teadaolevad tegurid numbritega asendatud ja alaindeksid ära kaotatud:
U = 5 * (ADC / 1024)
R = (10 * 5) / U - 10
Valguse intensiivsuse leidmisel saab teha lihtsustavaid teisendusi:
E = 10log(18.5/R) / 0.9 + 1 = 10log(18.5/R) * 10/9 * 101 =
= 10log18.5*10/9 - logR*10/9 * 10 = (10log18.5*10/9 / 10logR*10/9) * 10 =
= (18.510/9 / R10/9) * 10 = 18.510/9 * 10 * R-10/9
Arvutades välja muutuja R ees oleva konstandi, jääb avaldis kujule:
E = 255,84 * R-10/9
Nende valemite abil saab kasutada vaid Kodulabori andurite mooduli plaadil olevat fototakistit. Teiste komponentidega skeemi kasutades tuleks valemites muuta vastavaid arve. Järgnevalt on toodud näidisprogrammi lähtekood, mis teostab ADC-ga mõõtmist, arvutamist ja valguse intensiivsuse kuvamist LCD ekraanil. Kuid veel enne programmi kompileerimist tuleb projekti teha seadistused ujukoma arvude kasutuselevõtuks. Selle kohta on lühiõpetus tarkvara paigaldamise peatükis.
Näidisprogrammis defineeritakse pinge, takistuse ja intensiivsuse muutujad ujukoma arvu tüüpi double. Arvud, mida soovitakse kindlasti ujukoma tehetes kasutada, peavad alati sisaldama komakohta, olgu kas või nulli, sest siis ei tõlgenda kompilaator neid valesti. sprintf abil ujukoma arvu tekstiks teisendades tuleb kasutada “%f” formaati mida võib täiendada täis- ja komakohtade arvuga, näiteks “%3.2”, mis kuvab alati 3 täis- ja 2 komakohta.
// // Kodulabori andurite mooduli fototakisti näidisprogramm. // LCD ekraanil kuvatakse ligikaudne valguse intensiivsus luxides // #include <stdio.h> #include <math.h> #include <homelab/module/lcd_alpha.h> #include <homelab/adc.h> #include <homelab/delay.h> // // Põhiprogramm // int main(void) { char text[16]; unsigned short adc_value; double voltage, resistance, illuminance; // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Programmi nimi lcd_alpha_write_string("Luksmeeter"); // ADC muunduri seadistamine adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Lõputu tsükkel while (true) { // Fototakisti keskmistatud väärtuse lugemine adc_value = adc_get_average_value(1, 10); // Pinge arvutamine ADC sisendis voltage = 5.0 * ((double)adc_value / 1024.0); // Fototakisti takistuse arvutamine pingejaguris resistance = (10.0 * 5.0) / voltage - 10.0; // Valgustugevuse luxides arvutamine illuminance = 255.84 * pow(resistance, -10/9); // Valgustugevuse tekstiks teisendamine sprintf(text, "%0.1f lux ", illuminance); // Näidu LCD-l kuvamine lcd_alpha_goto_xy(0, 1); lcd_alpha_write_string(text); // Viide 500 ms sw_delay_ms(500); } }
Vajalikud teadmised: [HW] Andurite moodul, [HW] LCD moodul, [AVR] ADC, [LIB] ADC teek, [LIB] Alfabeetilise LCD teek, [LIB] Andurite teek
Objekti kauguse mõõtmiseks on olemas triangulatsioonimeetodil töötavad optilised andurid. Levinuimad neist on firma Sharp poolt toodetavad infrapuna (lühend IR - inglise keeles infra-red) lainepikkusel töötavad analoogpinge väljundiga kaugusandurid. Sharp-i anduritel on läätsega IR LED, mis kiirgab kitsast valguskiirt. Objektilt peegeldunud kiir suunatakse läbi teise läätse positsioonitundlikule fotoelemendile (inglise keeles position-sensitive detector lühendiga PSD). PSD-le langeva kiire asukohast sõltub selle juhtivus. Juhtivus muundatakse pingeks ja seda näiteks mikrokontrolleri analoog-digitaalmuunduriga digitaliseerides saab välja arvutada kauguse. Erinevalt kaugustelt peegelduvate kiirte teekonda näitab kõrvalolev joonis.
Sharp-i kaugusandurite väljund on pöördvõrdeline - kauguse kasvades see väheneb järjest aeglasemalt. Täpne kauguse ja väljundi graafik on toodud andurite andmelehel. Anduritel on vastavalt tüübile ka mõõtepiirkond, milles nende väljund on usaldusväärne. Maksimaalsele reaalselt mõõdetavale kaugusele seab piiri kaks aspekti: peegelduva valgushulga vähenemine ja PSD-e võimetus registreerida väikest peegeldunud kiire asukoha muutust. Liiga kaugete objektide mõõtmisel jääb anduri väljund ligikaudu samaks mis maksimaalselt mõõdetava kauguse puhulgi. Minimaalne mõõdetav kaugus on piiratud Sharp-i andurite omapära tõttu - nimelt hakkab väljund kauguse vähenedes teatud kaugusel (olenevalt andurist 4-20 cm) järsult jälle vähenema. Sisuliselt tähendab see, et ühele väljundpinge väärtusele vastab kaks kaugust. Probleemide ärahoidmiseks tuleb vältida objektide andurile liiga lähedale sattumist.
Kodulabori andurite komplektis on Sharp-i infrapuna kaugusmõõdik GP2Y0A21YK mõõtepiirkonnaga 10-80 cm. Anduri väljundpinge on kuni 3 V sõltuvalt mõõdetavast kaugusest. Andur ühendub andurite mooduli külge ja selle väljundpinge suunatakse AVR-i analoog-digitaalmuunduri kanalisse 0. Eelnevate andurite harjutuste baasil saab lihtsalt teha programmi, mis mõõdab kaugusmõõdiku väljundpinget, kuid lisaks on selle harjutuse eesmärk veel see pinge kauguseks teisendada.
GP2Y0A21YK andmelehel on toodud väljundpinge ja mõõdetud kauguse vahelise sõltuvuse graafik. See pole lineaarne, kuid väljundpinge ja kauguse pöördväärtuse graafik peaaegu et on, ning sellest on suhteliselt lihtne pinge kauguseks teisendamise valem leida. Valemi leidmiseks tuleb sama graafiku punktid sisestada mõnda tabelarvutuse programmi ja nendest uuesti graafik luua. Tabelarvutusprogrammides on graafiku punktide põhjal võimalik trendijoon automaatselt välja arvutada. Järgnevalt on toodud GP2Y0A21YK väljundpinge ja kauguse korrigeeritud pöördväärtuse vahelise seose graafik koos lineaarse trendijoonega. Väljundpinge on valemi lihtsustamise nimel juba teisendatud 10-bitiseks +5 V võrdluspingega analoog-digitaalmuunduri väärtuseks.
Nagu graafikult näha, kattub trendijoon (sinine) üsna täpselt graafiku punktidega (punane joon). Selline kattuvus on saavutatud kauguse korrigeerimiskonstandi abil. Korrigeerimiskonstant on leitud katse- ja eksitusmeetodil - läbi on proovitud hulk arve, kuni on leitud selline, mille korral graafik kattub enim trendijoonega. Antud graafiku puhul on see +2, ehk kõigile reaalsetele kaugustele on graafikus 2 otsa liidetud. Kuna nii on graafik väga sarnane lineaarsele trendijoonele, võib teha üldistuse ja öelda, et kauguse ja pinge vaheline seos on järgmine:
1 / (d + k) = a * ADC + b
kus,
Valemist saab avaldada kauguse d:
d = (1 / (a * ADC + B)) - k
Põhimõtteliselt saakski selle valemiga kauguse välja arvutada, kuid see eeldaks ujukoma-arvutusi, sest jagatises tekivad murdarvud. Täisarvudega opereeriva mikrokontrolleri jaoks tuleb valemit lihtsustada ja suuremate tegurite peale ümber teisendada. Valemi jagatist lineaarliikmega läbi jagades saab see kuju:
d = (1 / a) / (ADC + B / a) - k
Viies valemisse korrigeerimiskonstandi väärtuse ja trendijoone võrrandist saadud lineaar- ja vabaliikme, tuleb kauguse arvutamise valemiks:
d = 5461 / (ADC - 17) - 2
See valem on arvutatav 16-bitiste täisarvudega ja täiesti jõukohane AVR-ile. Enne arvutamist tuleb aga veenduda, et ADC väärtus oleks üle 17, sest muidu tekib nulliga jagamine või negatiivne kaugus.
Järgnevalt on toodud kodulabori teegis kirja pandud funktsioon ADC väärtuse sentimeetriteks teisendamise kohta. Lineaar- ja vabaliige ning korrigeerimiskonstant pole funktsiooni jäigalt sisse kirjutatud, vaid need antakse ette IR kaugusanduri parameetrite struktuuri objektiga. Hoides parameetreid eraldi konstandis, saab programmi lihtsalt lisada uute IR kaugusandurite tuge.
// // IR kaugusanduri parameetrite struktuur // typedef const struct { const signed short a; const signed short b; const signed short k; } ir_distance_sensor; // // GP2Y0A21YK anduri parameetrite objekt // const ir_distance_sensor GP2Y0A21YK = { 5461, -17, 2 }; // // IR kaugusanduri ADC väärtuse sentimeetriteks teisendamine // Tagastab -1, kui teisendus ei õnnestunud // signed short ir_distance_calculate_cm(ir_distance_sensor sensor, unsigned short adc_value) { if (adc_value + sensor.b <= 0) { return -1; } return sensor.a / (adc_value + sensor.b) - sensor.k; }
Teisenduse tegemiseks tuleb välja kutsuda ir_distance_calculate_cm funktsioon mille esimene parameeter on IR kaugusanduri parameetrite objekt, teine aga ADC väärtus. Funktsioon tagastab arvutatud kauguse sentimeetrites. Väära tehte (ehk siis ebaloomuliku ADC väärtuse) korral tagastab funktsioon -1. IR kaugusanduri ja teisendusfunktsiooni kasutamist demonstreerib järgnev programm. Kasutusel on alfabeetiline LCD ekraan kus kuvatakse mõõtetulemust. Ebaloomuliku kauguse puhul kuvatakse küsimärki.
// // Kodulabori IR kaugusmõõdiku näidisprogramm. // LCD ekraanil kuvatakse mõõdetud kaugus sentimeetrites. // #include <stdio.h> #include <homelab/adc.h> #include <homelab/delay.h> #include <homelab/module/sensors.h> #include <homelab/module/lcd_alpha.h> // // Põhiprogramm // int main(void) { unsigned short value; signed short distance; char text[16]; // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Programmi nimi lcd_alpha_write_string("Kaugusandur"); // ADC muunduri seadistamine adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Lõputu tsükkel while (true) { // Anduri väljundpinge 4-kordselt ümardatud väärtuse lugemine value = adc_get_average_value(0, 4); // ADC väärtuse kauguseks ümberarvutamine distance = ir_distance_calculate_cm(GP2Y0A21YK, value); // Kas arvutus õnnestus ? if (distance >= 0) { // Kauguse tekstiks teisendamine sprintf(text, "%d cm ", distance); } else { // Teadmata kauguse teksti loomine sprintf(text, "? cm "); } // Teksti kuvamine LCD teise rea alguses lcd_alpha_goto_xy(0, 1); lcd_alpha_write_string(text); // Paus sw_delay_ms(500); } }
Vajalikud teadmised: [HW] Kontrolleri moodul, [HW] LCD moodul, [AVR] Taimerid, [LIB] Taimeri teek, [LIB] Alfabeetilise LCD teek, [LIB] Andurite teek
Ultraheli kaugusmõõdik mõõdab objekti(de) kaugust helilaine objektilt tagasipeegeldumise aega mõõtes. Helilaine sagedus asub ultraheli sageduse piirkonnas, mis tagab kontsentreerituma helilaine suuna, sest kõrgema sagedusega heli hajub keskkonnas vähem. Tüüpiline ultraheli kaugusmõõdik koosneb kahest membraanist, millest üks genereerib heli, teine registreerib seda. Piltlikult öeldes on tegu kõlari ja mikrofoniga. Heligeneraator tekitab lühikese, mõne perioodi pikkuse ultraheli impulsi ja käivitab taimeri. Teine membraan registreerib peegeldunud impulsi saabumise ja peatab taimeri. Taimeri ajast on heli kiiruse järgi võimalik välja arvutada helilaine läbitud teepikkus. Objekti kaugus on ligikaudu pool helilaine teepikkusest.
Ultraheli kaugusmõõdikutel on igapäevaelus mitmeid rakendusi. Neid kasutatakse mõõdulintide asendajatena kauguse mõõtmise seadmetes ehitusel. Tänapäeva autod on varustatud tagurdamisel takistusest hoiatavate ultraheliandurite ja hoiatussignaaliga. Peale kauguse mõõtmise võivad nad lihtsalt registreerida objekti olemasolu mõõtepiirkonnas, näiteks tööstusmasinate ohualades. Kui ultraheli kiirgur ja vastuvõtja eraldada, saab mõõta nende vahel voolava aine voolukiirust, sest vastuvoolu levib helilaine aeglasemalt, ja vastupidi.
Kodulabori komplektis on Devantech SRF04 ultraheli kaugusmõõdik. SRF04 on ainult andur, mis otseselt kauguse infot ei väljasta. Anduril on peale toiteviikude ka päästiku ja kaja viik. Päästiku viiku kõrgeks seades genereerib andur 8-perioodilise 40 kHz ultraheli laine. Sel hetkel läheb kõrgeks kaja viik ja jääb kõrgeks niikaua, kuni peegeldunud helilaine on andurini jõudnud. Seega põhimõtteliselt näitab kaja signaal aega, mille jooksul heli levib objektini ja tagasi. Mõõtes seda aega, korrutades seda heli levimise kiirusega ja jagades kahega, saab leida objekti kauguse. Päästiku, helilaine kiirguri ja kaja signaale ajas iseloomustab järgnev graafik:
SRF04 AVR-iga kasutamiseks tuleb selle päästiku ja kaja viigud ühendada mõnede AVR-i viikudega. Aja mõõtmiseks on sobiv kasutada 16-bitist taimerit, näiteks timer3. Järgnevalt on toodud funktsioon, mis teostab kogu mõõtmisprotseduuri - genereerib päästiku signaali, käivitab taimeri, mõõdab kajasignaali pikkust ja teisendab selle kauguseks sentimeetrites. Funktsioon on blokeeruv ehk protsessor on sellega hõivatud senikaua, kuni mõõtetulemus on käes või mõõtmine venib liiga pikaks. Mida kiiremini kaja saabub, seda kiiremini saab mõõtetulemuse. Kui kaja ei saabugi, ootab funksioon seda kuni ~36 ms ja tagastab 0. Oluline on mõõtmiste vahele jätta mõnikümmend millisekundit pausi, et eelmisel mõõtmisel tekitatud helilaine sumbuda jõuaks ja uut mõõtmist ära ei rikuks. Kui kasutatakse mitut ultraheli andurit tuleb samuti jälgida, et helilained ei kattuks.
#define ULTRASONIC_SPEED_OF_SOUND 33000 // cm/s // // Instant ultrasonic distance measuring // unsigned short ultrasonic_instant_measure(pin trigger, pin echo) { // Pin setup pin_setup_output(trigger); pin_setup_input_with_pullup(echo); // Set timer 3 to normal mode // with period of F_CPU / 8 timer3_init_normal(TIMER3_PRESCALE_8); // Create trigger pulse pin_set(trigger); // Reset timer timer3_overflow_flag_clear(); timer3_set_value(0); // Wait ~10 us while (timer3_get_value() < 18) {} // End trigger pulse pin_clear(trigger); // Wait for echo start while (!pin_get_value(echo)) { // Timeout ? if (timer3_overflow_flag_is_set()) { return 0; } } // Reset timer again timer3_set_value(0); // Wait for echo end while (pin_get_value(echo)) { // Timeout ? if (timer3_overflow_flag_is_set()) { return 0; } } // Convert time to distance: // distance = timer * (1 / (F_CPU / 8)) * speed / 2 return (unsigned long)timer3_get_value() * ULTRASONIC_SPEED_OF_SOUND / (F_CPU / 4); }
Toodud funktsioon jätab päästiku ja kaja viigu kasutaja valida, nii et andurit saab ühendada sinna, kus on sobivam või on ruumi. Lisaks võimaldab viikude valiku vabadus funktsiooni kasutada ka mujal kui kodulabori komplektis. Toodud funktsioon juba kuulub kodulabori teeki, nii et seda ei pea oma programmi eraldi kirjutama. Peab aga arvestama, et kodulabori teegis on see funktsioon jäigalt seotud kodulabori kontrollerimooduli taktsagedusega 14,7456 Mhz ja muude taktsageduste puhul annaks funktsioon vale tulemuse. Muu taktsageduse korral tuleb see funktsioon ise oma programmmi kirjutada. Järgnevalt esitatud programmikood demonstreerib SRF04 ultraheli anduri kasutamist kodulabori teegiga.
// // Kodulabori ultraheli kaugusanduri näidisprogramm. // Kauguse mõõtmise funktsioon on blokeeruv. // #include <stdio.h> #include <homelab/pin.h> #include <homelab/delay.h> #include <homelab/module/sensors.h> #include <homelab/module/lcd_alpha.h> // // Ultraheli anduri viigud // pin pin_trigger = PIN(G, 1); pin pin_echo = PIN(G, 0); // // Põhiprogramm // int main(void) { unsigned short distance; char text[16]; // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON); // LCD ekraani puhastamine lcd_alpha_clear(); // Programmi nimi lcd_alpha_write_string("Ultraheli"); // Väike paus sw_delay_ms(100); // Lõputu tsükkel while (true) { // Mõõtmine distance = ultrasonic_measure(pin_trigger, pin_echo); // Mõõtmine õnnestus ? if (distance > 0) { // Kauguse tekstiks teisendamine sprintf(text, "%d cm ", distance); } // Mõõtmisel tekkis viga ? else { // Vea tekst sprintf(text, "Viga "); } // Teksti kuvamine LCD teise rea alguses lcd_alpha_goto_xy(0, 1); lcd_alpha_write_string(text); // Väike paus sw_delay_ms(500); } }
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Mootorid on täiturseadmed, õigemini vaid üks osa neist, ja neidki leidub väga erinevaid, alates tööpõhimõttest ja lõpetades võimsuse ja suurusega. Robootikas on peamiselt kasutusel erinevad elektrimootorid. Elektrimootor on seade, mida kasutatakse elektrienergia muundamiseks mehaaniliseks tööks ja mille töö põhineb elektromagnetismi nähtusel.
Elektrimootorite liigitamiseks on mitu erinevat viisi; olulisim on mootorite jaotamine alalisvoolu ja vahelduvvoolu mootoriteks. Lisaks sellele saab elektrimootoreid liigitada harjadega ja harjadeta mootoriteks, lineaarmootoriteks ja pöördmootoriteks, nano- ja maksiskaalas mootoriteks jne. Samas on mitmed liigitused tinglikud. Näiteks lineaarliikumine saadakse tihti ikkagi pöörleva elektrimootori abil, mis on integreeritud ühte korpusesse kruvimehhanismiga ja käsitletakse nii lineaartäiturina. Käesolevas peatükis on tähelepanu pööratud kolmele levinuimale elektrimootorile robootikas, milleks on püsimagnetiga alalisvoolu mootor, RC servomootor ja samm-mootor.
Vajalikud teadmised: [HW] Mootorite moodul, [AVR] Sisendid-väljundid, [LIB] Mootorite teek, [LIB] Viite teek
Püsimagnetiga alalisvoolu mootorid on laialt levinud erinevates rakendustes, kus on vajalikud väiksed mõõtmed, suur võimsus ja madal hind. Tänu nende suhteliselt suurele kiirusele kasutatakse neid koos ülekandega (madala kiiruse ja kõrge pöördemomendi saavutamiseks).
Püsimagnetiga alalisvoolu mootorid on lihtsa ehitusega ja elementaarse juhtimisega mootorid. Kuigi juhtimine on lihtne, ei ole nende pöörlemiskiirus üldjuhul täpselt juhtsignaaliga määratletav, sest see sõltub mitmetest teguritest, eelkõige võllile rakendatavast jõumomendist ja toitepingest. Ideaalse alalisvoolu mootori jõumomendi ja kiiruse suhe on lineaarne, mis tähendab seda, et mida suurem koormus on võllil, seda madalam on kiirus ja suurem mähist läbiv vool.
Harjadega alalisvoolu mootorid töötavad alalispingel ning põhimõtteliselt ei vaja eraldi juhtelektroonikat, kuna kogu vajalik kommutatsioon toimub mootori sees. Mootori töötamise ajal libisevad kaks staatilist harja rootori pöörleval kommutaatoril ning hoiavad mähiseid pinge all. Mootori pöörlemissuuna määrab toitepinge polaarsus. Kui mootorit on vaja juhtida ainult ühes suunas, võib toitevoolu anda relee või muu lihtsa lülitusega, kui mõlemat pidi, siis kasutatakse H-silla-nimelist elektriskeemi.
H-sillas tüürivad mootori pöörlemiseks vajalikku voolu neli transistorit (või nende gruppi). H-silla elektriskeem meenutab H-tähte - sellest ka nimi. H-silla eripära seisneb mootorile mõlemat pidi polaarsuse rakendamise võimaluses. Kõrvaloleval pildil on toodud H-silla põhimõtteskeem lülitite näitel. Kui selles skeemis sulgeda kaks diagonaalis asetsevat lülitit, hakkab mootor tööle. Mootori pöörlemisuund sõltub aga sellest, kummas diagonaalis lülitid suletakse. Reaalses H-sillas on lülitite asemel muidugi transistorid, mis on valitud vastavalt mootori voolule ja pingele.
H-sillaga saab peale pöörlemissuuna muuta ka mootori pöörlemiskiirust - selleks tuleb transistore pulsilaiusmodulatsiooniga (PWM) pidevalt avada ja sulgeda, nii et summaarne mootorile antav energia on midagi seismise ja täisvõimsuse vahepealset. Avatud aega kogu PWM perioodist nimetatakse ka töötsükliks (inglise keeles duty cycle), mida tähistatakse protsentidega. 0% tähendab, et transistor on pidevalt suletud ehk ei juhi voolu, 100% tähendab, et transistor on pidevalt avatud ehk juhib voolu. PWM sagedus peab olema piisavalt kõrge, et vältida mootorivõlli vibreerimist. Madalal sagedusel tekitab mootor ka müra ja seepärast kasutatakse tihti üle 20 kHz moduleerimissagedust. Samas kannatab väga suurtel sagedustel H-silla efektiivsus. Mootorivõlli vibreerimist vähendavad ka rootori inerts ja mootori mähiste induktiivsus.
Väiksemate voolude juhtimiseks leiab H-sildu ka integreeritud komponendina, suuremate voolude jaoks kasutatakse spetsiaalseid võimsustransistore (Power MOSFET). H-silda koos muu elektroonikaga nimetatakse ka mootorikontrolleriks või ajuriks (inglise keeles driver). Kodulaboris kasutatav alalisvoolu mootori ajur L293D sisaldab endas kahte integreeritud H-silda ja kaitsedioode. Mootorit juhitakse kolme digitaalse signaaliga, millest üks on üldine tööd lubav signaal (enable). Teised kaks signaali määravad H-silla transistoride oleku. Kunagi ei tohi olla avatud kaks vertikaalset transistorit, sest see lühistaks toiteallika. Seega on ajur tehtud n-ö. lollikindlana ja valida saab madala või kõrge väärtusega vaid seda, kumb transistor (kas ülemine või alumine) ühest H-silla poolest ehk poolsillast avatud on. Teisisõnu valitakse kahe juhtsignaaliga polaarsust, mis kummalegi mootori mähise otsale rakendatakse.
Märkus: Mitte ajada segamini RC (raadiojuhitav servomootor) PWM signaali tavaliste PWM signaalidega.
Kodulabori mootorite mooduli plaadil on võimalus kuni nelja alalisvoolu mootori ühendamiseks. Skeemid ja ühendamise õpetuse leiab mootorite mooduli peatükist. Sisuliselt on iga mootori jaoks H-sild, mida juhitakse kahe mikrokontrolleri digitaalse väljundviiguga, sest enable viik on konstantselt kõrge. Kui mõlemal juhtviigul on sama väärtus, siis mootor ei liigu, kui erinev, siis moootor pöörleb vastavas suunas. H-silla olekut iseloomustab järgmine tabel:
Sisend A | Sisend B | Väljund A | Väljund B | Tulemus |
---|---|---|---|---|
0 | 0 | - | - | Mootor seisab |
1 | 1 | + | + | Mootor seisab |
1 | 0 | + | - | Mootor pöörleb ühtpidi |
0 | 1 | - | + | Mootor pöörleb teistpidi |
Alalisvoolu mootoreid võib juhtida otse mootorikontrolleri sisendviikudele vastavaid mikrokontrolleri juhtviike manipuleerides, kuid kodulabori teegis on selleks olemas ka lihtsustavad funktsioonid:
// // DC mootorikontrolleri viikude seadistus // static pin dcmotor_pins[4][2] = { { PIN(B, 7), PIN(B, 4) }, { PIN(D, 1), PIN(D, 0) }, { PIN(D, 7), PIN(D, 6) }, { PIN(D, 5), PIN(D, 4) } }; // // Valitud DC mootori juhtimise lubamine // void dcmotor_init(unsigned char index) { pin_setup_output(dcmotor_pins[index][0]); pin_setup_output(dcmotor_pins[index][1]); } // // Valitud DC mootori töötamise ja suuna määramine. // void dcmotor_drive(unsigned char index, signed char direction) { pin_set_to(dcmotor_pins[index][0], direction < 0); pin_set_to(dcmotor_pins[index][1], direction > 0); }
Teegis defineeritakse dcmotor_pins massiiviga ära nelja mootorikontrolleri juhtviigud. Enne mootorite juhtimist tuleb välja kutsuda dcmotor_init funktsioon koos mootorikontrolleri numbri (0 kuni 3) parameetriga, mis seab viigud väljundiks. Juhtimiseks on dcmotor_drive funktsioon, millega antakse valitud mootorile negatiivse direction parameetriga üks ja positiivse arvuga teine pöörlemissuund ning 0 puhul see peatatakse.
Järgnevalt on toodud näidisprogramm, mis juhib esimest ja teist alalisvoolu mootorit, nii et need iga sekundi järel muudavad oma pöörlemissuunda. Kiirust saaks muuta, kui üht juhtviiku moduleerida PWM signaaliga.
// // Kodulabori mootorite mooduli // alalisvoolumootori testprogramm // #include <homelab/module/motors.h> #include <homelab/delay.h> // // Põhiprogramm // int main(void) { // Suuna muutuja signed char direction = 1; // Mootorite 0 ja 1 seadistamine dcmotor_init(0); dcmotor_init(1); // Lõputu tsükkel while (true) { // Üks mootor käib ühtepidi, teine teistpidi dcmotor_drive(0, -direction); dcmotor_drive(1, +direction); // Paus 1 sekund sw_delay_ms(1000); // Suuna ümberpööramine direction = -direction; } }
Vajalikud teadmised: [HW] Mootorite moodul, [HW] Andurite moodul, [AVR] Sisendid-väljundid, [LIB] Mootorite teek, [LIB] ADC teek
RC (lühend, inglise keeles radio-controlled) servomootor on mudelismis ja robootikas laialt levinud täiturmehhanism, mis koosneb väikesest alalisvoolu mootorist, hammasreduktorist ja juhtloogikast. Servomootori rootor liigub üldjuhul mingisse kindlasse asendisse ja üritab siis seda asendit püsivalt hoida. Rootori asend sõltub servomootorile etteantavast juhtsignaalist. Sõltuvalt mootori tüübist võib maksimaalne pöördenurk olla erinev. Harvem esineb pideva pöörlemisega servomootoreid. Sellisel juhul määrab juhtsignaal mitte rootori asendi, vaid pöörlemiskiiruse. Levinud on ka servomootori nn. häkkimine, mille käigus asendit määrav servomootor tehakse ümber pidevalt pöörlevaks. Sisuliselt tähendab see, et asendist tagasisidet andev potentsiomeeter asendatakse kahe fikseeritud takistiga ja eemaldatakse hammasrattalt täispööret takistav mehaaniline takistus. Servomootori üks oluline tunnus on tema hea kaalu ja võimsuse suhe.
Servomootori juhtsignaaliks on spetsiifiline pulsilaiusmodulatsiooniga (PWM) signaal, kus pulsi laius määrab ära rootori asendi. Signaali perioodiks on 20 ms (sageduseks 50 Hz) ja kõrge poolperioodi laiuseks 1-2 ms. 1 ms tähistab üht rootori äärmist asendit ja 2 ms teist rootori äärmist asendit. 1.5 ms tähistab rootori keskasendit.
Traditsiooniline RC servomootor kannab ka analoog-servomootori nime. Põhjus on selles, et viimasel kümnendil tekkisid ka nii-öelda digitaalsed servomootorid. Nende kahe vahe seisneb selles, et analoog-servomootoris juhitakse mootorit sellesama 50 Hz PWM sisendsignaaliga, digitaal-servomootoris juhib mootorit aga eraldi mikrokontroller palju kõrgema sagedusega. Sisendsignaal on digitaalsel servomootoril küll sama, kuid kõrgem mootori moduleerimissagedus võimaldab täpsemat ja kiiremat asendi määramist.
Kodulabori mootorite mooduli plaadil on kaks pistikut RC servomootorite ühendamiseks. Pistikute PWM signaali otsad on ühendatud mikrokontrolleri PB5 ja PB6 viikudega, mille alternatiivfunktsioonideks on taimeri? 1 võrdlusüksuste A ja B väljundid. Taimer 1 on võimeline raudvaraliselt tekitama PWM signaali ja seetõttu on mootorite juhtimine programmis väga lihtne. Keerulisem on ainult taimeri seadistamine.
Taimer 1 tuleb seadistada PWM tekitamise režiimi, kus taimeri maksimaalne väärtus on määratud ICR registriga. Taimeri taktijaguri ja programmis muudetava maksimaalse väärtusega saab täpselt ära määrata servomootori juhtimiseks vajaliku PWM sageduse. Taimeri võrdlusregistriga saab määrata kummagi PWM-signaali kõrge poolperioodi pikkuse. Taimeritel on nimelt spetsiaalsed võrdlusüksused, mis jälgivad loenduri väärtust ja kui see saab samaks võrdlusregistri väärtusega, siis muudavad võrdlusüksuse väljundi väärtust. Järgnevalt on toodud servomootoreid juhtiva kodulabori teegi programmikood, mis universaalsuse eesmärgil kasutab makro funktsioonidega määratud taimeri parameetreid. Näiteks kasutatakse perioodi leidmiseks F_CPU konstanti, mis tähistab mikrokontrolleri taktsagedust. Makrodega ei pea taimeri parameetreid erinevate taktsageduste jaoks ise välja arvutama ja kompilaator teisendab makrodega tehted niikuinii konstantideks, nii et programmimälu ei suurene ja ei võta ka rohkem täitmisaega.
// // Taimeri väärtus PWM täisperioodi (20 ms) saavutamiseks // F_CPU on mikrokontrolleri taktsagedus, mis jagatakse 8-ga // ja 50 hertsiga // #define PWM_PERIOD (F_CPU / 8 / 50) // // PWM servo keskasend (1.5 ms / 20 ms) // Keskasend saadakse täisperioodist 15/200 võtmisega. // #define PWM_MIDDLE_POS (PWM_PERIOD * 15 / 200) // // Kordamistegur, et protsentidest (-100% kuni 100%) vajalik periood saada. // +1 liidetakse selleks, et poolperiood kindlasti ulatuks 1 ja 2 ms // piiridesse või siis natuke üle. // #define PWM_RATIO (PWM_PERIOD / 20 / 2 / 100 + 1) // // Viikude seadistus // static pin servo_pins[2] = { PIN(B, 5), PIN(B, 6) }; // // Määratud servomootori tööks valmistamine. // void servomotor_init(unsigned char index) { // PWM signaali viik väljundiks pin_setup_output(servo_pins[index]); // Taimer 1 seadistamine // Taktijagur 8 // Kiire PWM režiim kus TOP = ICR // OUTA ja OUTB võrdusel madalaks timer1_init_fast_pwm( TIMER1_PRESCALE_8, TIMER1_FAST_PWM_TOP_ICR, TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH, TIMER1_FAST_PWM_OUTPUT_CLEAR_ON_MATCH, TIMER1_FAST_PWM_OUTPUT_DISABLE); // Perioodi määramine maksimaalse väärtuse kaudu timer1_set_input_capture_value(PWM_PERIOD); } // // Servomootori positsiooni määramine. // Positsiooni parameeter on -100 kuni 100 protsenti. // void servomotor_position(unsigned char index, signed short position) { switch (index) { case 0: timer1_set_compare_match_unitA_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; case 1: timer1_set_compare_match_unitB_value( PWM_MIDDLE_POS + position * PWM_RATIO); break; } }
Näiteprogramm kasutab kirjeldatud kodulabori teegi funktsioone. Programmi alguses pannakse esimese servomootori PWM signaali? generaator tööle? servomotor_init funktsiooniga. Servomootori asendi väärtus saadakse analoog-digitaalmuunduri kanalist 3, kuhu on andurite plaadil ühendatud potentsiomeeter. Et servomootori juhtimiseks vajalikku -100 kuni 100 vahemikku saavutada, lahutatakse ADC väärtusest pool maksimumi (ehk 512) ja jagatakse viiega. Tulemuseks on küll ±102, kuid pisike ebatäpsus ei loe, sest servomootorid ise ka erinevad PWM signaali ja pöördenurga suhtelt. Lõplikult tuleb rakendustes PWM poolperioodi laius siiski katse-ja eksitusmeetodil määrata. Ka raadiojuhitavate mudelite pultidel on täpseks seadistuseks vastavad võimalused. Programmi käivitades muutub vastavalt potentsiomeetri asendile ka servomootori rootori asend.
// // Kodulabori mootorite mooduli servomootori // testprogramm. // #include <homelab/adc.h> #include <homelab/module/motors.h> // // Põhiprogramm // int main(void) { short position; // ADC seadistamine adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // Mootori seadistamine servomotor_init(0); // Lõputu tsükkel while (true) { // Potentsiomeetrist positsiooni lugemine ja servo- // mootori piirkonda teisendamine position = ((short)adc_get_value(3) - (short)512) / (short)5; // Servomootori positsiooni määramine servomotor_position(0, position); } }
Vajalikud teadmised: [HW] Mootorite moodul, [AVR] Sisendid-väljundid, [LIB] Mootorite teek
Samm-mootoreid kasutatakse laialdaselt täpsust nõudvates rakendustes. Erinevalt alalisvoolu mootorist puuduvad samm-mootoris harjad ja kommutaator - selleks on seal mitu eraldiseisvat mähist, mida kommuteeritakse välise elektroonikaga (ajuritega). Rootori pööramine toimub mähiseid sammhaaval kommuteerides, ilma tagasisideta. Siit avaldub ka üks samm-mootorite puudus - mehhaanilise ülekoormuse korral, kui rootor ei pöörle, lähevad sammud sassi ja liikumine muutub ebatäpseks. Mähiste järgi eristatakse kahte liiki samm-mootoreid: unipolaarsed- ja bipolaarsed samm-mootorid. Ehituse järgi jaotatakse neid veel kolmeks:
Muutuva magnetilise takistusega samm-mootorites on hambulised mähised ja hambuline rauast rootor. Suurim tõmbejõud tekib mõlema poole hammaste kattumisel. Püsimagnetiga samm-mootorites on, nagu nimigi ütleb, püsimagnet, mis orienteerub vastavalt mähise polaarsusele. Hübriidides on kasutusel mõlemad tehnoloogiad.
Sõltuvalt samm-mootori mudelist läheb mootorivõlli ühe täispöörde (360 kraadi) tegemiseks vaja sadu kommuteerimissamme. Stabiilse ja sujuva liikumise tagamiseks kasutatakse sobivat juhtelektroonikat, mis juhib mootorit vastavalt selle parameetritele (rootori inerts, pöördemoment, resonants jne.). Lisaks võib juhtelektroonikas rakendada erinevaid kommuteerimise meetodeid. Järjest ühe mähise kaupa kommuteerimist nimetatakse täissammuks, kuid vaheldumisi ühe ja kahe mähise kommuteerimist nimetatakse poolsammuks. Kasutatakse ka sinusoidaalset mikrosammu, mis annab eriti täpse ja sujuva juhtimise.
Unipolaarne samm-mootor
Unipolaarsamm-mootor on viie või kuue juhtmega. Vastavalt ajami skeemile käivitatakse korraga ainult üks neljandik mähistest. Vcc liinid on tavaliselt ühendatud mootori positiivse toitepingega. Mähiste otsad 1a, 1b, 2a, ja 2b ühendatakse kommuteerimisel läbi transistoride (mootoriplaadil transistormassiiv ULN2803) ainult maaga, mistõttu nende juhtelektroonika on suhteliselt lihtne.
Bipolaarne samm-mootor
Bipolaarsamm-mootor erineb unipolaarsamm-mootorist selle poolest, et mähiste polaarsust muudetakse kommutatsiooni ajal. Korraga aktiveeritakse pooled mähised, mis tagab võrreldes unipolaarsamm-mootoritega suurema efektiivsuse. Bipolaarsamm-mootoritel on neli juhet, mis ühendatakse kõik eraldi poolsillaga (mootoriplaadil L293D ajur). Kommuteerimisel rakendavad poolsillad mähiste otstele kas positiivset või negatiivset pinget. Unipolaarmootoreid saab käivitada bipolaarajuri abil: selleks ühendada mähiste liinid 1a, 1b, 2a ja 2b (Vcc jääb ühendamata).
Mõlemat liiki mähisega samm-mootori juhtimiseks vajalikku kommutatsiooni täissammu ja poolsammu režiimis kujutab järgnev tabel.
Unipolaarne | Bipolaarne | |||||||
---|---|---|---|---|---|---|---|---|
Samm | 1A | 2A | 1B | 2B | 1A | 2A | 1B | 2B |
Täissamm | ||||||||
1 | 1 | 0 | 0 | 0 | + | - | - | - |
2 | 0 | 1 | 0 | 0 | - | + | - | - |
3 | 0 | 0 | 1 | 0 | - | - | + | - |
4 | 0 | 0 | 0 | 1 | - | - | - | + |
Poolsamm | ||||||||
1 | 1 | 0 | 0 | 0 | + | - | - | - |
2 | 1 | 1 | 0 | 0 | + | + | - | - |
3 | 0 | 1 | 0 | 0 | - | + | - | - |
4 | 0 | 1 | 1 | 0 | - | + | + | - |
5 | 0 | 0 | 1 | 0 | - | - | + | - |
6 | 0 | 0 | 1 | 1 | - | - | + | + |
7 | 0 | 0 | 0 | 1 | - | - | - | + |
8 | 1 | 0 | 0 | 1 | + | - | - | + |
Harjutuse eesmärk on tööle panna bipolaarsamm-mootor, mille asemel saab eespool nimetatud meetodil kasutada ka unipolaarsamm-mootorit. Mootorite mooduli plaadil on olemas ajurid, mida mikrokontrollerist tuleb nelja sisendviiguga juhtida. Iga viik tähistab ühe mähise otsa polaarsust. Mähiseotsa pinge on positiivne, kui viik on kõrge, ja negatiivne, kui viik on madal. Otstele 1A, 1B, 2A ja 2B vastavad mikrokontrolleri viigud on PB0, PB1, PB2 ja PB3.
Bipolaarsamm-mootori juhtimiseks on kodulabori teegis olemas bipolar_init funktsioon, mis seadistab viigud väljundiks ja bipolar_halfstep funktsioon, mis teostab pöörlemist määratud arvu poolsammude võrra. Kommuteerimine toimub poolsammude tabeli järgi, kuid selleks kasutatakse keerukamaid bitioperatsioone.
// // Bipolaarse samm-mootori juhtimise ettevalmistamine // void bipolar_init(void) { DDRB |= 0x0F; PORTB &= 0xF0; } // // Bipolaarse samm-mootori liigutamine poolsammudega // void bipolar_halfstep(signed char dir, unsigned short num_steps, unsigned char speed) { unsigned short i; unsigned char pattern, state1 = 0, state2 = 1; // Suuna kindlustamine +- 1 dir = ((dir < 0) ? -1 : +1); // Poolsammude teostamine for (i = 0; i < num_steps; i++) { state1 += dir; state2 += dir; // Mustri loomine pattern = (1 << ((state1 % 8) >> 1)) | (1 << ((state2 % 8) >> 1)); // Väljundi määramine PORTB = (PORTB & 0xF0) | (pattern & 0x0F); // Pausi tegemine sammu teostamise ootamiseks sw_delay_ms(speed); } // Mootori peatamine PORTB &= 0xF0; }
Funktsioonide kasutamist demonstreerib näiteprogramm, mis pöörab mootorit vaheldumisi ühele ja teisele poole 200 poolsammu. Mootori pöörlemise kiiruse määrab sammude vahel tehtava pausi pikkus. Kui paus liiga väikeseks seada, ei jõua mootor rootori intertsi tõttu pööret teostada ja võll ei liigu.
// // Kodulabori mootorite mooduli bipolaarse // samm-mootori testprogramm // #include <homelab/module/motors.h> // // Põhiprogramm // int main(void) { // Mootori seadistamine bipolar_init(); // Lõputu tsükkel while (true) { // Pööramine ühele poole 200 poolsammu kiirusega 30 ms/samm bipolar_halfstep(+1, 200, 30); // Pööramine teisele poole 200 poolsammu kiirusega 30 ms/samm bipolar_halfstep(-1, 200, 30); } }
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Mikrokontrolleritega saab juhtida täitureid, sellega saab lugeda andurite väärtusi ja mitmeid muid toiminguid, kuid alati jääb vajadus ühendada seadmeid, millega ei saa suhelda lihtsaid digitaalseid signaale edastades. Põhjuseks võib olla näiteks, et seadme juhtimiseks läheb vaja liiga palju juhtsignaale või edastatavad andmehulgad on liiga mahukad. Seepärast on nii mikrokontrolleritele kui ka üldse elektroonikas välja arendatud terve hulk erinevaid andmesideliideste standardeid. Standardid määravad ära signaalide elektrilised parameetrid ja nende signaalide edastamise reeglid, ehk protokolli.
Üks lihtne näide protokollist on morse kood, kus infot edastatakse piiksude ja pausidega ning nende pikkustega. Sarnaselt toimivad ka digitaalsed andmesideprotokollid, kus infot edastatakse bitiväärtustega ja olenevalt liidesest ka moduleeritud kujul. Erinevaid andmesideliideseid koos nende protokollidega on loodud küll vastavalt vajadusele, kuid edastamist vajavad andmehulgad on alati kasvanud ja pidevalt lisandub uusi meetodeid. Rahulikum on olukord elektroonikakomponentidevahelise andmesidega, kus juba pikka aega kasutatakse I²C, SPI ja UART liideseid. Traditsioonilisemad süsteemidevahelised sideliidesed on RS-232, Rs-485, LIN ja CAN, kuid palju mikrokontrollereid toodetakse ka juba USB, Ethernet ja juhtmevaba ZigBee liidestega. Käesolev peatükk aga keskendub kodulaborile, kus peamine andmesideliides on RS-232.
Vajalikud teadmised: [HW] Kontroller, [AVR] USART, [LIB] USART teek, [LIB] Alfabeetilise LCD teek
RS-232 on füüsilise andmesideliidese standard, mida kasutatakse binaarandmete edastamiseks. Standard on kasutusel peamiselt arvutite jadaportides, mida kutsutakse kõnekeeles ka “COM” portideks. Tänapäeval on RS-232 suures osas asendunud USB liidesega, kuid oma lihtsuse tõttu kasutatakse hobirakendustes RS-232 edukalt edasi, eriti veel siis, kui on olemas USB - RS-232 muundurid. RS-232 standard määrab ära pistikud, elektrilised parameetrid ja signaalide tähenduse, kuid mitte protokolli.
RS-232 liidest kasutatakse peamiselt koos UART-nimelise ? riistvaralise andmesidemooduliga, millel on protokoll standardiseeritud, kuid mis jällegi ei määra ära pistikuid jms. Seega RS-232 ja UART täiendavad teineteist. Kuna UART on enamasti üks moodul mikrokontrolleris, millel on digitaalsed sisendid-väljundid, mis ei vasta RS-232 elektrilistele parameetritele, siis omavahel viiakse need kokku spetsiaalsete nivoomuunduritega. Üks tuntumaid RS-232 TTL/CMOS nivoomuundureid on näiteks MAX232.
UART on lahtitõlgituna “universaalne asünkroonne vastuvõtja/saatja” (inglise keeles universal asynchronous receiver/transmitter). USART on peaaegu sama asi? kui UART, kuid selle erinevusega, et andmeid edastatakse koos taktsignaaliga. UART-i võib nimetada ka jadaliideseks. Jadaliides on andmete ülekandmise mehhanism, kus iga bitt edastatakse ükshaaval. Näiteks selleks, et edastada 1 bait, edastatakse kindla ajaintervalliga 8 bitti. Ehk siis füüsiliselt toimub jadaliidese liinil, mis on 1 mikrokontrolleri viik, kindla ajavahemiku järel selle viigu pingeväärtuse muutus kõrgeks või madalaks. Jadaliidesega on üldjuhul ühendatud 2 seadet, millest üks edastab infot (viigu väärtust muutes) ja teine võtab seda vastu (viigu väärtust registreerides). Edastava viigu lühend on TX, vastuvõtval RX. Info liigub ühel liinil alati ühes suunas. Andmete teistpidi saatmiseks kasutatakse teist liini. Andmed võivad kahel liinil samaaegselt liikuda, ehk tegu on täisdupleks-siiniga.
Andmete edastamine toimub UART liideses kaadri (inglise keeles frame) kaupa, milles andmebitte on olenevalt seadistusest 5 kuni 9. Enamlevinud andmehulk on siiski 8 bitti, ehk 1 bait. Peale andmebittide edastakse kaadriga ka lisabitte, mille abil toimub andmete saabumise ja lõppemise hetke äratundmine vastuvõtja poolel. Esimest neist nimetatakse startbitiks mis on alati 0, teist aga stoppbitiks (või bittideks) mis on alati 1. Enne stoppbitti võib tulla ka paarsuse bitt, mida kasutakse andmete korrektsuse kontrolliks. Paarsuse bitt näitab, kas andmebittide hulgas on paaris või paaritu arv ühtesid. See, kumba näitu see omab, sõltub UART liidese häälestusest. Paaruse bitti tänapäeval enam üldjuhul ei kasutata ja selle saab häälestuses ka ära keelata. Nii nagu saab paarsuse bitti seadistada, saab ka andmebittide ja stoppbittide arvu.
Peale kaadri struktuuri on veel üks tähtis parameeter - see on boodikiirus (baud rate), millega määratakse edastatavate sümbolite arv ühes sekundis. Bood näitab nimelt sümbolite arvu. UART puhul on 1 bood aga 1 bitt ja seepärast kaadri juures bittidest saigi räägitud. Põhimõtteliselt võib andmete edastamiseks kasutada ükskõik millist boodikiirust, kuid on olemas hulk üldkasutavaid boodikiirusi, mida tasub kasutada. Näiteks: 9600 bps, 19200 bps, 38400 bps, 57600 bps, 115200 bps.
Lisainformatsioonina võiks teada, et RS-232 standard sisaldab peale andmesignaalide (RX, TX) veel vookontrolli viike DTR, DCD, DSR, RI, RTS ja CTS, mida kasutatakse seadmetevahelise suhtluse juhtimiseks. Näiteks võib seade nende kaudu teada anda, kas ta on valmis andmeid vastu võtma või mitte. Kuna RS-232 liidese originaalne eesmärk oli ühendada arvuteid modemiga, siis mõned signaalid on (pigem olid) kasutusel telefoniliini seisundi näitamiseks.
Kodulabori kontrollerimoodulil on RS-232 isa-tüüpi pesa. Selle kaudu saab kontrolleri arvutiga või teise kontrolleriga ühendada. Arvutiga ühendamiseks tuleb kasutada tavalist pööramata kaablit, mille üks pistik on ema-tüüpi, teine isa-tüüpi. Teise kontrolleriga ühendamiseks tuleb kasutada kaablit kus RX ja TX ning vookontrolli signaalid on risti keeratud ja mõlemad pistikud on ema-tüüpi. Pööratud kaablit nimetatakse ka nullmodemi kaabliks. Järgnevalt on toodud UART jadaliidese kasutamise näiteprogramm. Programm saadab käivitades RS-232 liidese kaudu tervituse ja kuvab sõnumeid, mis saabuvad. Kasutatud on LCD ja USART teeke.
// // Kodulabori kontrollerimooduli arvutiga RS-232 kaudu liidestamine. // Näide kasutab digitaalset sisend-väljundmoodulit koos LCD ekraaniga. // Arvuti terminalis sisestatud tekst kuvatakse LCD-l. // #include <homelab/usart.h> #include <homelab/module/lcd_alpha.h> // // USART liidese määramine // usart port = USART(0); // // Põhiprogramm // int main(void) { char c; unsigned char row = 1; // USART liidese seadistamine usart_init_async(port, USART_DATABITS_8, USART_STOPBITS_ONE, USART_PARITY_NONE, USART_BAUDRATE_ASYNC(9600)); // LCD ekraani seadistamine lcd_alpha_init(LCD_ALPHA_DISP_ON_BLINK); // Ekraanil tervituse ütlemine lcd_alpha_puts("Ootan teadet"); // Kursori teise rea algusesse viimine lcd_alpha_gotoxy(0, row); // Arvutile tere ütlemine usart_send_text(port, "Tere, kirjuta midagi!\r\n"); // Lõputu tsükkel while (true) { // Jadaliidesest märgi lugemine if (usart_try_read_char(port, &c)) { // Kas tegu on reavahetuse märgiga? if (c = '\r') { // Rea vahetamine row = 1 - row; // Rea tühjendamine eelmisest teatest lcd_alpha_clr_line(row); } else { // Märgi otse ekraanile väljastamine lcd_alpha_putc(c); } } } }
Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.
Näidisprojektis üritatakse tuua konkreetsed juhised, kuidas koostada projekti dokumentatsiooni. Milliseid teemasid tuleks käsitleda ja mis iga teema alla kirjutada. Praktilisuse huvides on näiteks toodud ka üks tüüpiline projektdokumentatsioon. Paraku on projekti dokumentatsioon tavaliselt tänu graafilisele materjalile küllalt mahukas ja poleks siia raamatusse kuidagi ära mahtunud. Sellest tulenevalt on näiteprojektis püütud kajastada kõiki punkte, kuid mitte täies mahus. Näiteks joonistest on toodud ainult ühe detaili joonis ja elektroonikaskeemi juures samuti ainult ühe plaadi skeem. Reaalses dokumentatsioonis tuleks sellegipoolest lisada kõigi loodud detailide joonised ja elektroonikaplaatide skeemid. Loodetavasti on näiteprojektist abi ka õpetajatele, kellel on seeläbi lihtsam seletada, mida ta ootab õpilastelt projekti lõpus ja kuidas seda esitada. Sõltuvalt õpilaste tasemest ja konkreetsest situatsioonist võib vabalt osa punkte dokumentatsioonist välja jätta.
Lihtsa mehhatroonikaseadme koostamisel on vaja projekteerida seadme konstruktsioon ja mehaanika, elektroonika ja sensoorika ning juhtimine ja tarkvara. Projektide lõppemisel tuleks koostada töö aruanne - dokumentatsioon, mis peaks koosnema vähemalt järgmistest sisulistest punktidest:
Järgnevalt on esitatud näiteprojekt, mis näitlikustab dokumentatsiooni koostamist ja on abiks oma projekti aruande koostamiseks. Aruanne on raamatu piiratud mahu tõttu paraku lühendatud kujul, kuid püütud on näidata dokumenteerimise erinevaid aspekte.
Liikurrobot (mobiilne robot) on üks tüüpilisemaid roboteid, mida soovitakse ehitada. Väga populaarsed on sumorobotid, mängurobotid (jalgpall, võrkpall jms.), päästeoperatsioone simuleerivad (tuletõrje, isiku või objekti leidmine jms.) robotid ja mitmed muud. Sellistele robotitele korraldatakse maailmas ja ka Eestis mitmeid erinevaid võistlusi ja on isegi kujunenud välja standardklassid (näiteks sumorobotid). Kõigi seda tüüpi robotite ühiseks jooneks on tavaliselt liikuv platvorm, mis võib olla küll erineva konstruktsiooni ja võimekusega, kuid oma baasfunktsionaalsuselt jääb samaks. Selleks baasfunktsionaalsuseks on eelkõige mootorite juhtimine ja baasnavigeerimine, mis hõlmab endas objektidest eelmahoidmist ja soovitud sihtkohta sõitmist. Baasfunktsionaalsusele lisandub tavaliselt ülesande spetsiifiline funktsionaalsus, mis projekteeritakse lähtuvalt projektile esitatavatest nõuetest ja võimalustest.
Alljärgnevalt vaatame ühte tüüpilist liikurroboti platvormi projekti ja selle projekteerimise erinevaid etappe.
Projekteerida ja valmistada Kodulabori komponentide baasil multifunktsionaalne liikurroboti platvorm koos baasnavigatsiooni funktsionaalsusega. Robotplatvorm peab võimaldama lihtsalt muuta tema operatiivfunktsionaalsust, varustades teda erinevate seadmetega:
Robot peab olema võimeline liikuma tasasel pinnal sisetingimustes.
Süsteemi üldine mudel on esitatud plokkdiagrammidena. Süsteemi mudel kirjeldab süsteemi struktuuri, käitumist jt. olulisi aspekte. Alljärgnevalt on näiteks toodud süsteemi struktuuri üldine hierarhiline mudel.
Antud ülesande lahenduseks kasutas meeskond ajurünnaku metoodikat ja genereeris 3 põhimõtteliselt erinevat lahendust. Koostati hindamismaatriks, mille abil leiti optimaalseim konstruktsioon. Lahenduste põhiline erinevus seisnes erinevates liikumisskeemides.
Lihtsustatud hindamismaatriks oli järgmine:
Funktsioon/Lahendus | I | II | III | Kaalutegur |
---|---|---|---|---|
Maksumus | 3 | 4 | 6 | 0,8 |
Valmistamise keerukus | 2 | 4 | 7 | 0,7 |
Manööverdamisvõime | 4 | 8 | 8 | 0,5 |
Läbivus | 5 | 8 | 2 | 0,3 |
Kodulabori rakendatavus | 5 | 4 | 5 | 0,9 |
Kaal | 5 | 6 | 7 | 0,8 |
Kokku (koos kaaluteguriga) | 19 | 27 | 28 |
Hindamisskaala oli 1-10 punkti ja kaalutegur 0-1. Kaalutegurid olid valitud lähtuvalt süsteemile esitatud nõuetest ja piirangutest. Kuigi näiteks lahendus 2 oli oluliselt võimekam raskel maastikul liikumisel, ei olnud seda lähteülesandes nõutud ja vastava funktsionaalsuse kaalutegur oli sellest tulenevalt madal.
Hindamise tulemusena osutus antud ülesande optimaalseimaks lahenduseks ratastel liikuv kahe eraldi mootoriga platvorm. Edasine töö jätkus valitud lahenduse edasiarendusega reaalseks süsteemiks.
Mehaanika püüti valmistada võimalikult lihtne, järgides samal ajal modulaarsuse põhimõtet. Esimene ja tagumine põrkeraud on identsed moodulid. Elektroonika osas on kasutatud kolme moodulit, mis on paigutatud üksteise peale, võimaldades nii lihtsaid ribakaabelühendusi ja tagades samal ajal moodulite suhteliselt lihtsa vahetatavuse. Mootoriteks on valitud Kodulabori komplektis olevad integreeritud reduktori ja koodriga mootorid, mis on ühendatud otse mootorite ajurplaadiga. Ratasteks on kasutatud mudellennuki rattaid, mis on väga kerged ja piisavalt tugevad antud roboti jaoks. Valmistamise lihtsuse huvides on roboti alusplaat ja pealmine plaat identsed. Plaadid on varustatud avadega, võimaldades nii pealmisele plaadile kinnitada erinevaid seadmeid. Kahe plaadi vahele mahub lisaks elektroonikamoodulitele ka aku.
Eraldi on projekteeritud roboti põrkeraud, mis on integreeritud puute- ja joonejälgimise anduritega. Põrkerauad on valmistatud trükiplaatidest, omades lisaks konstruktsioonile ka elektriühendusi. Joonejälgimise andurid on joodetud otse põrkeraua alumisele plaadile. Puuteandurid (mikrolülitid) on paigutatud kahe põrkeraua plaadi vahele ja eestpoolt kaetud ühtse kummiribaga. Kummiriba summutab põrkejõudu ja võimaldab samal ajal täpsemalt tuvastada, mis suunalt löök tuli.
Süsteemi elektroonika on kirjeldatud põhimõttelahendusena ja klassikalise elektriskeemina koos trükiplaadi pildiga.
Näitena on toodud roboti põrkeraua joonejälgimise andurite elektroonika skeem ja vastav trükiplaadi (PCB) skeem.
Roboti juhtimine tuleneb süsteemi käitumismudelist ja on määratud lähteülesande funktsionaalsusega ning nõuete ja piirangutega. Süsteemi käitumismudelist luuakse täpsustatud juhtprogrammi algoritm, millest omakorda lähtutakse tarkvara programmikoodi koostamisel. Kõik kolm taset (käitumismudel-algoritm-lähtekood) peavad olema omavahel kooskõlas.
Algoritm kirjeldab süsteemi juhtloogikat ja on esitatud plokkdiagrammina. Lihtsama algoritmi koostamiseks piisab paarist elemendist ja nendevaheliste seoste kirjeldamisest. Kui roboti algoritm on koostatud korrektselt, siis on sellest roboti juhtprogrammi suhteliselt lihtne koostada. Algoritmis on kasutatud põhiliselt kahte erinevat objekti: ümardatud nurkadega ristkülik tähistab mingit tegevust, väike romb mingi tingimuse kontrollimist ja vastavalt kontrolli tulemusena järgneb edasiste tegevuste käivitamine.
Algoritmis kasutatud tähiste tähendused:
Tähis | Tähendus | 0 | 1 | -1 |
---|---|---|---|---|
M0 | parem mootor | seisab | pöörleb päripäeva | pöörleb vastupäeva |
M1 | vasak mootor | seisab | pöörleb päripäeva | pöörleb vastupäeva |
F | esimene keskmine puuteandur | signaal puudub | signaal olemas | |
FR | esimene parem puuteandur | signaal puudub | signaal olemas | |
FL | esimene vasak puuteandur | signaal puudub | signaal olemas |
Lihtne navigeerimine
#include <homelab/module/motors.h> #include <homelab/pin.h> #include <homelab/delay.h> // Põrkeandurite viikude defineerimine pin front = PIN(C, 0); pin frontleft = PIN(C, 1); pin frontright = PIN(C, 2); // // Põhiprogramm // int main(void) { // Mootorite 0 ja 1 algseadistamine dcmotor_init(0); dcmotor_init(1); // Lõputu tsükkel while (true) { // Mootorite päripäeva käivitamine dcmotor_drive(0, 1); dcmotor_drive(1, 1); // Esimeste puuteandurite signaalide kontroll if (pin_get_value(front) || pin_get_value(frontleft) || pin_get_value(frontright)) { // Keskmise anduri signaali kontroll if (pin_get_value(front)) { // Mootorite reverseerimine dcmotor_drive(0, -1); dcmotor_drive(1, -1); // Paus 1 sekund sw_delay_ms(1000); // Vasaku mootori päripäeva käivitamine dcmotor_drive(1, 1); } // Vasaku anduri signaali kontroll else if (pin_get_value(frontleft)) { // Vasaku mootori päripäeva käivitamine dcmotor_drive(1, 1); } else { // Parema mootori vastupäeva käivitamine // Vasaku mootori päripäeva käivitamine dcmotor_drive(0, -1); dcmotor_drive(1, 1); } // Paus 2 sekundit sw_delay_ms(2000); } } }
Projekti raames valminud robotplatvorm on valmistatud üldjoontes plastikust, välja arvatud mootori kinnitused, mis on valmistatud alumiiniumprofiilist. Elektroonikamoodulid on paigutatud üksteise peale, aku on lahtiselt kahe plaadi vahel. Põrkerauad on valmistatud trükkplaadist ja värvitud mustaks. Roboti pealmine plaat on täiesti sile, võimaldades sinna kinnitada erinevaid soovitud seadmeid. Projekti raames paigaldati robotplatvormile lihtne radar, mis koosnes väikesest RC servomootorist ja infrapunaandurist. Teiseks seadmeks katsetati standardmanipulaatoreid, mille lülisid juhitakse samuti standardsete RC servodega. Mõlemad variandid on näidatud allolevatel piltidel.
Majanduslik kalkulatsioon hõlmab endas komponentide maksumust ja roboti detailide valmistamise ning koostamise kulusid.
Komponentide maksumuse tabel
Komponent | Mark | Kogus | Hind | Maksumus |
---|---|---|---|---|
Mootor | M LE149.6.43 | 2 | 500.- | 1000.- |
Mikrokontroller | uC ATmega128 | 1 | 900.- | 900.- |
Mootorite juhtplaat | Actuator Board v1.2 | 1 | 700.- | 700.- |
Toiteplaat | TP | 1 | 500.- | 500.- |
Joonejälgimise andurid | LFS QRD1114 | 8 | 30.- | 240.- |
TS Microswitch | Puuteandurid | 8 | 25.- | 150.- |
Kere plaat | ABS | 4 | 50.- | 200.- |
Trükiplaadi toorik | 2 | 50.- | 100.- | |
Mootorikinnituse profiil | Al-L | 2 | 10.- | 20.- |
Ratas | 60/10 mm | 2 | 30.- | 60.- |
Aku | NI-MH 9,6 V | 1 | 350.- | 350.- |
Erinevad kaablid | 10 | 20.- | 200.- | |
Mutrid poldid | 1 | 50.- | 50.- | |
Muud tarvikud | 1 | 100.- | 100.- | |
Kokku | 4570.- |
Hinnanguline tööjõu- ja tootmiskulu üksikeksemplari korral.
Töö | Aeg (h) | Hind | Maksumus |
---|---|---|---|
Konstruktsioonidetailide freesimine | 1 | 300.- | 300.- |
Trükiplaatide (põrkerauad) freesimine | 0,5 | 500.- | 250.- |
Roboti konstruktsiooni koostamine | 0,5 | 250.- | 125.- |
Põrkeraudade koostamine (komponentide jootmine) | 1 | 300.- | 300.- |
Programmeerimine | 5 | 300.- | 1500.- |
Dokumentatsiooni koostamine | 3 | 250.- | 750.- |
Kokku | 11 | 3225.- |
Roboti hinnanguline maksumus kokku 7795.-
Arvutatud roboti maksumus on siiski hinnanguline, kuna tegemist on õppeotstarbelise projektiga, kus enamik tööd ja koostamist on tehtud oluliselt suuremas mahus, kuid otsese rahalise tasuta. Seetõttu on töö- ja ajakulu ligikaudne ja ei kajasta tegelikku olukorda.
Mehhatroonikasüsteem (Robot) on loodud meeskonnatööna ja kindla ajakava ning eelarvega, omades seega enamuse olulisi projekti tunnuseid. Projektijuhtimise seisukohalt olid olulised tegevused: aja planeerimine, meeskonnatöö planeerimine ja juhtimine, eelarve jälgimine ja vahendite hankimine, jooksev aruandlus juhendajale, lõpptulemuse presentatsioon ja dokumenteerimine. Projekti aruandele lisatakse töögruppide koosolekute protokollid, projekti plaan (soovitavalt Gantti diagrammina), ressursijaotus (k.a. inimressurss) ja planeeritud ning tegelik eelarve. Näiteks on toodud lihtne tegevuste plaan Gantti diagrammina.
Majanduslik kalkulatsioon näitas meile, et roboti tootmishind on üsna kõrge, eriti kui tegemist on ainueksemplariga, kuid jäi siiski lähteülesandes etteantud piiridesse. Tootmise hinda saaks kindlasti oluliselt alandada, optimeerides komponentide ja materjalikulu ning tootes korraga suurema koguse roboteid. Projekti käigus tutvusime mehhatroonikasüsteemi projekteerimise, valmistamise ja testimisega, mis andis meile esmakordse sellelaadse kogemuse.
Töö lõpus selgus tõsiasi, et roboti korralikuks töötamiseks on vaja oluliselt rohkem aega planeerida testimisele, seda eriti tarkvara osas. Erinevad moodulid ei pruugi alati koos korrektselt töötada, kuigi eraldi katsetades oli kõik korras. See näitab, et süsteemi moodulite integreerimine on tõsine väljakutse ja selleks tuleb planeerida oluliselt rohkem aega ja ressurssi.
Kokkuvõteks arvame, et projekt oli väga huvitav ja hariv ning andis aimu integreeritud süsteemide projekteerimisest ja valmistamisest.
Kui oled jõudnud selle raamatuga lõpule, on sul juba päris palju praktilisi oskusi nii programmeerimise kui ka erinevate seadmete kasutamise osas. Kui oled näiteid ja harjutusi kasutanud valikuliselt, ei ole ka midagi katki. Loodetavasti aitasid need leida lahenduse probleemile, millega tegelesid ja andsid juurde natuke ka teoreetilisi teadmisi. Järgmine loogiline samm oleks hakata koostama intelligentseid seadmeid vastavalt siis oma huviks või ka tööstuslikele rakendustele. Õpilastel soovitaks vaadata ringi ja osaleda mõnel robootika võistlusel või konkursil, näiteks Robotex, Baltic Sumo Cup jms. Kindlasti tasuks aga saadud teadmisi ja oskusi rakendada ka oma igapäevaelu lihtsamaks, turvalisemaks ja huvitavamaks muutmiseks. Näiteks võite endale koju/suvilasse/garaaži lihtsa vaevaga ehitada turvarakenduse, mis kontrollib erinevate anduritega toimuvat ja vajadusel käivitab alarmi ning edastab sõnumi omanikule.
Kui jääd hätta, küsi abi. See raamat ei ole lõplik ja areneb edasi elektroonilises versioonis. Raamat on üks osa robootika õppimise kontseptsioonist, mis sisaldab endas lisaks spetsiifilist veebikeskkonda, mis toetab kogu õpet. Veebikeskkond asub aadressil http://www.roboticlab.eu ja sisaldab endas muude funktsionaalsuste hulgas ka kasutajafoorumit, kus saad kindlasti vastused oma küsimustele. Raamatu elektroonilises versioonis on lisamaterjale ja peatükid ka sellistel teemadel, nagu näiteks Kohtvõrk (Ethernet), Sinihammas (Bluetooth), RFID (Radio-frequency identification), Masinnägemine (Machine Vision), jt.
Õpetajale: Registreerige ennast kindlasti ka robootika õppe tugikeskkonnas http://home.roboticlab.eu ning andke administraatorile märku, et olete õpetaja. Siis saate juurdepääsu harjutusülesannete lahendustele ja kordamisküsimuste vastustele ;)