This is an old revision of the document!


Table of Contents

Eessõna

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 baasplatvormiks 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.

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 mikrokontrolleritest 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 riistvara- ja tarkvaraplatvormi. Viimase juurde kuulub 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üsteemid.

4. osas on praktilised harjutused, mis on konkreetsed näited enam levinud elektroonika- ja elektromehaanikaseadmete 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 seotud peatükkidest. Harjutuste gruppide juurde kuuluvad harjutusülesanded, mida õpetaja saab kasutada täiendava harjutamise eesmärgil. Harjutusülesanded on jaotatud kahte raskusastmesse. Iga teema sisaldab ka kordamisküsimusi, mis enamasti 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

Mikrokontrollerid ja robootika

Mikrokontrollerid

Maailma esimene mikrokontroller Intel 8048

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) mitmete aspektide poolest:

  • Kõik funktsioonid on paigutatud ühe kiibi peale väiksemas ja kompaktsemas mahus.
  • Programmeeritakse kindla ülesande täitmiseks. Funktsionaalsuse muutmiseks tuleb uus tarkvara peale laadida.
  • Väiksem voolutarve, kuna kõik füüsilised parameetrid on väiksemad ja vähem ressursinõudlikumad kui tavaarvutis. Mikrokontrolleri arendajad rõhuvadki tihti madalale voolutarbele, et mobiilsed lahendused suudaksid kauem aku pealt töötada.
  • Sihtotstarbelised sisendid ja väljundid. Mikrokontrolleritel on välja töötatud perifeeriad, et hõlbustada suhtlemist teiste mikrokontrollerite ja arvutitega (näiteid suhtluskanalitest USB, CAN, UART), aru saada füüsilistest reaalse maailma protsessidest (näiteks lüliti lülitus, temperatuuri mõõtmine) ja ise mõjutada ümbritsevat keskkonda (näiteks mootori käitamine, alarmsignaali käivitamine).

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 lisada uusi omadusi.

Robootika

Robootika on ala, mis ühendab endas teadmisi ja tehnoloogiat robotite ehitamisest. 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 piisavalt keerulised ja ajakriitilised, et inimene tuleb asendada automaatse otsustajaga.

 

Mikrokontrollerid robootikas

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:

  • Atmel AVR perekonna mikrokontrollerid (ATmega, ATtiny ja muud)
  • Microchip Technology PIC perekonna mikrokontrollerid (PIC16, PIC24 ja muud)
  • ARM tehnoloogial põhinevad mikrokontrollerid

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 kasutajatugi. Füüsilistest parameetritest tasub jälgida järgmisi:

  • protsessori töösagedus – määrab kiibi töökiiruse
  • programmimälu maht – kui suure mahuga programmi on võimalik kiibile peale laadida
  • andmemälu maht – kui suures mahus andmeid on võimalik käsitleda programmis
  • sisend-väljundviikude arv ja nende funktsioon – erinevatel väljaviikudel on erinevad võimalused
  • taimerite arv – oluline ajakriteeriumite täitmisel
  • voolutarve – oluline mobiilsetes lahendustes

Arenduskeskkonna all mõeldakse PC arvuti tarkvara, mille abil saab 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 - kasutajatoe - 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.

Elektroonika

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 arusaamiseks ja läbimiseks. Kindlasti tulevad need kasuks ka paljudes huviliste isiklikes projektides.

Ohmi seadus

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:

Voolujuhi takistus, rakendatud pinge ja läbiv voolutugevus

I = U / R

kus:

  • I on voolutugevus
  • U on pinge
  • R on takistus

Ohmi seadusest on tuletatud mitmeid teisi valemeid, mida elektroonikas igapäevaselt kasutatakse.

Pingejagur

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:

Pingejaguri elektriskeem

U2 = U1 ⋅ (R2 / (R1 + R2))

kus:

  • U1 on sisendpinge
  • U2 on väljundpinge
  • R1 ja R2 on takistid

Valem tuleneb Ohmi seadusest, mille järgi:

I = U1 / (R1 + R2)

ning:

U2 = I ⋅ R2

Pingejagurit kasutatakse tihti takistuslike andurite ühendamisel, kus üks takistitest asendatakse takistusliku anduriga (näiteks termistor).

LED-i takisti arvutamine

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 voolu ja tekitab vajaliku pingelangu. Õige takisti väärtuse leidmiseks saab kasutada Ohmi seadust:

LED järjestikku takistiga

R = Ur / If = (Uin - Uf) / If

kus:

  • R on takisti takistus.
  • Ur on pingelang takistil.
  • Uin on toitepinge.
  • Uf on LED-i päripinge.
  • If on LED-i voolutugevus.


Kuna takisti valimisel tuleb lähtuda ka selle soojuse eraldamise võimest, siis tuleb leida ka nõutav elektriline võimsus takistil:

Pr = Ur ⋅ If = (Uin - Uf) ⋅ If

Kokkuvõtvalt saab öelda, et LED-i voolu piirav takisti peab olema vähemalt sama suure takistusega, kui R ja vähemalt sama suure võimsusega, kui Pr.

Arvutusnäide:

LED ühendatakse 12 V pingega. Valitud LED-i päripinge on 3 V ja pärivool 20 mA

If = 20 mA = 0,02 A

R = (12 - 3) / 0,02 = 450 Ω

Pr = (12 - 3) ⋅ 0,02 = 0,18 W

Lähim standardne takistus on 470 Ω ja võimsus 1/4 W, nii et sellise takisti valimegi.

C-keel

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, kuid sisaldab palju 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-keele kohta soovitatav lugeda täiendavaid materjale.

Kiirkursus

Programmi ülesehitus

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");
}

Kommentaarid

Programmi saab kirjutada teksti, mida ei kompileerita ja mis on programmeerijale abiks selgitamisel või märkmete tegemisel. Samuti 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
*/

 

Andmed

Andmetüübid

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, kuna vaikimisi ongi andmetüübid 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.

Muutujad

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;

Konstandid

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;

Struktuurid

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;

Massiivid

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;

 

Avaldised

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.

Aritmeetilised

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

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.

Võrdlused

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

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.

 

Funktsioonid

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 tagastamisväärtuseta 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.

 

Laused

Tingimuslause

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;
}

 

Valikulause

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üklid

Tsüklitega saab programmilõiku täita mitmeid kordi.

while

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

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

Tsüklis liikumine

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

AVR mikrokontroller

Järgnevad peatükid tutvustavad AVR mikrokontrollerit, mille põhjal on koostatud kogu käesolev raamat. Mikrokontroller, olgugi et pisike, on täis mitmeid võimalusi, mille kasutamise kohta Atmel on kirjutanud peaaegu 400-leheküljelise juhendi ning lisaks mitmed spetsiifilised lisadokumendid. Kogu sellest infost on siinkohal tehtud kiire ja võimalikult lihtne ülevaade, mis aitab algajal paremini AVR mikrokontrolleri funktsionaalsusest aru saada ja selle dokumentatsioonis orienteeruda.

Tutvustus

ATmega128 SMT pakendis (täpsemalt TQFP64)

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 pagasit, 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 kasutusel ka Kodulabori komplektis. Ü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.

Füüsiline kuju

ATmega32 40 jalaga DIP korpuses

Nagu kõik teisedki kiibid, on AVR pakendatud mingi standardkesta sisse. 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 saab mikrokontrolleri läbipõlemise korral lihtsalt kätte ja uuega asendada. Samas on jalad ka DIP kesta miinuseks, sest nende jaoks on vaja trükiplaadile 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 umbes mündi suurused 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.

ATmega128

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. Toiteotsad on GND ja VCC. AVCC ja AREF on vastavalt analoog-digitaalmuunduri toite ja võrdluspinge viigud. XTAL1 ja XTAL2 on välise kvartsostsillaatori, resonaatori või taktigeneraatori jaoks. Viigud PB0 kuni PG4 tähistavad sisend-väljundsiinide bitte. Viikude alternatiivfunktsioonidest tuleb juttu vastavates peatükkides.

ATmega128 viigud

Registrid

Ü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 saab tuttavaks registri mõistega ja seepärast on järgnevalt seda algajale ka võimalikult lihtsalt selgitatud.

Olemus

Kassetimängija nupud

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:

  • Salvestamine
  • Tagasikerimine
  • Mängimine
  • Edasikerimine
  • Stopp
  • Paus

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.

Registri “elektrilülitite asendid” ja nende bitiväärtused

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.

Kasutamine

C-keele programmis registri väärtuse kirjutamiseks või lugemiseks tuleb selle poole pöörduda nagu muutuja poole. 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 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.

Heksadetsimaalnumbrid

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 lugedes bitte nelja kaupa, alates madalamast järgust. 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. Järgnevalt on toodud kõigile neljale binaartehtele vastav loogikatehe üksiku biti või bittidega.

Eitus, loogiline korrutamine, loogiline liitmine ja mittesamaväärsus

 

  • Eitus / Inversioon
    Eitus muudab biti väärtuse vastupidiseks ehk 0 muutub 1 ja 1 muutub 0. C-keeles on eituse märk “~”.
  • Loogiline korrutamine / Konjunktsioon
    Kahte bitti korrutades on vastus 1, kui mõlemad bitid olid 1, muul juhul on vastus 0. C-keeles on korrutamise märk “&”.
  • Loogiline liitmine / Disjunktsioon
    Kahe biti liitmisel on vastus 1, kui vähemalt ühe biti väärtus oli 1, muul juhul on vastus 0. C-keeles on liitmise märk “|”.
  • Mittesamaväärsus / Välistav disjunktsioon
    Kahe bitiga mittesamaväärsuse tehte korral on vastus 1, kui bittide väärtused teineteisest erinevad, muul juhul on vastus 0. C-keeles on mittesamaväärsuse märk “^”.

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.

Üksiku biti kõrgeks seadmine
Biti kõrgeks seadmise tehe

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
Üksiku biti madalaks seadmine
Biti madalaks seadmise tehe

Ü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

 

Üksiku biti inverteerimine
Biti inverteerimise tehe

Ü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 inverteerimine
Bittide inverteerimise tehe

Kogu registri bittide inverteerimiseks tuleb kasutada eitustehet. See on unaarne tehe ehk tal on ainult üks operand. Kõrvalnäites toodud tehe näeb C-keeles välja niimoodi:

  // Oletame, et REG = 0x0F
  REG = ~REG;
  // Siinkohal REG = 0xF0
Üksiku biti väärtuse lugemine
Biti lugemise tehe

Ü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

 

Biti nihutamine

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.

Bitinihe vasakule

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 järgmiselt:

REG = 0x01 << 5;
// Siinkohal REG = 0x20
Bitinihe paremale

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.

AVR registrid

Selleks et midagi reaalselt mikrokontrolleri registritega teha saaks, tuleb osata selle mikrokontrolleriga läbi saada. Kõigi mikrokontrolleritega käib kaasas üks või mitu andmelehte, kus on dokumenteeritud kogu mikrokontrolleri struktuur ja funktsionaalsus. Andmelehes on kirjeldatud ka registrid. Järgnevalt uurime, kuidas saada aru AVR-i andmelehe registrite kirjeldusest.

Üks AVR register selle andmelehest

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 - suurenevad paremalt vasakule. 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 registrist. Lisaks registritele on nimi ka igal registri bitil - täpselt nagu kassetimängija nuppudelgi. Iga biti kohta on andmelehes olemas 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, kas bitt on loetav (R), kirjutatav (W) või mõlemat (R/W). Näiteks olekubitte ei saa üle kirjutada ja isegi siis, kui seda programmis üritada, ei omanda bit lihtsalt talle omistatavat väärtust. Biti puhul, mida saab ainult kirjutada, on öeldud üks kindel väärtus, mis selle lugemisel alati tuleb. Bittide all teises reas on toodud vaikevää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äitelaused 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

Arhitektuur

AVR-il on sisemine 8-bitine andmesiin, mille kaudu 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.

ATmega128 struktuur

Käsukonveier

AVR-i käsukonveier on kaheastmeline. Samal ajal kui üht instruktsiooni täidetakse, laetakse järgmine instruktsioon programmimälust ootele. 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.

Üldkasutatavad registrid

Üldkasutatavad 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 mälust lugemiseks kasutama andmesiini. Üldkasutatavaid registreid kasutatakse kõikide andmetega seotud aritmeetiliste ja loogiliste operatsioonide tegemiseks.

Assemblerkeeles programmeerides võib kiiret töötlust vajavaid andmeid üldkasutatavates registrites hoida. Kui programmeeritakse C-keeles ja on kindel soov muutuja hoidmiseks üldkasutatavat registrit kasutada, defineeritakse muutuja täiendavalt “register” tüüpi. Näiteks:

register char x;

Käsustik

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 takti. 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 ja 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, null, ületas maksimaalse võimaliku väärtuse (8-bitti), vajas biti ülekandmist järgmisesse tehtesse, ja veel paaril keerukamal juhul.

Näide

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

Programmi pinumälu

Pinumälu (inglise keeles stack) on andmete ülesehitus, kus viimasena mällu kirjutatud andmed loetakse välja esimesena. 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 kasutama ei pea, 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 vastavalt vajadusele üldkasutavaid registreid ja instruktsioone, kuid see teadmine tuleb kasuks. Mikrokontrolleri instruktsioone on oluline tunda ajakriitilistes rakendustes, kus protseduurid peavad toimuma loetud protsessori taktide jooksul.

Töötakt

Nii nagu enamik digitaalelektroonikat, töötab ka AVR kindlal taktsagedusel. Kindel taktsagedus tagab andmevahetuse töökindluse kogu kiibi ulatuses. Taktsignaali ehk töötakti genereerimiseks on AVR-i puhul mitu võimalust.

Sisemine RC ostsillaator

RC ostsillaatori ühendus

See on kiibisisene taktigeneraator, mis ei vaja väliseid komponente. Puuduseks on suhteliselt madal sagedus ja ebatäpsus.

Väline RC ostsillaator

Sama põhimõttega, nagu sisemine RC ostsillaator ja ei oma sisulist eelist eelmise ees.

Kvartsostsillaator

Kvartsostsilaatori ühendus

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.

Keraamiline resonaator

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 temperatuuritundlikumad.

Väline taktsignaal

Välise taktsignaali ühendus

Välist taktsignaali võib tekitada ükskõik mis seade, peaasi et taktsagedus ja amplituut (pinge) oleks lubatud piirides. Näiteks võib skeemis kasutada eraldi taktigeneraatorit, mis takteerib mitut mikrokontrollerit.

Katkestused

Katkestuse (inglise keeles interrupt) saavad AVR-il tekitada loendurid, andmesideliidesed, analoog-digitaalmuundur, komparaator, spetsiaalsed sisend-väljundviigud ja mitmed muud funktsioonid, 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.

Näide

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.

 

Näide

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;
 
	// Globaalne katkestuste lubamine
	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 võib peale 0x1111 ja 0x3333 tekkida ka väärtus 0x3311. Et sellist asja ei juhtuks, tuleks katkestused enne operatsioone, mis toimuvad pikemalt kui 1 takti jooksul, ajutiselt keelata.

Toodud näites muutujale y muutuja x väärtuse omistamine ohutul meetodil:

	// Globaalne katkestuste keelamine
	cli();
 
	// Laadimine
	y = x;
 
	// Globaalne katkestuste uuesti lubamine
	sei();

Digitaalsed sisendid-väljundid

Kõik AVR siinid on loetavad ja kirjutatavad, kui neid kasutada tavalises loogilises sisend-väljundrežiimis (inglise keeles input/output, ehk I/O). 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 siin 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:

  • PORT - siini füüsilise väljundoleku määramiseks.
  • PIN - siini füüsilise sisendoleku lugemiseks.
  • DDR - siini füüsilise suuna määramiseks.

Näide

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 peaaegu üldse signaaliallikat. Seda režiimi võib vaja minna, kui viiku kasutatakse andmesiinina. Kui viik on kasutusel nupu, lüliti või muu 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

Välised katkestused (inglise keeles external interrupt) on ühed lihtsamad 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 tuleks viik seadistada tavalise IO sisendrežiimi (võib ka väljundrežiimis kasutada, aga siis saab katkestust tekitada vaid kontroller ise). Välise katkestuse seadistusregistrites tuleb ära märkida katkestuste tekitamise lubamine ja tingimus, mille peale seda teha. Võimalikke tekitajaid on neli:

  • Loogiline null (pinge on 0V)
  • Loogilise väärtuse muutus
  • Langev front - loogiline muutus ühest nulli.
  • Tõusev front - loogiline muutus nullist ühte.

Katkestuse tekitamiseks loogilise nulli valimisel tekitatakse katkestust järjest senikaua, kuni viigu väärtus on null. Põhiprogrammi töö on samal ajal peatatud.

Lähtudes tööpõhimõttelt, on väliseid katkestusi kahte liiki: kontrolleri taktiga sünkroniseeritud ja asünkroonsed. Sünkroniseeritud katkestused toimivad sisendite väärtuse meelespidamise teel, mis tähendab, 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, kas ei teki õigesti või jäävad üldse vahele. Asünkroonsed katkestused ei sõltu kontrolleri taktist ja võimaldavad tuvastada ka 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.

 

Näide

Vaja on panna ATmega128 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). Need rakenduvad siis, kui vähemalt ühe viigu väärtus grupis muutub.

Analoog-digitaalmuundur

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 on suhteliselt aeganõudev, 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 taktid. Maksimaalse täpsuse saamiseks peaks ADC takt olema 50-200 kHz. Kõrgemal taktil kaob täpsus. Vahel on ka mõõtmiste suur arv olulisem kui täpsus ja siis on põhjendatud suurema sageduse kasutamine. Ü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.

 

Näide

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,
	// teisendustakti seadmine 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/Taimerid

Loendurid (inglise keeles counter), teatud mõttes taimerid (inglise keeles timer), on mikrokontrollerite ühed oluliseimad 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 sisemine eraldiseisev taktsignaali generaator, mille sagedust saab sageduskordistiga tõsta. Loendurid erinevad ka rakendusvõimaluste ja töörežiimide poolest.

Loenduri normaalrežiim

Normaalrežiimis ei täida loendur muud funktsiooni kui pidevat järestikulist arvude loendamist. Loenduri väärtust saab igal hetkel programmis muidugi ka lugeda ja muuta. Ainuke lisavõimalus normaalrežiimis on katkestuse tekitamine loenduri ületäitumisel. Normaalrežiimi kasutatakse tavaliselt mingi programmilõigu täitmiseks kindlate ajaintervallide järel.

Näide

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>
 
ISR(TIMER0_OVF_vect)
{
	// Loendurile sellise väärtuse omistamine,
	// et järgmine ületäitumine tekiks 10 ms pärast.
	// Valem: 256 - 8 MHz / 1024 / 100 Hz = 177,785 = ~178
	TCNT0 = 178;
}
 
int main()
{
	// Et esimene ületäitumise katkestus tekiks 10 ms pärast,
	// tuleb ka siinkohal loendur algväärtustada.
	TCNT0 = 178;
 
	// Sagedusjaguri teguriks 1024
	TCCR0 = 0x07;
 
	// 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 ka 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.

Välise taktiga loendur

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.

Sündmuste mõõtmine

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.

Näide

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
	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äärtus. Riistvaraline sündmuste püüdmine on siiski mõeldud eeskätt programmist sõltumatuks töötamiseks ja suhteliselt lühiajaliste (või tihedate) sündmuste mõõtmiseks.

Signaali genereerimine

Keerukamate loenduritega saab peale signaali pikkuse mõõtmise 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 nende registrite 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. Valida on võrdusmomendil viigu kõrgeks muutumise, madalaks muutumise ja ümbermuutumise vahel. Väljundviigu oleku muutused tekitavadki signaali.

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. Lisaks sellele on võimalik loendurit seadistada režiimi, kus see toimib nii juurde- kui mahalugemisel.

Loendurid ja nende abil genereeritavate signaalide režiimid on ühed keerulisemad perifeeriamoodulid AVR-il. Kõigist neist kirjutamine läheks pikaks ja enamasti pole nende kasutamisel kõike detailselt teada. Seetõttu on järgnevalt kirjeldatud vaid üht levinuimat PWM signaali robootikas. Ülejäänut saab juba AVR dokumentatsioonist järgi uurida.

Pulsilaius-modulatsioon

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.

Näide

Vaja on 8 MHz taktsagedusel töötava ATmega128-ga genereerida kaks kiirusreguleeritavat servomootori 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

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 aga mitte. AVR-i USART võimaldab täisduplekssidet, 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, kuid mõnel puudub USART üldse. Andmete edastamine toimub sõna kaupa, ehk AVR teeb riistvara 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 saatmise õnnestumise olekubitt kõrgeks.

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 ongi oluline saabuvad sõnad kiiresti programmi lugeda, kasutades selleks näiteks katkestust. 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 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.

 

Näide

Seadistada 8 MHz taktsagedusel töötav ATmega128 USART0 liides boodikiirusel 9600 bps asünkroonselt edastama 8-bitiseid sõnu 1 stop-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 mõtet, sest saadetakse alles
	// esimest märki, küll tasub seda teha rohkemate märkide korral.
	while (!(UCSR0A & (1 << UDRE))) continue;
 
	// Märgi kirjutamine puhvrisse, kust see ka teele saadetakse
	UDR0 = 'X';
 
	// Lõputu tsükkel
	while (1) continue;
}

Robootika Kodulabor

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 ning 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.

Integreeritud robootika õppe kontseptsioon

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 samal 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 praktilises õppes.

Õppe kontseptsioon sisaldab endas järgnevaid õppeabimaterjale:

  • Tavaline käsiraamat-õpik, näiteks “Integrated Systems & Design” ISBN:978-9985-59-850-4.
  • Praktiline harjutusülesannete kogu, näiteks käesolev raamat.
  • Robootika Kodulabor.
  • Mehhatroonika Kauglabor.
  • Robootika õpetajate ja õpilaste võrgustik http://www.roboticlab.eu.

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, 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.

Kodulabori veebikeskkond
http://home.roboticlab.eu

Kauglabori veebikeskkond
http://distance.roboticlab.eu

 

Õppeprotsessi ühe teema/laboritöö raames kirjeldab järgnev skeem.

Teema algab sissejuhatava loenguga, mis võib toimuda klassikalise kontakttunnina, kaugloenguna (juhul kui õpetaja on eemal) või videoloenguna. Videoloeng on oluline isegi sel juhul, kui toimub tavaloeng, võimaldades nii ka puudunud õpilastel loengumaterjalist osa saada või osalenud õpilastel soovi korral loeng üle vaadata. Teemat tutvustav loeng sisaldab endas praktilise näite koos läbitegemist ja õppetajapoolset protsessi 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ööde “Harjutusülesannete” osast. Praktiline töö teostatakse Kodulaboriga või mõne muu robootika komplektiga, mida toetab teoreetiline ja praktiline juhend, 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 nii juhendajalt kui ka kaasõpilastelt.

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.

Robootika õpetamisest

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….

  1. Grupi suurus

Optimaalse õpilaste arvu laborikomplektiga tegutsemiseks määrab suuresti ära juba arvutikasutamise võimalus. See tähendab, et ühe arvuti taha mahub enamasti kuni 3 inimest nii, et veel kõik saavad toimuvast aktiivselt osa võtta. Suurema arvu juures ei näe osa õpilasi enam kirjutatavat koodi ja neil hakkab igav ning tunnitööga enam ei tegeleta.

  1. Praktiline töö ja aruandlus

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 õpilastelt 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 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 toodud välja etappidena, mis võivad omakorda varieeruda vastavalt situatsioonile.

  • Laboritöö tutvustus
    • Õpetaja selgitab kõigepealt uut laboritööd, võttes läbi kogu teoreetilise materjali, ning hiljem uuritakse koos läbi selgitav näide (programmi kood).
    • Õpetaja jaotab labori materjali etappideks, nii et iga etapp koosneb teooriast ja koodi kirjutamisest. Seega kirjutatav programmikoodi näide valmib koos teooria selgitamisega.
  • Iseseisev ülesannete lahendamine. See toimub laboritöö juhendi järgi, kus on kirjas ülesanne, nõuded ja aruandluse vorm. Õpilased teevad tööd iseseisvalt, võimalusel saavad õpetajalt abi küsida. Eesmärk on, et õpilased jõuaksid ise lahenduseni. Kui on võimalus anda õpilastele laborikomplekt koju kaasa, siis iseseisev töö ei pea toimuma kindla tunni ajal, vaid õpilased teevad tööd endale sobival ajal.
  • Tööde esitamine. Õpilased koostavad tehtud tööst aruande, kus nad vastavad lisaks õpetaja poolt määratud kordamisküsimustele. Aruandlus koos kompileeritud lahendusega (hex failina) saadetakse õpetajale kindlaks ajaks elektrooniliselt.
  • Kontroll
    • Õpetaja kontrollib, kas lahendus töötab ning paneb hinde saadetud töö ja aruandluse alusel.
    • Õpetaja kontrollib, kas lahendus töötab ning palub grupil tööd kaitsta suuliselt nii, et üks õpilane peab selgitama teatud osas aruandest, teine õpilane teist osa, jne.
  1. Gruppide haldamine

Ü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.

  1. Hindamine

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.

  1. Veaotsing

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.

  1. Võistlus

Üks võimalus motivatsiooni tõstmiseks ja kogu õppeprotsessi huvitavamaks muutmiseks on 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

  1. Teha läbi näiteülesanne potentsiomeetriga.
    http://home.roboticlab.eu/et/examples/sensor/potentiometer
  2. Teha ühine harjutus “Soojendusülesanne”
    http://home.roboticlab.eu/et/exercises/sensor
  3. Teha grupi personaalne harjutusülesanne (mille määrab õppejõud vahetult enne töö alustamist)
  4. Vastata kordamisküsimuste ühele küsimusele (küsimuse määrab õppejõud vahetult enne töö alustamist)

Aruanne

Tehtud töö kohta tuleb esitada elektrooniline aruanne, mis sisaldab:

  • Seletuskirja töö käigu kohta
    • Töö eesmärk
    • Lühikirjeldus tehtud töödest
    • Algoritm ja väljatrükk programmi algkoodist sammude 2 ja 3 kohta
      NB! Lähtekood peab olema kommenteeritud ja värvitud (võib kasutada “Programmer's Notepad” abi).
    • Küsimuse vastus (samm 4)
    • Järeldused ja kommentaarid
  • Ülesannete 2 ja 3 töötav lahendus HEX failina.

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

  1. Kodulabori tugikeskkond: http://home.roboticlab.eu
  2. ATmega128 andmeleht
  3. Sharp infrapunaanduri andmeleht

Kodulabori riistvara

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, sest 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.

Kodulabori baaskomplekt

Kodulabori baaskomplekt
  • AVR ATmega128 arendusplaat
  • Digitaal sisend-väljundplaat (nupud, LED-id, 2 x LCD väljund, 7-segment-indikaator)
  • 2 x 16 tähemärgiga taustavalgustusega LCD ekraan
  • JTAG programmaator ja silur (USB) + kaabel
  • Näiteülesanded koos C-lähtekoodiga (näidisharjutus)
  • Toiteplokk
  • Multimeeter
  • Tarkvara assembler- ja C-keeles programmeerimiseks
  • Kaasaskantav kohver

Andurite ja Mootorite lisakomplekt

Andurite ja Mootorite lisakomplekt

Mootorite moodul

  • Alalisvoolumootor (reduktoriga)
  • RC servomootor
  • Samm-mootor (bipolaarne või unipolaarne samm-mootor)
  • Mootorite ajuriplaat
  • Toitejagur
  • Ribakaabel

Andurite moodul

  • Analooganduri ja madalpääsu filtri kombineeritud plaat koos anduritega (temperatuuri andur, valgustugevuse andur, potentsiomeeter)
  • Ultraheli kaugusandur SRF05 koos kaabliga
  • Infrapuna kaugusandur SHARP koos kaabliga
  • Ribakaabel

 

Kodulabori täiskomplekt

Kodulabori täiskomplekt sisaldab kõiki komponente Kodulabori baaskomplektist ja Andurite ja Mootorite lisakomplektist ning lisaks järgmisi mooduleid:

RFID moodul

  • Lugeja
  • Märk (2 tk)
  • Kaabel

Kommunikatsiooni moodul

  • Bluetooth
  • Ethernet
  • SPI

Masinnägemise moodul

  • Intelligentne kaameramoodul (CMUcam3)
Kodulabori täiskomplekt

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, kuna mõningad harjutused ja näited võivad olla koostatud uuematele versioonidele.

Kontrollermoodul

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:

  • ATmega128-16AU mikrokontroller
    • 8-kanaliga analoog-digitaalmuunudr (ADC)
    • 128 kB flash-mälu (programmi mälu)
    • 6 kanaliga programmeeritav PWM generaator
  • 4 kB EEPROM mälu (andmemälu)
  • Standardne 6-viiguga ISP (inglise keeles in-system programming interface) programmeerimise liides
  • 14,7456 MHz taktigeneraator
  • Reaalaja kell RTC (inglise keeles real time clock)
  • Programmeeritav oleku LED (PB7) ja toite indikaator-LED
  • Standardne RS-232 jadaliidese pistikupesa
  • Grupeeritud AVR viigud (1: pordid D, B, E; 2: pordid G, C, A; 3: port F)
  • Taaskäivitamise (inglise keeles reset) nupp
  • JTAG 10-viiguga programmeerimise liides
  • 2,1 mm toitepistiku pesa
  • Pingestabilisaator ja valepolaarsuse kaitse
Mikrokontrolleri arendusplaat - Kontrollerplaat

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 toitesillas (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.

Plaadile on paigaldatud lisamälu - 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.

Kontrollerplaadi komponendid

Ühenduspesade viigud ja nende funktsioonid

NrViikAlternatiivfunktsioon / kirjeldus
1VCC- +5 V
2GND- Maa
3REFAREFADC võrdluspinge sisend
4GND- Maa
5PF0ADC0ADC sisendkanal 0
6GND-Maa
7PF1ADC1ADC sisendkanal 1
8GND-Maa
9PF2ADC2ADC sisendkanal 2
10GND-Maa
11PF3ADC3ADC sisendkanal 3
12GND-Maa
13PF4ADC4/TCKADC sisendkanal 4 või JTAG taktsignaal
14GND-Maa
15PF5ADC5/TMSADC sisendkanal 5 või JTAG režiimivalik
16GND-Maa
17PF6ADC6/TDOADC sisendkanal 6 või JTAG andmete väljund
18GND-Maa
19PF7ADC7/TDIADC sisendkanal 7 või JTAG andmete sisend
20GND-Maa

 

NrViikAlternatiivfunktsioon / kirjeldus
1 PD7T2 Taimer/Loendur2 taktsignaali sisend
2 PD6T1 Taimer/Loendur1 taktsignaali sisend
3 PD5XCK1 USART1 taktsignaali sisend/väljund
4 PD4IC1 Taimer/Loendur1 sündmuste püüdja sisend
5 PD3INT3/TXD1Väline katkestus 3 või UART1 andmete väljund
6 PD2INT2/RXD1Väline katkestus 2 või UART1 andmete sisend
7 PD1INT1/SDA Väline katkestus 1 või TWI andmesignaal
8 PD0INT0/SCL Väline katkestus 0 või TWI taktsignaal
9 VCC- +5 V
10GND- Maa
11PB7OC2/OC1C Taimer/Loendur2 või Taimer/Loendur1 võrdlustulemuse väljastusüksus (C)
12PB6OC1B Taimer/Loendur1 võrdlustulemuse väljastusüksus B
13PB5OC1A Taimer/Loendur1 võrdlustulemuse väljastusüksus A
14PB4OC0 Taimer/Loendur0 võrdlustulemuse väljastusüksus
15PB3MISO SPI master andmete sisend / SPI slave väljund
16PB2MOSI SPI master andmete väljund / SPI slave sisend
17PB1SCK SPI taktsignaal
18PB0SS SPI slave valik
19PE7INT7/IC3 Väline katkestus 7 või Taimer/Loendur3 sündmuste püüdja sisend
20PE6INT6/T3 Väline katkestus 6 või Taimer/Loendur3 taktsignaali sisend
21PE5INT5/OC3CVäline katkestus 5 või Taimer/Loendur3 võrdlustulemuse väljastusüksus C
22PE4INT4/OC3BVäline katkestus 4 või Taimer/Loendur3 võrdlustulemuse väljastusüksus B
23PE3AIN1/OC3AKomparaatori negatiivne sisend või Taimer/Loendur3 võrdlustulemuse väljastusüksus A
24PE2AIN0/XCK0Komparaatori positiivne sisend või USART0 taktsignaali sisend/väljund
25PE1PDO/TXD0 ISP Programmeerimisliidese väljund või UART0 andmete väljund
26PE0PDI/RXD0 ISP Programmeerimisliidese sisend või UART0 andmete sisend

NrViikAlternatiivfunktsioon / kirjeldus
1 GND- Maa
2 VCC- +5 V
3 PA0AD0Välismälu-liidese aadressi- ja andmebitt 0
4 PA1AD1Välismälu-liidese aadressi- ja andmebitt 1
5 PA2AD2Välismälu-liidese aadressi- ja andmebitt 2
6 PA3AD3Välismälu-liidese aadressi- ja andmebitt 3
7 PA4AD4Välismälu-liidese aadressi- ja andmebitt 4
8 PA5AD5Välismälu-liidese aadressi- ja andmebitt 5
9 PA6AD6Välismälu-liidese aadressi- ja andmebitt 6
10PA7AD7Välismälu-liidese aadressi- ja andmebitt 7
11- - Pole ühendatud
12- - Pole ühendatud
13PG2ALEVälismälu-liidese aadressi lukustussignaal
14- - Pole ühendatud
15PC6A14Välismälu-liidese aadressi- ja andmebitt 14
16PC7A15Välismälu-liidese aadressi- ja andmebitt 15
17PC4A12Välismälu-liidese aadressi- ja andmebitt 12
18PC5A13Välismälu-liidese aadressi- ja andmebitt 13
19PC2A10Välismälu-liidese aadressi- ja andmebitt 10
20PC3A11Välismälu-liidese aadressi- ja andmebitt 11
21PC0A8 Välismälu-liidese aadressi- ja andmebitt 8
22PC1A9 Välismälu-liidese aadressi- ja andmebitt 9
23PG0WR Välismälu kirjutussignaal
24PG1RD Välismälu lugemissignaal
25- - Pole ühendatud
26- - Pole ühendatud

 

Ühendamine

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).

Kontrollerplaadi ühendamine toite ja programmaatoriga

Digitaalne sisend-väljundmoodul

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:

  • Rohelise, kollase ja punase valgusdioodiga (LED)
  • Kolme mikrolülitiga.
  • 7-segmendilise numberindikaatoriga.
  • Alfabeetilise LCD ühenduspistikuga.
  • Graafilise LCD ühenduspistikuga (alates versioonist 3.2).
  • Ultraheli kaugusanduri ühenduspistikuga (alates versioonist 3.3).

Elektrilised ühendused

Digitaalse- ja Kontrollermooduli vaheline ühendus

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 olla 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).

Nuppude ja LED-ide ühenduse skeem

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 viiguga PC6, taktisignaal (CLK) viiguga PC7 ja lukustussignaal (LATCH) viiguga PG2.

7-segmendilise numberindikaatori ühenduse skeem

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.

LCD ekraanide ühenduse skeem

Mooduli ühendamine

Mooduli ühendamine on soovitatav teostada alltoodud järjekorras. Enne ühendamist veenduda, et Kontrollermooduli toide oleks lahti ühendatud.

  1. Ühendada Digitaalne sisend-väljundmoodul Kontrollermooduliga, kasutades ribakaablit.
  2. Ühendada vajadusel JTAG programmaator Kontrollermooduliga.
  3. Ühendada Kontrollermooduli toide.
Digitaalse sisend-väljundmooduli ühendamine

LCD moodul

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 ühendatakse porti PA. Korraga saab kasutada ainult ühte LCD ekraani.

LCD ekraani ühendamine

Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja enne ühendamist veenduda, et Kontrollermooduli toide on lahti ühendatud.

  1. Ühendada Digitaalne sisend-väljundmoodul Kontrollermooduliga kasutades ribakaablit.
  2. Ühendada alfabeetiline või graafiline LCD ekraan Digitaalmooduliga (korraga ainult üks).
  3. Ühendada vajadusel JTAG programmaator Kontrollermooduliga.
  4. Ühendada Kontrollermooduli toide.
LCD ekraanide ühendamine

Andurite moodul

Andurite moodul koosneb integreeritud andurite ja madalpääsu filtri plaadist ning kaugusanduritest.

Anduri moodul on varustatud:

  • Ultraheli kaugusanduriga Devantech SRF05 koos kaabliga (mõõtepiirkond 1-400 cm) andmeleht
  • Infrapuna kaugusandur Sharp GP2Y0A21YK0F (mõõtepiirkond 10-80 cm) andmeleht
  • Valgustundlik andur (fototakisti) VT935G (takistus 18,5 kΩ 10 lux juures) andmeleht
  • Temperatuuriandur (NTC termistor) (takistus 10 kΩ 25 °C juures) andmeleht
  • Potentsiomeeter 5 kΩ

Andurite plaat

Elektrilised ühendused

Andurite- ja Kontrollermooduli vaheline ühendus
Andurid
Andurite ühenduse skeem

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 sellegipoolest soovitakse kasutada väliseid andureid koos JTAG programmaatoriga, tuleb sildade abil ADC0-ADC3 kanalid plaadil olevatelt anduritelt välistele viikudele ümber lülitada.

Madalpääsu filter
Madalpääsu filtri ühenduse skeem

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 ühendamine

Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja enne ühendamist veenduda, et Kontrollermooduli toide on lahti ühendatud.

  1. Ühendada moodul Kontrollermooduliga (20 soonega ribakaabel). NB! Kontrollermooduliga ühendatakse pistikupesa, mis on tähistatud nimega PF (CON1).
  2. Ühendada vajadusel infrapuna kaugusandur (must juhe - GND).
  3. Ühendada vajadusel Digitaalmoodul ja LCD ekraan.
  4. Ühendada vajadusel ultraheli kaugusandur (must juhe - GND).
  5. Ühendada Kontrollermooduli toide.
Andurite mooduli ühendamine

Mootorite moodul

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, sest sisaldab H-sildu (L293D), mis on mootorite juhtimisel üldlevinud.

Mootoriplaat eraldab mootorite toited juhtsignaalidest ning võimaldab ühe ribakaabliga ühendada kõik juhtsignaalid kontrollerplaadiga.

Mootoriplaat

Moodul võimaldab juhtida erinevaid mootoritüüpe ning kõigil tüüpidel võib olla erinev toitepinge. Mooduli (ühendus)võimalused:

  • 4 x alalisvoolumootor või 3 x alalisvoolumootor ja 2 x kooder.
  • 2 x unipolaarne samm-mootor.
  • 1 x bipolaarne samm-mootor.
  • 2 x RC servomootor.
  • Eraldi UART pistik.
  • Juhtkiipide toite valiku sild JP1 (kontrollerplaadilt või väline).
  • Toite LED.

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.

Mootorid

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.

  • Alalisvoolumootor
    • Micromotors L149.6.10 (reduktor) andmeleht
    • Micromotors L149.6.43 (reduktor) andmeleht
    • Micromotors LE149.6.10 (reduktor + kooder) andmeleht
  • RC servomootor
  • Unipolaarne samm-mootor
  • Bipolaarne samm-mootor
  • Pieso heligeneraator (valikuline)
Mootorid

 

Elektrilised ühendused

Mootoriplaat 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.

Mootorimooduli ja Kontrollermooduli plaatidevaheline ühenduspistik, Mootoriplaadi toite ühendus ja UART pistiku ühendus
Alalisvoolumootor

Alalisvoolumootorid ü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.

 

Alalisvoolumootori ühenduse skeem
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
Samm-mootorid

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
Unipolaarse (vasakul) ja bipolaarse (paremal) samm-mootori mähised
Samm-mootorite ühenduse skeem
Servomootor

RC servomootorid ühendatakse mootoriplaadi 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
Mootorite ühendused
Mootorite ühendused

 

Mooduli ühendamine

Mooduli ühendamisel on soovitatav järgida allolevat järjekorda ja kontrollerplaadi toitepistik ühendada alati kõige viimasena.

  1. Ühendada Mootorite mooduli plaat Kontrollermooduli plaadiga, kasutades ribakaablit.
  2. Ühendada mootor(id).
  3. Ühendada Mootorite mooduli plaat toitekaabliga.
  4. Ühendada Kontrollermooduli toide.
Mootorite mooduli ühendamine

Kodulabori teek

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.

Kodulabori teegi lähtekoodi failipuu

Sellest, kuidas Kodulabori teeki reaalselt Windows ja Linux operatsioonisüsteemidega kasutama hakata, räägivad esimesed kaks praktilist harjutust. Erinevaid teegi osasid kasutavad erinevad harjutused. Eranditult tuleb igasse teeki kasutavasse projekti kaasata teegi “.a” fail mis lingitakse kompilaatori poolt projekti kompileeritud failiga. Päisefaile tuleb kaasata vastavalt vajadusele. AVR-iga seotud teegi osade päisefailid asuvad “homelab” kaustas, Kodulabori moodulitega seotud teegi osad “homelab/module” kaustas. Nimetatud kaustad asuvad kompilaatori juurkaustas ja neist failide kaasamiseks peab faili nime kirjutama suurendus- ja vähendusmärkide vahel. Näide AVR-i viikude ja Kodulabori Mootorite mooduli teegi kaasamisest:

#include <homelab/pin.h>
#include <homelab/module/motors.h>

Kui Kodulabori teeki ei kasutata, siis on vajalik AVR-i registrite kasutamiseks kaasata projekti:

#include <avr/io.h>

Teegi kasutamise korral seda eraldi teha ei ole vaja, kuna on kaasatud juba failis pin.h.

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. Järgnevad peatükid kirjeldavad teegi erinevaid osasid mida kasutatakse raamatu näidisprogrammides.

Bitioperatsioonid

Bitioperatsioonide teek on üldkasutatav makrofunktsioonide kogum tüüpiliste bititehete teostamiseks. Neid funktsioone võib kasutada ükskõik milliste registrite või andmetüüpide puhul, sest makrofunktsioonidel pole kindlat andmetüüpi. Funktsioonid sobivad nii 8-, 16- kui ka 32-bitiste muutujate ning registrite jaoks. Neid bitioperatsioone kasutavad kõik teised teegi osad, seepärast on lähtekoodi alampeatükis funktsioonid ka välja kirjutatud.

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.

Funktsioonid

  • bit_mask(bit)

Bitiindeksi teisendamine bitimaskiks. Parameetrid:

  • bit - Bitiindeks.
  • Tagastab bitimaski.
  • bit_set(value, bit)

Muutujas kindla biti kõrgeks seadmine. Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • bit_clear(value, bit)

Muutujas kindla biti madalaks seadmine. Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • bit_set_to(value, bit, state)

Muutujas kindla biti soovitud olekusse seadmine. Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • state - Tõeväärtus (true või false).
  • bit_invert(value, bit)

Muutujas kindla biti oleku ümberpööramine (madal kõrgeks ja vastupidi). Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • bit_is_set(value, bit)

Väärtuse kindla biti kõrgeloleku kontroll. Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • Tagastab tõeväärtuse true, kui bitt on kõrge ja false, kui bitt on madal.
  • bit_is_clear(value, bit)

Väärtuse kindla biti madaloleku kontroll. Parameetrid:

  • value - Muutuja.
  • bit - Bitiindeks.
  • Tagastab tõeväärtuse true, kui bitt on madal ja false, kui bitt on kõrge.

Näide

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);
}

Lähtekood

Järgnevalt on lühendatud kujul toodud teegi lähtekood, kust on näha, mis iga makrofunktsiooni taga peitub:

//
// Funktsioonid bittidega tegelemiseks
//
#define bit_mask(bit)            (1 << (bit))
#define bit_set(value, bit)      value |= bit_mask(bit)
#define bit_clear(value, bit)    value &= ~bit_mask(bit)
#define bit_invert(value, bit)   value ^= bit_mask(bit)
#define bit_is_set(value, bit)   ((value) & (bit_mask(bit)))
#define bit_is_clear(value, bit) (!((value) & (bit_mask(bit))))
#define bit_set_to(v, b, x) v = ((x) ? (v | bit_mask(b)) : (v & ~bit_mask(b)))
 
//
// Funktsioonid bitimaskidega tegelemiseks
//
#define bitmask_set(value, bitMask)     value |= (bitMask)
#define bitmask_clear(value, bitMask)   value &= ~(bitMask)
#define bitmask_invert(value, bitMask)  value ^= (bitMask)
#define bitmask_set_to(v, m, x)         v = ((x) ? (v | (m)) : (v & ~(m))) 
#define bitmask_is_set(value, bitMask)  ((value) & (bitMask))

Sisend-väljundviigud

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 makrofunktsiooniga 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.

Andmetüübid

  • pin
    Viigu registrite ja bitimaski hoidmise struktuurne andmetüüp. pin-tüüpi muutujad on konstantsed ja need tuleb väärtustada kohe programmi alguses. Väärtustamise lihtsustamiseks on makrofunktsioon PIN, mille esimene parameeter on siini tähis (suur ladina täht A, B, C, jne) ja teine viigu number (0-7).

Funktsioonid

  • void pin_setup_output(pin pin)
    Viigu väljundiks määramine. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_setup_input(pin pin)
    Viigu sisendiks määramine ilma pull-up takistita. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_setup_input_with_pullup(pin pin)
    Viigu sisendiks määramine koos pull-up-takistiga. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_set(pin pin)
    Viigu väljundi kõrgeks määramine. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_clear(pin pin)
    Viigu väljundi madalaks määramine. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_toggle(pin pin)
    Viigu väljundi oleku pööramine. Madal olek muutub kõrgeks ja vastupidi. Parameetrid:
    • pin - Viigu muutuja.
  • void pin_set_to(pin pin, bool value)
    Viigu väljundi parameetriga määratud olekusse viimine. Parameetrid:
    • pin - Viigu muutuja.
    • value - Tõeväärtuse muutuja.
  • bool pin_get_value(pin pin)
    Viigu sisendi oleku lugemine ja funktsiooniga tagastamine. Parameetrid:
    • pin - Viigu muutuja.
    • Tagastab tõeväärtuse.
  • bool pin_get_debounced_value(pin pin)
    Viigu sisendi oleku lugemine läbi lüliti väreluse filtri ja selle tagastamine. Filtreerimine toimub minimaalselt 8 ms ja maksimaalselt 100 ms jooksul - olenevalt sellest, kui kiiresti lüliti värelemine lõppeb. Kui värelemine 100 ms jooksul ei lõpe, siis funktsioon tagastab false. Funktsioon kasutab tarkvaralist pausi funktsiooni viite teegist. Parameetrid:
    • pin - Viigu muutuja.
    • Tagastab tõeväärtuse.

Näide

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-digitaalmuundur

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.

Andmetüübid

  • adc_reference
    Analoog-digitaalmuunduri võrdluspinge valiku tüüp. Väärtuste variandid ja tähendused:
    • ADC_REF_AREF - Võrdluspinge saadakse AREF viigult.
    • ADC_REF_AVCC - Võrdluspinge saadakse AVCC viigult.
    • ADC_REF_2V56 - Võrdluspinge on sisemine 2,56 V.
  • adc_prescale
    Analoog-digitaalmuunduri taktijaguri valiku tüüp. Väärtuste variandid:
    • ADC_PRESCALE_2 - Jagamistegur 2.
    • ADC_PRESCALE_4 - Jagamistegur 4.
    • ADC_PRESCALE_8 - Jagamistegur 8.
    • ADC_PRESCALE_16 - Jagamistegur 16.
    • ADC_PRESCALE_32 - Jagamistegur 32.
    • ADC_PRESCALE_64 - Jagamistegur 64.
    • ADC_PRESCALE_128 - Jagamistegur 128.

Funktsioonid

  • void adc_init(adc_reference reference, adc_prescale prescale)
    ADC tööks ettevalmistamine. Parameetrid:
    • reference - Võrdluspinge valik.
    • prescale - Taktijaguri valik. Mida suurem on jaguri tegur, seda rohkem võtab muundamine aega, kuid seda mürakindlam see on.
  • unsigned short adc_get_value(unsigned char channel)
    Soovitud ADC sisendkanali väärtuse muundamine. Funktsioon on blokeeruv. Parameetrid:
    • channel - ADC kanali number (0 kuni 7).
    • Tagastab 10-bitise väärtuse.
  • unsigned short adc_get_average_value(unsigned char channel, unsigned char num_samples)
    Soovitud ADC sisendkanali väärtuse mitmekordne muundamine ja keskmise võtmine. Funktsioon on blokeeruv. Parameetrid:
    • channel - ADC kanali number (0 kuni 7).
    • num_samples - Keskmistamiste arv. Lubatud arv on 1 kuni 64.
    • Tagastab 10-bitise keskmistatud väärtuse.

 

Näide

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);
}

Jadaliides

Tegu on AVR universaalse jadaliidese kasutamise teegiga. Võimaldab asünkroonset andmete kirjutamist ja lugemist.

Andmetüübid

  • usart
    USART liidese registrite hoidmise andmetüüp. usart-tüüpi muutuja on konstantne ja see tuleb väärtustada kohe programmi alguses. Väärtustamise lihtsustamiseks on makrofunktsioon USART, mille parameetriks on liidese indeks (0 või 1).
  • adc_usart_databits
    Andmebittide arvu valiku tüüp. Väärtuste variandid:
    • USART_DATABITS_5 - Andmebitte 5.
    • USART_DATABITS_6 - Andmebitte 6.
    • USART_DATABITS_7 - Andmebitte 7.
    • USART_DATABITS_8 - Andmebitte 8.
    • USART_DATABITS_9 - Andmebitte 9.
  • usart_stopbits
    Stoppbittide arvu valiku tüüp. Väärtuste variandid:
    • USART_STOPBITS_ONE - Üks stoppbitt.
    • USART_STOPBITS_TWO - Kaks stoppbitti.
  • usart_parity
    Paarsuskontrolli valiku tüüp. Väärtuste variandid:
    • USART_PARITY_NONE - Paarsuskontrolli ja -bitti ei kasutata.
    • USART_PARITY_EVEN - Ühtede paarisarvulisuse kontroll.
    • USART_PARITY_ODD - Ühtede paarituarvulisuse kontroll.

Funktsioonid

  • USART_BAUDRATE_ASYNC(baud)

Makrofunktsiooni USART mooduli asünkroonse režiimi boodikiiruse registri väärtuse arvutamiseks. Parameetrid:

  • baud - Boodikiirus.
  • Tagastab boodikiiruse registri väärtuse.
  • void usart_init_async(usart port, usart_databits data_bits, usart_stopbits stop_bits, usart_parity parity, usart_baudrate baudrate)

Jadaliidese asünkroonseks seadistamine. Parameetrid:

  • port - USART liidese muutuja.
  • data_bits - Andmebittide arv.
  • stop_bits - Stoppbittide arv.
  • parity - Paarsuse tüüp.
  • baudrate - Boodi kiirus, mis on arvutatud USART_BAUDRATE_ASYNC makro funktsiooniga.

 

  • void usart_send_char(usart port, char symbol)

Blokeeruv sümboli saatmise funktsioon. Funktsioon ootab, kuni saatmise puhver tühjeneb ja kirjutab sinna saatmiseks uue sümboli. Parameetrid:

  • port - USART liidese muutuja.
  • symbol - Saadetav sümbol.
  • void usart_send_string(usart port, char *text)

Blokeeruv teksti saatmise funktsioon. Parameetrid:

  • port - USART liidese muutuja.
  • text - Viit tekstile. Tekst peab lõppema binaarse 0 sümboliga.
  • bool usart_has_data(usart port)

Sisendpuhvris andmete olemasolu kontroll. Parameetrid:

  • port - USART liidese muutuja.
  • Tagastab true, kui sisendpuhvris on sümbol ja false kui mitte.
  • char usart_read_char(usart port)

Sisendpuhvrist sümboli lugemine. Enne lugemist peab veenduma, et puhvris on sümbol. Parameetrid:

  • port - USART liidese muutuja.
  • Tagastab sümboli.
  • bool usart_try_read_char(usart port, char *symbol)

Sisendpuhvri sümboli olemasolu kontroll ja selle lugemise ühisfunktsioon. Parameetrid:

  • port - USART liidese muutuja.
  • symbol - Viit sümbolile. Kui sisendpuhvris on sümbol, siis see kirjutatakse siia.
  • Tagastab true, kui sisendpuhvris oli sümbol ja false kui mitte.

Näide

Jadaliidese seadmistamine töötab asünkroonselt 8 andmebiti, ühe stoppbiti ja ilma paarsuse kontrollita boodikiirusel 9600. Programm saadab teksti ja loeb sissetuleva sümboli.

#include <homelab/usart.h>
 
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);
}

Taimerid

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.

Andmetüübid

  • timer0_prescale
    Taimer 0 taktijaguri tegurite valiku tüüp. Väärtuste variandid ja tähendused:
    • TIMER0_NO_PRESCALE - Jagurit ei kasutata.
    • TIMER0_PRESCALE_8 - Jagamistegur 8.
    • TIMER0_PRESCALE_32 - Jagamistegur 32.
    • TIMER0_PRESCALE_64 - Jagamistegur 64.
    • TIMER0_PRESCALE_128 - Jagamistegur 128.
    • TIMER0_PRESCALE_256 - Jagamistegur 256.
    • TIMER0_PRESCALE_1024 - Jagamistegur 1024.
  • timer2_prescale
    Taimer 2 taktijaguri tegurite valiku tüüp. Väärtuste variandid ja tähendused:
    • TIMER2_NO_PRESCALE - Jagurit ei kasutata.
    • TIMER2_PRESCALE_8 - Jagamistegur 8.
    • TIMER2_PRESCALE_64 - Jagamistegur 64.
    • TIMER2_PRESCALE_256 - Jagamistegur 256.
    • TIMER2_PRESCALE_1024 - Jagamistegur 1024.
    • TIMER2_PRESCALE_T2_FALLING - Taktsignaal tuleb hoopis T2 viigu langeval frondil.
    • TIMER2_PRESCALE_T2_RISING - Taktsignaal tuleb hoopis T2 viigu tõusval frondil.
  • timer1_prescale
  • timer3_prescale
    Taimer 1/3 taktijaguri tegurite valiku tüüp. Väärtuste variandid ja tähendused (“n” tähistab 1 või 3):
    • TIMERn_NO_PRESCALE - Jagurit ei kasutata.
    • TIMERn_PRESCALE_8 - Jagamistegur 8.
    • TIMERn_PRESCALE_64 - Jagamistegur 64.
    • TIMERn_PRESCALE_256 - Jagamistegur 256.
    • TIMERn_PRESCALE_1024 - Jagamistegur 1024.
    • TIMERn_PRESCALE_Tn_FALLING - Taktsignaal tuleb hoopis Tn viigu langeval frondil.
    • TIMERn_PRESCALE_Tn_RISING - Taktsignaal tuleb hoopis Tn viigu tõusval frondil.

 

  • timer1_ctc_top
  • timer3_ctc_top
    Taimer 1/3 CTC-režiimi maksimaalse loenduri väärtuse valiku tüüp. Väärtuste variandid ja tähendused (“n” tähistab 1 või 3):
    • TIMERn_CTC_TOP_OCRA - Maksimaalne väärtus määratakse taimer 1/3 võrdlusregistriga A.
    • TIMERn_CTC_TOP_ICR - Maksimaalne väärtus määratakse taimer 1/3 sündmuste loenduri registriga.
  • timer1_fast_pwm_top
  • timer3_fast_pwm_top
    Taimer 1/3 kiire PWM režiimi maksimaalse loenduri väärtuse valiku tüüp. Väärtuste variandid ja tähendused (“n” tähistab 1 või 3):
    • TIMERn_FAST_PWM_TOP_256 - Maksimaalne väärtus on 255.
    • TIMERn_FAST_PWM_TOP_512 - Maksimaalne väärtus on 511.
    • TIMERn_FAST_PWM_TOP_1024 - Maksimaalne väärtus on 1023.
    • TIMERn_FAST_PWM_TOP_ICR - Maksimaalne väärtus määratakse taimer 1/3 sündmuste loenduri registriga.
    • TIMERn_PAST_PWM_TOP_OCRA - Maksimaalne väärtus määratakse taimer 1/3 võrdlusregistriga A.
  • timer1_fast_pwm_output_mode
  • timer1_fast_pwm_output_mode
    Taimer 1/3 väljundite seadistuste valiku tüüp kiire PWM režiimis. Väärtuste variandid ja tähendused (“n” tähistab 1 või 3):
    • TIMERn_FAST_PWM_OUTPUT_DISABLE - Väljundisse PWM signaal ei jõua.
    • TIMERn_FAST_PWM_OUTPUT_TOGGLE_ON_MATCH - Väljund muutub vastupidiseks, kui loendur omistab võrdlusregistri väärtuse.
    • TIMERn_FAST_PWM_OUTPUT_CLEAR_ON_MATCH - Väljund läheb madalaks, kui loendur omistab võrdlusregistri väärtuse, ja kõrgeks, kui loendur jõuab nulli.
    • TIMERn_FAST_PWM_OUTPUT_SET_ON_MATCH - Väljund läheb kõrgeks, kui loendur omistab võrdlusregistri väärtuse, ja madalaks, kui loendur jõuab nulli.

Funktsioonid

  • void timer0_init_normal(timer0_prescale prescale)
    Taimer 0 normaalrežiimi seadistamine. Selles režiimis loendab taimer 255-ni (kaasa arvatud) ja ainuke tekkiv sündmus on ületäitumine. Parameetrid:
    • prescale - Taktijaguri tegur.
  • void timer2_init_normal(timer2_prescale prescale)
    Taimer 2 normaalrežiimi seadistamine. Selles režiimis loendab taimer 255-ni (kaasa arvatud) ja ainuke tekkiv sündmus on ületäitumine. Kaks taktijaguri tegurit võimaldavad taimeri taktsignaali allikaks seada ka T2 viigu. Parameetrid:
    • prescale - Taktijaguri tegur või taktsignaali allikas.
  • void timer0_stop()
  • void timer2_stop()
    Taimeri 0/2 peatamine.
  • unsigned char timer0_get_value(void)
  • unsigned char timer2_get_value(void)
    Taimer 0/2 loenduri hetkeväärtuse tagastamine. Parameetrid:
    • Tagastab 8-bitise loenduri hetkeväärtuse.
  • void timer0_set_value(unsigned char value)
  • void timer2_set_value(unsigned char value)
    Taimer 0/2 loenduri uue väärtuse määramine. Parameetrid:
    • value - Uus 8-bitine loenduri väärtus.
  • void timer0_overflow_interrupt_enable(bool enable)
  • void timer2_overflow_interrupt_enable(bool enable)
    Taimer 0/2 ületäitumise katkestuse lubamine või keelamine. Katkestuse vektor on TIMERn_OVF_vect kus “n” on 0 või 2. Parameetrid:
    • enable - Tõeväärtus katkestuse lubamiseks või keelamiseks. true lubab, false keelab.
  • bool timer0_overflow_flag_is_set(void)
  • bool timer2_overflow_flag_is_set(void)
    Taimer 0/2 ületäitumise toimumise kontrollimine. Parameetrid:
    • Tagastab tõeväärtuse true, kui ületäitumine on toimunud, ja false, kui pole.
  • void timer0_overflow_flag_clear(void)
  • void timer2_overflow_flag_clear(void)
    Taimer 0/2 ületäitumise sündmuse lipukese nullimine.
  • void timer1_init_normal(timer1_prescale prescale)
  • void timer3_init_normal(timer3_prescale prescale)
    Taimer 1/3 normaalrežiimi seadistamine. Selles režiimis loendab taimer 65535-ni (kaasa arvatud) ja ainuke tekkiv sündmus on ületäitumine. Parameetrid:
    • prescale - Taktijaguri tegur.
  • void timer1_init_ctc(timer1_prescale prescale, timer1_ctc_top top)
  • void timer3_init_ctc(timer3_prescale prescale, timer3_ctc_top top)
    Taimer 1/3 CTC (inglise keeles Clear Timer on Compare Match) režiimi seadistamine. Selles režiimis taimer ei loenda mitte 65535-ni, vaid valitud registri väärtuseni ja tekitab soovi korral sinnani jõudes katkestuse. Parameetrid:
    • prescale - Taktijaguri tegur.
    • top - Taimeri maksimaalse väärtuse registri valik. Valida saab kahe registri vahel, mille mõlema muutmiseks on omaette funktsioonid. Mõlemad registrid võib loenduri tippu jõudes katkestust tekitama seadistada.
  • void timer1_init_fast_pwm(timer1_prescale prescale, timer1_fast_pwm_top top, timer1_fast_pwm_output_mode output_a, timer1_fast_pwm_output_mode output_b, timer1_fast_pwm_output_mode output_c)
  • void timer3_init_fast_pwm(timer3_prescale prescale, timer3_fast_pwm_top top, timer3_fast_pwm_output_mode output_a, timer3_fast_pwm_output_mode output_b, timer3_fast_pwm_output_mode output_c)
    Taimer 1/3 kiire PWM tekitamise režiimi seadistamine. Selles režiimis on valitav väärtus, milleni taimer loendab, ehk PWM signaali periood. Taimeril on 3 PWM signaali genereerimise üksust (A, B ja C), millel kõigil on seadistatav väljund. Parameetrid:
    • prescale - Taktijaguri tegur.
    • top - Taimeri maksimaalse väärtuse valik. Valida saab konstantide ja kahe registri vahel. Mõlemad registrid võib loenduri tippu jõudes katkestust tekitama seadistada.
    • output_a - Väljundviigu A seadistus.
    • output_b - Väljundviigu B seadistus.
    • output_c - Väljundviigu C seadistus.
  • void timer1_stop()
  • void timer3_stop()
    Taimeri 1/3 peatamine.
  • unsigned char timer1_get_value(void)
  • unsigned char timer3_get_value(void)
    Taimeri 1/3 loenduri hetkeväärtuse tagastamine. Parameetrid:
    • Tagastab 16-bitise loenduri hetkeväärtuse.
  • void timer1_set_value(unsigned char value)
  • void timer3_set_value(unsigned char value)
    Taimeri 1/3 loenduri uue väärtuse määramine. Parameetrid:
    • value - Uus 16-bitine loenduri väärtus.
  • unsigned short timer1_get_compare_match_unitA_value(void)
  • unsigned short timer1_get_compare_match_unitB_value(void)
  • unsigned short timer1_get_compare_match_unitC_value(void)
  • unsigned short timer3_get_compare_match_unitA_value(void)
  • unsigned short timer3_get_compare_match_unitB_value(void)
  • unsigned short timer3_get_compare_match_unitC_value(void)
    Taimeri 1/3 signaali genereerimise üksuse A/B/C võrdlusväärtuse tagastamine. Parameetrid:
    • Tagastab 16-bitise üksuse võrdlusregistri väärtuse.
  • void timer1_set_compare_match_unitA_value(unsigned short value)
  • void timer1_set_compare_match_unitB_value(unsigned short value)
  • void timer1_set_compare_match_unitC_value(unsigned short value)
  • void timer3_set_compare_match_unitA_value(unsigned short value)
  • void timer3_set_compare_match_unitB_value(unsigned short value)
  • void timer3_set_compare_match_unitC_value(unsigned short value)
    Taimeri 1/3 signaali genereerimise üksuse A/B/C võrdlusväärtuse määramine. Parameetrid:
    • value - Uus 16-bitine võrdlusväärtus.
  • unsigned short timer1_get_input_capture_value(void)
  • unsigned short timer3_get_input_capture_value(void)
    Taimer 1/3 sündmuste loenduri väärtuse tagastamine. Parameetrid:
    • Tagastab 16-bitise sündmuste loenduri registri väärtuse.
  • void timer1_set_input_capture_value(unsigned short value)
  • void timer3_set_input_capture_value(unsigned short value)
    Taimer 1/3 sündmuste loenduri registri väärtuse määramine. Parameetrid:
    • value - Uus 16-bitine sündmuste loenduri väärtus.
  • void timer1_overflow_interrupt_enable(bool enable)
  • void timer3_overflow_interrupt_enable(bool enable)
    Taimer 1/3 ületäitumise katkestuse lubamine või keelamine. Katkestuse vektor on TIMERn_OVF_vect, kus “n” on 1 või 3. Parameetrid:
    • enable - Tõeväärtus katkestuse lubamiseks või keelamiseks. true lubab, false keelab.
  • void timer1_compare_match_unitA_interrupt_enable(bool enable)
  • void timer1_compare_match_unitB_interrupt_enable(bool enable)
  • void timer1_compare_match_unitC_interrupt_enable(bool enable)
  • void timer3_compare_match_unitA_interrupt_enable(bool enable)
  • void timer3_compare_match_unitB_interrupt_enable(bool enable)
  • void timer3_compare_match_unitC_interrupt_enable(bool enable)
    Taimer 1/3 signaali genereerimise üksuse A/B/C võrdluse sündmuse katkestuse lubamine või keelamine. Katkestuse vektor on TIMERn_COMPx_vect, kus on “n” on 1 või 3 ja “x” on A, B või C. Parameetrid:
    • enable - Tõeväärtus katkestuse lubamiseks või keelamiseks. true lubab, false keelab.
  • void timer1_input_capture_interrupt_enable(bool enable)
  • void timer3_input_capture_interrupt_enable(bool enable)
    Taimer 1/3 sündmuste loenduri katkestuse lubamine või keelamine. Katkestuse vektor on TIMERn_CAPT_vect, kus “n” on 1 või 3. Parameetrid:
    • enable - Tõeväärtus katkestuse lubamiseks või keelamiseks. true lubab, false keelab.
  • bool timer1_overflow_flag_is_set(void)
  • bool timer3_overflow_flag_is_set(void)
    Taimeri 1/3 ületäitumise toimumise kontrollimine. Parameetrid:
    • Tagastab tõeväärtuse true, kui ületäitumine on toimunud, ja false, kui pole.
  • bool timer1_input_capture_flag_is_set(void)
  • bool timer3_input_capture_flag_is_set(void)
    Taimer 1/3 sündmuste loenduri lipukese kontrollimine. Parameetrid:
    • Tagastab tõeväärtuse true, kui sündmus on toimunud, ja false, kui pole.
  • void timer1_overflow_flag_clear(void)
  • void timer3_overflow_flag_clear(void)
    Taimeri 1/3 ületäitumise sündmuse lipukese nullimine.
  • void timer1_input_capture_flag_clear(void)
  • void timer3_input_capture_flag_clear(void)
    Taimer 1/3 sündmuste loenduri lipukese nullimine.

Näide

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 katkestuste lubamine
	sei();
}

Viide

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.

Funktsioonid

  • void sw_delay_ms(unsigned short count)
    Tarkvaraline viide millisekundites. Funktsiooni kasutamine eeldab kompilaatorilt optimeerimise kasutust. Parameetrid:
    • count - Viite aeg millisekundites. 0 kuni 65535 millisekundit.
  • void sw_delay_us(unsigned short count)
    Tarkvaraline viide mikrosekundites. Funktsiooni kasutamine eeldab kompilaatorilt optimeerimise kasutust. Parameetrid:
    • count - Viite aeg mikrosekundites. 0 kuni 65535 mikrosekundit.
  • void hw_delay_ms(unsigned short count)
    Riistvaraline taimeril põhinev viide millisekundites. Funktsioon kasutab ATmega128 8-bitist taimerit 0. Olenevalt taktsagedusest võib tekkida kuni mõne millisekundi suurune viga. Täpsema viite saaks teha 16-bitiste taimeritega, kuid neid on tavaliselt muuks otstarbeks vaja. Parameetrid:
    • count - Viite aeg millisekundites. 0 kuni 65535 millisekundit.

Näide

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);
}

7-segmendiline LED indikaator

Seotud mooduliga: [HW] Kasutajaliidese moodul

See teek on spetsiaalselt loodud Kodulabori Digitaalse sisend-väljundmooduli plaadil asuva indikaatori kasutamiseks. 7-segmendilise indikaatoriga saab kuvada numbreid 0 kuni 9 ja mõningaid tähti.

Funktsioonid

  • void segment_display_init(void)

Indikaatori juhtviikude seadmistamine väljundiks.

  • void segment_display_write(unsigned char digit)

Soovitud numbri kuvamine indikaatoriga. Parameetrid:

  • digit - Number 0 kuni 9. Muude väärtuste puhul kuvatakse E nagu error (viga).

Näide

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);
}

Alfabeetiline LCD

Seotud mooduliga: [HW] LCD moodul

See teegi osa sisaldab Kodulabori alfabeetilise LCD kasutamise funktsioone.

Andmetüübid

  • lcd_alpha_mode
    Ekraani algseadistuse valiku tüüp. Väärtuste variandid ja tähendused:
    • LCD_ALPHA_DISP_OFF - Ekraani väljalülitamine.
    • LCD_ALPHA_DISP_ON - Ekraani tööle lülitamine ilma kursorita (nähtamatu kursor).
    • LCD_ALPHA_DISP_ON_CURSOR - Ekraani tööle lülitamine koos kursoriga.
    • LCD_ALPHA_DISP_ON_CURSOR_BLINK - Ekraani tööle lülitamine koos vilkuva kursoriga.

Funktsioonid

  • void lcd_alpha_init(lcd_alpha_mode disp_attr)
    Ekraani tööks seadistamine. Parameetrid:
    • disp_attr - Ekraani seadistuse valik.
  • void lcd_alpha_clear(void)
    Ekraani tühjendamine kõigist märkidest. Kursor viiakse pärast tühjendamist esimese rea algusesse.
  • void lcd_alpha_clear_line(unsigned char line)
    Ekraani ühe rea tühjendamine. Kursor viiakse pärast tühjendamist tühjendatud rea algusesse. Parameetrid:
    • line - Rea number. Väärtus 0 või 1.
  • void lcd_alpha_home(void)
    Kursori esimese rea algusesse viimine.
  • void lcd_alpha_goto_xy(unsigned char x, unsigned char y) - Kursori soovitud positsioonile viimine. Parameetrid:
    • x - X koordinaat (veeru number). Väärtus 0 kuni 15.
    • y - Y koordinaat (rea number). Väärtus 0 või 1.
  • void lcd_alpha_write_char(char c)
    Sümboli kuvamine ekraani kursori positsioonil. Parameetrid:
    • c - ASCII sümbol.
  • void lcd_alpha_write_string(const char *s)
    Teksti kuvamine ekraanil kursori positsioonist alates. Parameetrid:
    • s - Teksti viit.
  • void lcd_alpha_write_string_p(const char *progmem_s)
    Programmimälus asuva teksti kuvamine ekraanil kursori positsioonist alates. Parameetrid:
    • progmem_s - Viit tekstile programmimälus.

Näide

#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");
}

Graafiline LCD

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.

Funktsioonid

  • void lcd_gfx_init(void)
    Ekraani tööks seadistamine.
  • void lcd_gfx_backlight(bool set)
    Ekraani taustvalgustuse lülitamine. Parameetrid:
    • set - Tõeväärtus taustvalgustuse töötamisest. true puhul taustvalgustus on sees, false puhul väljas.
  • void lcd_gfx_clear(void)
    Kogu ekraani tühjendamine.
  • void lcd_gfx_clear_line(unsigned char line)
    Ekraani ühe tekstirea kustutamine. Parameetrid:
    • line - Rea number 0 kuni 5.
  • void lcd_gfx_goto_char_xy(unsigned char x, unsigned char y) - Märgi positsiooni valik teksti väljastamiseks. Parameetrid:
    • x - X koordinaat. Väärtus 0 kuni 13.
    • y - Y koordinaat. Väärtus 0 kuni 5.
  • void lcd_gfx_write_char(char c)
    Sümboli kuvamine ekraanil eelnevalt määratud positsioonil. Parameetrid:
    • c - ASCII sümbol.
  • void lcd_gfx_write_string(char *s)
    Teksti kuvamine ekraanil eelnevalt määratud positsioonist alates. Parameetrid:
    • s - Teksti viit.

Näide

#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");
}

Mootorid

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.

Funktsioonid

  • void dcmotor_init(unsigned char index)

Ühe alalisvoolu mootorikontrolleri juhtviikude seadistamine väljundiks. Parameetrid:

  • index - Mootorikontrolleri number. Väärtus 0 kuni 3.
  • void dcmotor_drive(unsigned char index, signed char direction)

Alalisvoolu mootorikontrolleri juhtkäsk. Parameetrid:

  • index - Mootorikontrolleri number. Väärtus 0 kuni 3.
  • direction - Mootori polaarsus. Väärtus -1, 0 või +1. 0 puhul mootor seisab, muul juhul pöörleb vastavas suunas.
  • void bipolar_init(void)

Bipolaarse mootorikontrolleri juhtviikude seadistamine väljundiks.

  • void bipolar_halfstep(signed char direction, unsigned short num_steps, unsigned char speed)

Bipolaarse samm-mootori mootorikontrolleri poolsammumise juhtkäsk. Funktsioon on blokeeruv ehk seda täidetakse seni, kuni soovitud arv samme on tehtud. Parameetrid:

  • direction - Pöörlemissuund. Väärtus -1 või +1.
  • num_steps - Poolsammude arv.
  • speed - Ühe sammu tegemise aeg millisekundites.
  • void servomotor_init(unsigned char index)

Ühe servomootori juhtviikude väljundiks seadistamine ja taimer 1 seadistamine PWM režiimi. Parameetrid:

  • index - Servomootori number. Väärtus 0 või 1.
  • void servomotor_position(unsigned char index, signed short position)

Servomootori juhtkäsk. Kui juhitakse positsioneerivat servomootorit, siis muutub rootori asend, kui lõputult pöörlevat, siis muutub pöörlemise kiirus. Parameetrid:

  • index - Servomootori number. Väärtus 0 või 1.
  • position - Rootori asend või pöörlemiskiirus (olenevalt mootorist). Väärtus -100 kuni +100. 0 on keskasend või peatumine.

 

Näide

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);
}

Andurid

Seotud mooduliga: [HW] Andurite moodul

See teegi osa sisaldab Kodulabori andurite kasutamise funktsioone.

Andmetüübid

  • ir_distance_sensor
    Infrapuna-kaugusanduri kauguse arvutuse funktsiooni parameetrite struktuur. Kauguse arvutusvalem on a / (ADC + b) - k. Struktuuri liikmed:
    • a - jagatav.
    • b - vabaliige.
    • k - korrigeerimiskonstant.

Konstandid

  • ir_distance_sensor GP2Y0A21YK - Sharp GP2Y0A21YK kaugusanduri parameetrite struktuuri objekt.

Funktsioonid

  • signed short thermistor_calculate_celsius(unsigned short adc_value)

Termistori temperatuuri arvutamine Celsiuse kraadides ADC muunduri väärtusest. Funktsioon põhineb teisendustabelil. Parameetrid:

  • adc_value - ADC teisenduse väärtus.
  • Tagastab temperatuuri Celsiuse kraadides -20 kuni 100 kraadi piires.
  • signed short ir_distance_calculate_cm(ir_distance_sensor sensor, unsigned short adc_value)

IR kaugusanduri väljundpinge ADC väärtuse sentimeetriteks ümberarvutamise funktsioon. Parameetrid:

  • sensor - Kaugusanduri parameetrite struktuuri objekt.
  • adc_value - 10-bitine +5 V võrdluspingega ADC väärtus.
  • Tagastab kauguse sentimeetrites või -1, kui seda ei saanud arvutada.
  • unsigned short ultrasonic_measure(pin trigger, pin echo)

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:

  • trigger - päästiku viigu muutuja.
  • echo - kaja viigu muutuja.
  • Tagastab kauguse sentimeetrites või 0, kui mõõtmine ebaõnnestus.

 

Näide

#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

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:

  • [HW] Näites kasutatud riistvara moodul
  • [LIB] Näites kasutatud tarkvara teegi osa
  • [ELC] Viide elektroonika baasteadmiste peatükile
  • [AVR] Viide AVR mikrokontrolleri mooduli peatükile
  • [PRT] Viide teisele harjutusele

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 ühtses stiilis, et programmikood oleks ülevaatlikum. Ühtne stiil teeb programmi loetavaks ja välistab kergemate süntaksivigade tekkimise. Kindlat stiili on soovitatav järgida ka harjutusülesannete tegemisel. Stiili peamised iseloomustajad:

  • Programm, selle funktsioonid ja muutujad on ingliskeelsed ning väiketähtedega, kus sõnu eraldab alakriips.
  • Funktsioonid on kujul objekt_tegevus_subjekt.
  • Olulisemad kohad programmis on kommenteeritud eesti keeles.
  • Iga C-keele plokk (tähistatud loogeliste sulgudega { ja } ) algab ja lõpeb eraldi real.
  • Plokid on tabuleeritud tabulaatorklahviga. Reasiseselt tabulaatorit ei kasutata.

Alustamine

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. Järgnevad peatükid tutvustavadki mõlema keskkonna seadistamist.

Kogu vajaliku installeeritava tarkvara harjutuste läbimiseks leiab Kodulabori veebilehelt.

Tarkvara Windowsi keskkonnas

Järgnev juhend kirjeldab AVR arenduskeskkonna installeerimist ja kasutamist Windowsi operatsioonisüsteemis.

Tarkvara paigaldamine

Enne paigaldamist tuleks hankida alljärgnev tarkvara, kas tootja või Kodulabori kodulehelt või Kodulabori kohvriga kaasas olevalt plaadilt.

1. AVR Studio

AVR Studio 4 on IDE (inglise keeles Integrated Development Environment), milles toimub tarkvara kirjutamine ja mikrokontrollerisse laadimine. Uusima AVR Studio versiooni 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 lisaks nimele versiooni numbrit, kuid kataloog tuleks käsitsi muuta lihtsalt:

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 ühendamist arvutiga. Paigaldusprogrammi 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.

Uue pordi leidmise teade

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 protseduuri veebilehelt.

Projekti loomine

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 konkreetset vajadust teiste meetodite 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.

 

Seadistuste testimine

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 kontrolleri toide (kontrollerplaadil 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);
	}
}
Kompileerimise ja programmaatori nupud

Kompileerida programm käsuga Build (kiirklahv F7) ja kontrollida, et kompileerimine õnnestus. 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

Programmi mõjul peaks kontrolleri plaadil olev oleku-LED PB7 perioodiliselt süttima ja kustuma. Kui programm töötab, on tarkvara paigaldatud edukalt ja esimene projekt tehtud. Palju õnne!

Siluri kasutamine

ATmega128 registrite loetelu siluris

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 peab olema silumist toetav riistvara - JTAG programmaator. Odavamad programmaatorid, mis kasutavad ISP programmeerimise liidest, võimaldavad laadida kontrollerisse 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).

Ujukoma-arvude kasutamine

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.

Tarkvara Linuxi keskkonnas

Järgnev juhend kirjeldab AVR arenduskeskkonna installeerimist ja kasutamist Ubuntu 9.10 operatsioonisüsteemis.

Tarkvara paigaldamine

Installeerida järgnev tarkvara:

1. Linuxi tarkvarapaketid

  • gcc-avr – GNU C-keele kompilaator AVR platvormile
  • avrdude – programm hex-faili laadimiseks mikrokontrollerisse
  • avr-libc – C-keele teegid koodi kirjutamiseks AVR platvormile

Installeerimiseks kasutada terminali käsurida:

sudo apt-get install gcc-avr avrdude avr-libc

või graafilist paketihaldustarkvara (näiteks 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 paigaldamine õnnestus.

3. KontrollerLab

KontrollerLab on IDE (inglise keeles integrated development environment) ehk integreeritud arenduskeskkond tarkvara kirjutamiseks, kompileerimiseks, pealelaadimiseks jms. Salvestada KontrollerLab tarkvarapakett kausta (näiteks ~/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 paigaldab puuduvad paketid:

sudo apt-get install –f

Programmaatori ühendamine

Ü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.

 

Projekti loomine

AVR programmi kirjutamiseks tuleb luua uus projekt, mis tüüpiliselt sisaldab endas mitmeid 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 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 hetkeseadistused 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äljundfailide 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 määrata kompilaatori seaded, nagu näidatud juuresoleval pildil. Enne OK vajutamist määrata siin sisestatud parameetrid vaikimisi seadeteks.

4. Määrata programmaatori seaded, 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 vastavad parameetrid vaikimisi seadeteks.

 

5. Määrata tekstiredaktori seaded 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. Järgnevas alampeatükis on näitena toodud vilkuva LED programm.

 

Seadistuste testimine

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 Kontrollerimooduli plaadiga. Kontrollida, et programmaator saab ühendatud õigesse pistikusse (JTAG) ja õigetpidi (kaabel on suunatud kontrolleri plaadist eemale - vaata järgmist pilti). Pärast programmaatori ühendamist ühendada kontrolleri toide (kontrollerplaadil peab süttima väike roheline oleku-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);
	}
}
Tööriistariba

Veendu, et väljundaknasse tuleb teade “File compiled successfully”. Kui annab teate “Error(s) occurred: ”, siis kontrollida, et koodi sisestamisel ei ole tehtud mõnda 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 oleku-LED hakkaks perioodiliselt vilkuma (500 ms põleb, 500 ms on kustund).

Kui LED vilgub, nii nagu eespool kirjeldatud, on tarkvara paigaldatud edukalt ja esimene labor läbitud. Palju õnne!

Ujukoma-arvude kasutamine

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 (vaata ka juuresolevat pilti).

2. Vajutada OK ja sulgeda seadete aken.

Digitaalsed sisend-väljundviigud

Digitaalsed sisendid/väljundid

Järgnevad peatükid tutvustavad lihtsaimat mikrokontrolleri funktsiooni - digitaalseid sisend-väljundviike. Viigud on mikrokontrolleri metallist kontaktid, kõnekeeles jalad, mille kaudu saab edastada ja vastu võtta digitaalseid signaale. Kui viik seadistada programmis sisendiks, saab selle kaudu mikrokontrollerisse 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 alternatiivfunktsioonid. Enne alternatiivfunktsioonidega tegelemist, tuleks aga lihtsamad funktsioonid endale selgeks teha.

Valgusdiood

Teooria

5 mm jalgadega valgusdiood

Valgusdiood on pooljuht, mille päripingestamisel kiirgab see valgust. Valgusdioodi nimetatakse inglise keelse lühendiga LED (light-emitting diode). On olemas erineva värvusega valgusdioode ja valgusdioodide 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.

Valgusdioodi skemaatiline tähis ja polaarsus

Päripingestamisel rakendatakse LED-i anoodile positiivne ja katoodile negatiivne pinge. LED-i 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 lihtsalt läbi põletada.

Kui LED-e kasutatakse spetsiaalselt valgustamiseks, on mõistlik kasutada spetsiifilisi 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 tuleb LED-iga järjestikku lisada takisti, mis piirab voolu ja tekitab vajaliku pingelangu. Takisti arvutusvalemid leiab elektroonika peatükist.

Jalgadega ja pindliides valgusdioodi viikude tähistus

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.

Praktika 1

Kodulabori Kontrollermooduli plaadil on üksik punane LED, mille anood on läbi takisti ühendatud +5 V toitega ja katood ATmega128 viiguga PB7. Selleks et Kontrollermooduli 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.

Peaaegu kõik Kodulabori praktilised näited, kaasa arvatud LED-i süütamise näide, kasutavad Kodulabori viikude teeki. Viikude teegis on andmetüüp pin, mis sisaldab viiguga seotud registrite aadresse ja viigu bitimaski. Kui programmi tekitada pin-tüüpi muutuja ja see kohe programmi alguses makrofunktsiooniga PIN 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 Kontrollermooduli LED-i testimise programm.
// Põhineb Kodulabori teegil.
//
#include <homelab/pin.h>
 
//
// LED-i 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 süütamine
	pin_clear(debug_led);	
}
//
// Kodulabori Kontrollermooduli LED-i testimise programm.
// Põhineb otsesel registrite muutmisel.
//
#include <avr/io.h>
 
//
// Põhiprogramm
//
int main(void)
{	
	// LED-i viigu väljundiks seadmine
	DDRB |= (1 << 7);	
 
	// LED-i süütamine
	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 funktsiooni pin_setup_output ja seejärel selle viigu madalaks määramine funktsiooniga pin_clear, mille tulemusena LED süttib. Teises näites muutujaid ei kasutata, LED-i 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 vaja anda LED-i põlema paneku käsku kummaski näites, kuna vaikimisi on AVR väljundite väärtus nagunii 0, kuid seda on siinkohal tehtud korrektsuse pärast.

Mis siis on viikude teegi ja registrite kasutamise vahe? Vahe on kasutusmugavuses - teegiga on see lihtsam, sest ei pea registrite nimesid ja nende toimet teadma. Kõige olulisem teegi eelis on aga kohandatavus. Registreid kasutades tuleb viigu muutmiseks kogu programmis registrite nimed ja bitimaskid ümber muuta, teegi puhul tuleb seda teha vaid programmi alguses, 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 pin-tüüpi üksikmuutujate kohta, mitte töö ajal muutuvate muutujate ja massiivide kohta.

Järgnevalt on osaliselt toodud viikude teegi lähtekood, mille eesmärk on selgitada teegis toimuvat. Paraku ei pruugi see algajale päris arusaadav olla kuna kasutusel on C-keele viidad (inglise keeles pointer), millest selle raamatu C-keele õpetuses kirjutatud pole. Viitade kohta kohta leiab huviline palju infomaterjali internetist ja programmeerimise õpikutest.

// Makro-konstant millega määratakse ära registri viit
#define _REG_PTR_ volatile uint8_t *
 
//
// Viigu andmetüüp
//
typedef struct pin
{
	_REG_PTR_ ddr;
	_REG_PTR_ port;
	_REG_PTR_ pin;
	uint8_t mask;
}
pin;
 
//
// Viigu andmetüüpi muutuja algväärtustamise makrofunktsioon
//
#define PIN(port_char, bit_index) \
{ \
	(_REG_PTR_)&DDR ## port_char, \
	(_REG_PTR_)&PORT ## port_char, \
	(_REG_PTR_)&PIN ## port_char, \
	bit_mask(bit_index) \
}
 
//
// Viigu seadmine väljundiks
//
inline void pin_setup_output(pin pin)
{
	bitmask_set(*pin.ddr, pin.mask);
}
 
//
// Viigu seadmine kõrgeks
//
inline void pin_set(pin pin)
{
	bitmask_set(*pin.port, pin.mask);
}
 
//
// Viigu seadmine madalaks
//
inline void pin_clear(pin pin)
{
	bitmask_clear(*pin.port, pin.mask);
}

Praktika 2

Peale Kontrollermooduli asuvad LED-id ka Digitaalsel sisend-väljundmooduli plaadil. Need on elektriliselt ühendatud samamoodi nagu Kontrollermooduli LED ehk katood on ühenduses AVR viiguga. Punane LED on ühenduses viiguga PC5, kollane viiguga PC4 ja roheline viiguga 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);	
 
	// Punase ja rohelise LED-i põlema panek
	pin_clear(led_red);
	pin_clear(led_green);
 
	// Kollase LED-i kustutamine
	pin_set(led_yellow);
}

Lüliti

Teooria

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 pöiallüliteid ning lüliteid, mis vajutades ei ühenda, vaid katkestavad elektriahela.

Erinevat liiki lülititel on erinev skemaatiline tähis. Järgnevalt on toodud tüüpilisemad elektroonikaskeemides kasutatavad lülitid ja nende elektrilised tähised:

Surunupp-lüliti Tumbler-lüliti Klahvlüliti Mikrolüliti DIL-lüliti

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 pöiallü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 (mida leidub kõikjal) 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 ühendada läbi takisti kas maa- või toitepotentsiaaliga. Sellises funktsioonis olevat takistit nimetatakse inglise keeles kas pull-down või pull-up takistiks. Tavaliselt ulatub pull-up või pull-down takistite takistus mõnest kilo-oomist ühe mega-oomini. Kui lüliti on avatud, jääb sisendile, millele on ühendatud takisti, pinge, kui lüliti sulgeda, rakendub sisendile lüliti pinge, sest lüliti takistus on palju väiksem (nullilähedane) kui takisti oma. Sisuliselt on tegu pingejaguriga.

Lüliti ühendusskeem pull-up takistiga

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 väärlülituse probleem praktiliselt ei mõjuta.

Praktika

Kodulabori Digitaalse sisend-väljundmooduli plaadil 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 0 V 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, viikudel juba on 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 plaadil olevaid 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 viigud 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-i, teine kollase ja kolmas punase.

Lüliti põrkumise filtreerimine

Vajalikud teadmised: [HW] Kasutajaliidese moodul, [AVR] Digitaalsed sisendid-väljundid, [LIB] Sisend-väljundviigud, [LIB] Viide, [PRT] Lüliti

Teooria

Lüliti kontaktide põrkumine

Nii nagu lüliteid tutvustavas peatükis öeldud, eksisteerib mehhaaniliste lülititega kontaktide põrkumise probleem. 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 käivitamiseks, siis pole see suur probleem, kuid kui lüliti on kasutusel seadme juhtimiseks, võib mitmekordne lülitumine probleemiks olla.

Lüliti RC-filter

Põhiline kontaktide põrkumisest tekkinud väärlülitusi välistav meetod on filtreerimine. Filtreerida saab nii elektriliselt kui ka tarkvaraliselt. Elektriliseks filtreerimiseks tuleb lüliti ühendada läbi madalpääsu filtri – näiteks RC filter - mis silub pingemuutusi ja sellest tulenevalt ei omanda mikrokontrolleri viik hetkelisi väärtusi. 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 põrkumisega. Igasugusel filtreerimisel peab aga arvestama viitega, mis tekib oleku määratlemisel.

Praktika

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-i. Väär-nupuvajutuste tõttu süttivad LED-id aga mitmeid kordi ja näib, et lausa suvaliselt.

//
// Kodulabori digitaalse sisend-väljundmooduli
// nuppude kontaktide 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 variandil on oma eelised ja puudused. 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 lisalü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äljundmooduli 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 kaheksa 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 kontaktide 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.

Harjutusülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Süütab nupu S1 vajutamisel ühe LED-i, S2 vajutamisel kaks LED-i, S3 vajutamisel kolm LED-i.

Algajale

  1. Imiteerib ülekäiguraja autode valgusfoori tööd. Kuni pole vajutatud ühelegi nupule, põleb autodele roheline LED. Pärast suvalisele nupule vajutamist hakkab roheline kolmeks sekundiks vilkuma, seejärel süttib kolmeks sekundiks kollane ning kümneks sekundiks punane ja lõpuks jääb uuesti pidevalt põlema roheline LED.
  2. Loendab nupuvajutusi. Vajutus loetakse lõppenuks alles siis, kui nupp vabastatakse. Tulemus kuvatakse kahendkoodis LED-idel. Maksimaalne tulemus kolmel LED-il on 23-1. Roheline LED tähistab 1. bitti, kollane 2. bitti, punane 3. bitti.
  3. Vajutades nupule S1, süttib korraga LED1 ja LED3, vajutades nupule S2, süttib LED2, vajutades nupule S3, kustuvad kõik LED-id. Operatsioonid tuleb teostada otse vastavate registrite väärtusi muutes (ilma Kodulabori teegita).
  4. Loendab nupuvajutusi. Tulemus kuvatakse LED-i vilkumistega. Pärast igat nupule vajutamist suureneb vilgutamiste arv ühe võrra. Valida võib suvalise nupu. LED-i vilgutamiseks kasutada alamfunktsiooni, mille parameetriks on vilkumiste arv.
  5. Vajutades nupule S1, vilgutab punane LED morsekoodis “SOS”, vajutades nupule S2, vilgutab kollane LED “CQD” ja, vajutades nupule S3, vilgutab roheline LED “OK”.

Edasijõudnule

  1. Igale nupule kolmest vastab üks LED, mis süttib nuppu all hoides. Süütamiseks või kustutamiseks tuleb kasutada registreid ja teha võib seda ainult ühe omistamistehtega (vihje: kasutada bitinihutust).
  2. Vajutades nuppe järjekorras S3 – S2 - S1, süttib roheline LED. Kõigi teiste kombinatsioonide korral süttib punane LED. Iga nupuvajutuse korral vilgatab kollane LED, mis kinnitab nupule vajutust.
  3. Igale LED-ile vastab üks nupp. Kontroller vilgutab LED-e suvaliselt ja kasutaja peab nuppe vajutades sama jada kordama. Vilkumiste jada läheb iga korraga järjest pikemaks, lisades eelnevale jadale uue suvalise LED-i. Pärast iga kasutaja sisestuskorda kontrollitakse, kas sisestus oli õige. Sisestuste vahe on kaks sekundit. Vale sisestuse korral vilgutatakse kõiki tulesid korraga kolm korda. (Mängija õigete sisestuste arvu võib kuvada LCD ekraanil.)
  4. Programm mõõdab reaktsiooniaega. Suvalise LED-i süttides peab kasutaja võimalikult kiiresti vajutama nuppu LED-i all. Aeg, mil LED süttib, on juhuslik, kuid vähemalt 100 ms. Reaktsiooniaega näidatakse kasutajale millisekundites LCD ekraanil. Nuppude väärtust ei tohi lugeda kontaktide põrkumist filtreeriva funktsiooniga, sest see tekitab lisaviite.

 

Kordamisküsimused

  1. Mis on tehete “=” ja “=” erinevus? Esitage selle erinevuse tõestuseks kaks näidet.
  2. Mis on tehete “|” ja “||” erinevus? Esitage selle erinevuse tõestuseks kaks näidet.
  3. Kirjutage avaldis, milles kasutate võrrandit “x = x + 1” kaksteist korda.
  4. Kuidas kirjutate C-keeles lõputu tsükli? Esitage kaks erinevat varianti.
  5. Millist tüüpi muutuja valite C-keeles, et esitada positiivseid arve vahemikus 7 kuni 154?
  6. Milline register määrab ära pordi suuna? Tooge pordi näide sisendi ja väljundi seadistamise kohta.
  7. Milliste meetoditega saab elimineerida lüliti kontaktide põrkumisest tekkivaid väärlülitusi? Tooge näiteid riistvaralise ja tarkvaralise lahenduse kohta.
  8. Mida tähendab termin bitinihutus? Tooge praktiline näide koos seletusega.
  9. Miks kasutatakse lülitite juures pull-up takistit? Mille järgi määratakse selle takistus?
  10. Arvutage LED voolu piirava takisti väärtus, kui toitepinge on 5 V, LED päripinge 2,7 V ja vool 30 mA.

Taimerid ja viited

Taimerid

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 juhtida. Oma olemuselt on taimerid ja viited väga sarnased, kuid on ka selgesti eristatavaid erinevusi. 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. Sarnasuse poole pealt töötavad nad mõlemad aga 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 mikrokontrolleri sisesed taimerid.

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.

Tarkvaraline viide

Vajalikud teadmised: [HW] Kontrollermoodul, [AVR] Arhitektuur, [LIB] Sisend-väljundviigud, [LIB] Viide

Teooria

Tihti on mikrokontrollerite programmis vaja tekitada viiteid, et tegevusi ajastada või nende lõppu oodata. Üks idee poolest lihtsamaid meetodeid mikrokontrolleri töös paus tekitada on selle protsessor mingi muu tegevusega üle koormata - näiteks panna see lugema suuri arve. Protsessori taktsagedusest saab välja arvutada, mitmeni see arve loendama peaks, et kindlat ajalist viidet tekitada. Mingi arvu loendamine nullist protsessori taktsageduse väärtuseni hertsides tekitaks teoreetiliselt viite üks sekund. Praktikas see erinevatel põhjustel päris nii lihtne ei ole.

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 tulevad ka tarkvaralise viite masinkood ja selle ajaline kestus erinevad.

Praktika

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 täitmiseks kulub. Infot instruktsioonide toime ja tööaja kohta leiab AVR käsustiku andmelehest. Antud näites kulub ühe 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 kasutatav 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 kasutatakse ka järgmistes näidetes.

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 tööd jätkata.

Praktika

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-i süütamine
		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 1 sekundi järel, on aeg tegelikult siiski natuke pikem, sest LED-i ja viite funktsioonide väljakutsumised võtavad ka mõned mikrokontrolleri taktid aega.

Riistvaraline viide

Vajalikud teadmised: [HW] Kontrollermoodul, [AVR] Loendurid/Taimerid, [LIB] Sisend-väljundviigud, [LIB] Viide, [LIB] Taimerid, [PRT] Tarkvaraline viide

Teooria

Tarkvaraline viide pole ainus meetod pausi tekitamiseks. 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 mingi teguriga jagada väiksem taktsageduse saavutamiseks - seda tehakse taktijaguriga, mida inglise keeles nimetatakse 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 loenduri väärtuse muutusega kaasnevad sündmused

AVR loendurit saab panna teavitama loenduri ületäitumisest (inglise keeles overflow) või kindla väärtuse saavutamisest (inglise keeles compare match). Ületäitumine tekib hetkel, kui loendur on omistanud maksimaalse võimaliku väärtuse ja alustab uuesti nullist loendamist. Kindla väärtuse saavutamise puhul aga toimub loenduri suurendamise hetkel selle uue väärtuse võrdlemine kasutaja poolt määratud väärtusega. Sündmuse tekkimise korral seatakse AVR olekuregistrites vastavad bitid automaatselt kõrgeks.

Selleks, et taimeriga viide tekitada, piisabki vaid loenduri seadistamisest ja 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.

Praktika

Allpool olev programmikood on 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-ga 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. F_CPU on makro-keele konstant, mis näitab taktsagedust hertsides. Nimetatud taktsageduse puhul peaks 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();	
}

 

Esitatud viite funktsioon kasutab aga taimerite teeki, mille lähtekood näeb välja järgmine:

//
// Taimer 0 taktijaguri valiku tüüp
//
typedef enum
{
	TIMER0_NO_PRESCALE         = 0x01,
	TIMER0_PRESCALE_8          = 0x02,
	TIMER0_PRESCALE_32         = 0x03,
	TIMER0_PRESCALE_64         = 0x04,
	TIMER0_PRESCALE_128        = 0x05,
	TIMER0_PRESCALE_256        = 0x06,
	TIMER0_PRESCALE_1024       = 0x07
}
timer0_prescale;
 
//
// Taimer 0 normaalrežiimi seadistamine
//
inline void timer0_init_normal(timer0_prescale prescale)
{
	TCCR0 = prescale & 0x07;
}
 
//
// Taimer 0 peatamine
//
inline void timer0_stop()
{
	TCCR0 = 0x00;
}
 
//
// Taimer 0 loenduri väärtuse määramine
//
inline void timer0_set_value(unsigned char value)
{
	TCNT0 = value;
}
 
//
// Taimer 0 ületäitumise lipukese nullimine
//
inline void timer0_overflow_flag_clear(void)
{
	bit_set(TIFR, TOV0);
}
 
//
// Taimer 0 ületäitumise lipukese oleku lugemine
//
inline bool timer0_overflow_flag_is_set(void)
{
	return (bit_is_set(TIFR, TOV0) ? true : false);
}

 

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 muude funktsioonide täitmine igas tsüklis võtab samuti aega. Täpseks ajastuseks tuleb kasutada 16-bitist taimerit koos katkestustega.

//
// Kodulabori riistvaralise viite demonstratsioonprogramm.
// Programm vilgutab ~1 sekundi järel hetkeks LED-i.
//
#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-i viigu väljundiks seadmine
	pin_setup_output(debug_led);
 
	// Lõputu tsükkel	
	while (true)
	{
		// LED-i põlema panek
		pin_clear(debug_led);
 
		// Riistvaraline paus 100 millisekundit
		hw_delay_ms(100);
 
		// LED-i kustutamine
		pin_set(debug_led);
 
		// Riistvaraline paus 900 millisekundit
		hw_delay_ms(900);
	}
}

Perioodiline katkestus

Vajalikud teadmised: [HW] Kontrollermoodul, [HW] Kasutajaliidese moodul,
[AVR] Katkestused, [AVR] Loendurid/Taimerid, [LIB] Sisend-väljundviigud, [LIB] Viide,
[LIB] Taimerid, [PRT] Tarkvaraline viide

Teooria

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 kiireks sündmusele reageerimiseks, kuid neid võib kasutada ka mitme paralleelse protsessi või täpset ajastust nõudvate tegevuste täitmiseks 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.

Praktika

Järgnev programm näitab, kuidas seadistada loendurit tekitama katkestust. Programmis on kasutusel kaks Digitaalse sisend-väljundmooduli LED-i, millest punase olekut muudetakse perioodiliselt tarkvaralise viitega ja roheline, mille olekut muudetakse katkestuse tekkimisel. Tarkvaralise viitega LED-i 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 funktsiooniga timer1_init_ctc. 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 üle kogu mikrokontrolleri. Globaalseks katkestuste lubamiseks on funktsioon sei ja keelamiseks cli. 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. Nimetatud seadistuste juures on loendur 1 maksimaalse väärtuse saavutamise katkestuse vektoriks TIMER1_CAPT_vect.

//
// Kodulabori loenduri katkestusega vilkuva LED-i 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 punase LEDi vilgutamise viide on 1000 ms, siis tegelik aeg, mis kulub iga tsükli täitmiseks, on natuke suurem. Põhjus on selles, et ka LED-i 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-i vilkumine rohelise LED-i vilkumisest pidevalt maha. Just sel põhjusel ei ole soovitatav ka kellaaja loendureid ja muid täpselt ajastatud tegevusi teha viitega, vaid loenduri katkestustega.

Harjutusülesanded

Ülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Panna punane LED vilkuma 10-sekundilise perioodiga (poolperiood 5 s). Teostamiseks luua tarkvaralise viite funktsioon, mille parameetriks on sekundite arv.

Algajale

  1. LCD ekraanil kuvada aega 100 ms täpsusega, mis kulub suvalise kahe nupu allavajutamiste vahel. Aja mõõtmise teostuse võib vabalt valida.
  2. Vajutades nuppu S1, aeglustub kõigi kolme LED-i vilkumine 2 korda, vajutades nuppu S3, sageneb vilkumine 2 korda, ja vajutades nuppu S2, määratakse vilkumise sageduseks 1 Hz. Kasutada viitefunktsioone või katkestusi. (Katkestused on keerukamad, kuid viitefunktsioonidega tekib nuppude filtreerimisfunktsiooni tõttu lisaviide.)
  3. 7-segmendilisel LED indikaatoril kuvada nupu S1 vajutamise sagedus hertsides. Sageduse näit tuleb piirata madalamalt nulli ja kõrgemalt üheksaga.
  4. Nupule S1 vajutades loendab programm sekundeid 60-st nullini ja süütab seejärel punase LED-i. Nupule S2 vajutades on ajaks 30 sekundit, misjärel süüdatakse kollane LED. Nupp S3 aeg on 10 sekundit ja süüdatav LED on roheline. Kõik protsessid peavad toimima paralleelselt. LED-id kustuvad, kui vajutada vastavaid nuppe.
  5. Näidata LCD ekraanil kellaaega kujul “hh:mm:ss”. Kasutada tuleb riistvaralist taimerit 1 koos katkestustega ja kellaaeg peab nuppudega seadistatav olema. Soovitatav on kasutada 3 nuppu, millest S1 suurendab roteeruvalt tunde, S2 minuteid ja S3 sekundeid.

Edasijõudnule

  1. Teha stopper, mis LCD ekraanil kuvab tunde, minuteid, sekundeid ja millisekundeid. Nupp S1 alustab mõõtmist, S2 peatab mõõtmise ja S3 nullib aja. Kasutada tuleb taimeri katkestust.
  2. 2-sekundilise vahega süttib ja kustub sujuvalt järjest punane, kollane ja roheline LED. Sujuv valgustus saadakse LED-i mitmesajahertsise sagedusega moduleerides (seda ülikiiresti süüdates ja kustutades) ja põlemise/kustumise aja proportsioone muutes, mistõttu silmale paistab, et LED-i heledus muutub (tegu on pulsilaiusmodulatsiooniga).
  3. Kirjutada C-keeles programmilõik, mis tekitab 14,7456 MHz taktsagedusel 10 μs ± 10 % viite. Viite toime tõestada teoreetiliselt - kompileeritud programmi .lss failis olevaid assemblerkeele instruktsioone kommenteerides.

 

Kordamisküsimused

  1. Millised meetodid on viite tekitamiseks?
  2. Kuidas tekitada tarkvaraline viide? Millistest parameetritest tarkvaralise viite kestus sõltub?
  3. Mis sunnib kasutama riistvaralist taimerit koos katkestusega?
  4. Arvutage 8-bitise taimeri ületäitumise katkestuse periood, kui taktsagedus on 16 MHz ja sagedusjaguri tegur 1024.
  5. Mis asi on arvutites peituv “RTC”?
  6. Mis juhtub 19. jaanuaril 2038 arvutite maailmas?
  7. Mida saab AVR taimeritega veel teha peale aja loendamise?
  8. Milliste registritega saab seadistada ATmega128 taimer 0. Mida on nende registritega võimalik seadistada?
  9. Milline on suurim katkestuste ajaline täpsus millisekundites, mida on võimalik saavutada ATmega128 mikrokontrolleriga, mis töötab 14,7456 MHz taktsagedusel? Näidake arvutusvalem.
  10. Kui protsessor on tugevalt koormatud programmi täitmisega (näiteks juhib mitut mootorit ja kontrollib pidevalt paljude andurite väärtusi), siis kas see mõjutab taimeri aja mõõtmise täpsust? Selgitage oma vastust.

Näidikud ja ekraanid

Ekraanid

Üks lihtsamaid meetodeid veendumaks mikrokontrolleri töö korrektsuses on lisada programmi koodilõik, mis vilgutab LED-i või mitut kindla tegevuse korral. 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 omajagu vaeva näha.

Järgnevad peatükid tutvustavad lihtsamat liiki näidikuid ja ekraane - LED segmentidega indikaatorit ja kahte 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 populaarsemaks muutumas elektrooniline paber, mis imiteerib juba trükist. Kui esmased e-paberid (lühend elektroonilisest paberist) koosnesid erinevat värvi külgedega kuulikestest, mida pöörati elektriväljas, siis uuemad e-paberid sisaldavad aga pisikesi kapsleid, kus kahe värvi erinevalt laetud osakesi mõjutatakse elektriväljaga kas põhja vajuma või pinnale tõusma. Viimased nimetatud näidikud ja ekraanid on toodud infoks näitamaks visualiseerimise erinevaid võimalusi, kuid need lähemat käsitlemist Kodulabori kontseptsioonis ei leia.

7-segmendiline numberindikaator

Vajalikud teadmised: [HW] Kasutajaliidese moodul, [LIB] Viide,
[LIB] 7-segmendiline LED indikaator, [PRT] Valgusdiood

Teooria

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.

LED indikaatori segmentide asetus ja elektriskeem

Elektriliselt on kõigi LED-ide anoodid ühendatud ühise anoodi viiguga ca. LED-e süüdatakse nende katoode (a, b, c…) lülitades. Olemas on ka vastupidi ühendusi, kus indikaatoritel on ühine katood cc. 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 kas või otse mikrokontrolleri viikudelt, kuid on ka spetsiaalseid ajureid, mis võimaldavad numberindikaatorit juhtida vähemate mikrokontrollerite viikude arvuga. 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.

Praktika

Digitaalse mooduli plaadil on üks 7-segmendiline LED numberindikaator. Seda juhitakse läbi järjestikliidesega ajuri A6275. Ajuri järjestikliides on sarnane SPI-ga, kus kasutatakse ka taktsignaali ja andmesignaali. Erinevalt SPI-st pole kasutusel kiibi valikut (inglise keeles chip-select), kuid selle asemel on andmete lukustussignaal (inglise keeles latch). Nimetatud kolm liini on ühendatud ATmega128-ga järgnevalt:

LED ajuri nihkeregistri ülesehitus koos vastavate indikaatori segmentidega
  • Lukustussignaal (latch) - PG2
  • Taktsignaal (clock) - PC7
  • Andmesignaal (data) - PC6

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 iga segmendi põlemine on tähistatud bitiga 1 ja kustumine bitiga 0. Bitid madalamast kõrgemaks (binaarkujul paremalt vasakule) tähistavad segmente A, B, C, D, E, F, G ja DP. Ajuri juhtliides on teostatud tarkvaralise SPI-ga ehk andmesideviike programmis tarkvaraliselt juhtides. Funktsiooniga segment_display_init 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 ajurile. Taktsignaali sageduseks on tarkvaraliste pausidega saadud ligikaudu 500 kHz.

 

Järgnevalt on toodud konkreetsem numberindikaatori kasutamise näiteprogramm. Programmis kasutatakse teegi eelnevalt kirjeldatud funktsioone. Programm loeb ligikaudu sekundilise intervalliga numbreid nullist üheksani. Selline loendamine on saavutatud 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);
	}
}

Alfabeetiline LCD

Vajalikud teadmised: [HW] LCD moodul, [LIB] Alfabeetiline LCD, [LIB] Viide,
[PRT] Perioodiline katkestus

Teooria

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 tumedana.

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äikeste 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.

Alfabeetilise LCD pikslite maatriksitest moodustatud tekst

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 LCD kontrollerile tähtede indekseid saates. Tegelikkuses tuleb LCD kontrolleritele ka mitmeid juhtkäske saata, enne kui midagi kuvama hakatakse. Iga konkreetse LCD ekraani kasutamiseks tuleb tutvuda enne selle andmelehega, kuna neid on väga erinevaid ning ühtlasi ka nende juhtimine toimub erinevalt.

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 - reeglina must, kuid esineb ka valge ja värvilise kirjaga ekraane.

Praktika

Kodulabori digitaalse mooduli külge ühendub 2×16 märgiline alfabeetiline LCD WC1602A. Ekraani juhtimiseks on 4-bitine andmesiin ja 3 juhtviiku, kuid selle suhtlusprotokoll on liiga mahukas, et seda siinkohal lahti seletada. Lihtsuse huvides on ekraani kasutamiseks Kodulabori teegis olemas vastavad funktsioonid, mille lähtekoodi leiab Kodulabori veebilehelt.

Esimene asi, mis ekraani kasutamiseks teha tuleb, on see algseadistada. Vastavaks otstarbeks on funktsioon lcd_alpha_init, millega saab lisada ekraanile ka vilkuva kursori. Ekraanil on olenemata sellest, kas seda on näha või mitte, pidevalt üks aktiivne kursori positsioon, kuhu sisestatakse järgmine täht. 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 ligikaudu sekundiga. 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 teksti 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);
	}
}

Graafiline LCD

Vajalikud teadmised: [HW] LCD moodul, [LIB] Graafiline LCD, [LIB] Viide,
[PRT] Teksti LCD

Teooria

Graafiline LCD on vedelkristall-ekraan, millega saab peale teksti ka kujundeid kuvada. Selle ehitus sarnaneb alfabeetilisele LCD-le ja 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.

Graafilise LCD pikslitest moodustatud pilt

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 sarnane alfabeetiliste LCD omadustega ja 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.

Praktika

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 algväärtustada funktsiooniga lcd_gfx_init. Pärast käivitust on soovitatav ekraan, õigemini kontrolleri mälu, puhastada funktsiooniga lcd_gfx_clear. 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 algseadistamine
	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);
	}
}

Harjutusülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Loendab 7-segmendilisel indikaatoril numbreid 1..9 ning siis tagurpidi tagasi 9..1. Loendamise periood 1 sekund.

Algajale

  1. Suvalises järjekorras esitada 7-segmendilisel indikaatoril kuueteistkümnendsüsteemi arve sagedusega 1 Hz.
  2. 7-segmendilisel indikaatoril panna 500 ms perioodiga ringiratast kordamööda põlema välised 6 segmenti.
  3. Alfabeetilisel LCD-le kirjutada järgnev tekst: “õun öö äpu ülo”
  4. Alfabeetilisel LCD-l näidata erisümboleid. Kuvada ekraanil kahel real järgnevad tekstid: “Minu programm ©”, “Kodulabor™”
  5. Graafilisel LCD-l kuvada 10-realine tekst, mida saab nuppudega S1 ja S2 üles-alla kerida.
  6. Kolme nupuga teha kasutajaliides teksti sisestamiseks. Näiteks ühe nupuga teha märgi valik, teisega märgi kinnitamine ja kolmandaga teksti lõplik kinnitamine. Teksti maksimaalne pikkus on 10 märki ja tekst tuleb pärast sisestust tagurpidi keerata ning teisel real kuvada. Piirduda võib ladina tähestikuga. LCD omal valikul.

Edasijõudnule

  1. Graafilisel LCD-l kuvada kreeka tähti. Esitada järgnevad read: “Takistus Ω”, “∑R=∑πR²”, “π=3.141592”. Vaja läheb Kodulabori teegi lähtekoodi (veebilehelt).
  2. Kirjutada kümnendsüsteemi arvu sisestaja ja kahendkoodi teisendaja. Kasuta nuppe S3 - S1 sisestamaks kümnendsüsteemi arvu (S3 - sajalised, S2 - kümnelised, S1 - ühelised) 10 sekundi jooksul. Näiteks 4 nupuvajutust S3-l tähendab arvu 400. Sisestamise alguse märguanne ja arvu kahendkoodi tulemus kuvada suvalisel LCD-l.
  3. Kirjutada funktsioon, mis kuvab graafilisel LCD-l ristküliku, kui laius, pikkus ja vasaku ülemise nurga koordinaadid on ette antud. Joone paksus on 1 piksel. Kontrollida, et etteantud ristkülik mahub ekraani mõõtudesse. Soovitatav on uurida Kodulabori teeki.
  4. Teha lihtne ussimäng graafilisel LCD ekraanil. Ussi laius on 1 piksel, pikkus 5 pikslit. Ussi saab nuppudega vasakule või paremale pöörama panna. Uss peab suutma vältida kokkupõrget ekraani servaga (enne seda ära keerama). Boonuspunktid munade korjamise võimaluse ja järjest pikeneva ussi eest. Ülesande lihtsam lahendus on uss teha “O” tähtedest.
  5. Kirjuta programm erinevate ilmastikunähtuste kuvamiseks graafilisel LCD-l. Päikesepaisteline ilm - päikese ikoon, vihmane ilm - pilv koos sajuga, pilves ilm - lihtsalt pilv, lumesadu - lumehelves. Ikoonide suurus võib varieeruda, peaasi, et ikoonid on selgesti eristatavad. Ikoone peab nupuvajutusega vahetada saama.

 

Kordamisküsimused

  1. Mitu viiku kasutab 7-segmendiline numbernäidik (koos punktisegmendiga), kui see on ühendatud mikrokontrolleriga otse? Mitu viiku on vaja, kui numbernäidikut juhitakse läbi ajuri A6275?
  2. Mis määrab 7-segmendilise numbernäidiku heleduse? Kuidas seda reguleerida, kui numbernäidikut juhitakse otse ja läbi ajuri A6275?
  3. Kui 7-segmendiline numbernäidik on kontrolleriga otse ühendatud porti A nii, et segment A on viik PA0, B on PA1 … ja DP on PA7, siis millised on PORTA registri väärtused numbrite 0..9 korral?
  4. Mille poolest erinevad alfabeetilise LCD 4-bitine ja 8-bitine juhtliides?
  5. Milliste viikude kaudu reguleeritakse alfabeetilise LCD taustavalgust ja kuidas?
  6. Mis andmevahetusprotokolli kasutab graafiline LCD? Selgitage andmevahetusviikude tähendusi.
  7. Kuidas teisendada kümnendsüsteemi arvu kahendsüsteemi arvuks (tekstikujule) ja vastupidi?
  8. Joonistage twisted nematic-tehnoloogias valmistatud LCD ekraani koostekihid.
  9. Kuidas moodustatakse graafilisel LCD-l tähed?
  10. Mille poolest erineb monokromaatiline (must-valge) ja värviline LCD ekraan?

Andurid

Andurid

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 väga 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 jagada väga üldiselt kahte tüüpi: analoog- ja digitaalandurid.

Analooganduris muutub füüsikalise suuruse muutudes mõni selle elektriline parameeter, tavaliselt kas pinge, vool või takistus. Kuna mikrokontrollerid on digitaalsed seadmed, siis analooganduri info edastamiseks kontrollerile tuleb see digitaalseks teisendada. Selleks kasutatakse peamiselt mikrokontrolleritesse integreeritud 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.

Potentsiomeeter

Teooria

Potentsiomeetri elektriline tähis

Potentsiomeeter on kolme kontaktiga muuttakisti, mille kahe äärmise kontakti vahel on fikseeritud takistus ja äärmiste ning keskmise kontakti vahel muutuv takistus. Potentsiomeeter on põhimõtteliselt ka pingejagur, kus takistid moodustuvad äärmiste kontaktide ja keskmise kontakti vahel. Potentsiomeetri (inglise keeles potentiometer) sünonüüm on reostaat, mis pärineb venekeelsest sõnast реостат.

Pööratav potentsiomeeter

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 pööratavad (näide kõrvaloleval pildil), kuid eksisteerib ka liugtakisteid. Potentsiomeetrite eriliik on digitaalsed potentsiomeetrid, milles takistuse reguleerimine toimub mikroskeemi sees vastavalt juhtsignaalidele.

Praktika

Kodulabori Andurite mooduli plaadil 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 jääb ootama muundamise lõppu ja tagastab väärtuse alles siis, kui mõõtmine on tehtud.

Näiteprogrammis kasutatakse äsja 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);
	}
}

Termistor

Vajalikud teadmised: [HW] Andurite moodul, [HW] LCD moodul, [ELC] Pingejagur,
[AVR] Analoog-digitaalmuundur, [LIB] Analoog-digitaalmuundur, [LIB] Alfabeetiline LCD,
[LIB] Andurid

Teooria

NTC termistor

Termistor on takisti, mille takistus muutub temperatuuriga. 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-Harti kolmandat järku eksponentsiaalne võrrand. NTC termistoride jaoks on olemas järgmine B-parameetriga lihtsustatud võrrand:

NTC termistori takistuse temperatuurisõltuvus

kus:

  • T0 on nimitemperatuur, näiteks 25 °C.
  • R0 on takistus nimitemperatuuril.
  • B on B-parameeter.

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 võimalusel kasutada andmelehel antud võrrandit.

Termistori takistust mõõdetakse kaudselt pingejaguriga, kus ühe takisti asemel on termistor ja mille 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älja arvutatud temperatuuri ja takistuse vahelise sõltuvuse 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.

Praktika

Kodulabori Andurite mooduli plaat 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 samaaegselt 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 Steinhart-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äpsusega 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 kraadides.
//
#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);
	}
}

Fototakisti

Teooria

Fototakisti
Fototakisti elektriline tähis

Fototakisti on andur, mille elektriline takistus muutub sõltuvalt temale pealelangeva 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 kindlasti sisse viia täpsustavad teisendused, kuna anduri takistuslik omadus sõltub välistemperatuurist.

Valguse intensiivsuse iseloomustamiseks kasutatakse füüsikalist suurust valgustustihedus (tähis E), mis näitab mingile pinnale jõudva valgusvoo hulka. Mõõdetavaks ühikuks on luks (lx), kus 1 luks tähendab, et 1 m2 suurusele pinnale langeb ühtlaselt valgusvoog 1 luumen. Reaalses elus praktiliselt kunagi aga ei lange valgus (elamis)pinnale ühtlaselt ning seetõttu valgustustihedus saadakse rohkem keskmise väärtusena. Võrdluseks olgu ära toodud ka mõningad valgustustiheduse näited:

Keskkond Valgustustihedus (lx)
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

Praktika

Kodulabori Andurite mooduli plaat 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 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äesolev harjutus on aga natukese keerulisem, kuna leitakse andurile valgeva valguse valgustustihedust luksides. Selle tegemiseks on kasutusel ligikaudne arvutusvalem ja ujukoma arvud. Ujukoma arvud on C-keeles float ja double tüüpi, 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 suhteliselt palju programmimälu ja aega. Kui puudused pole olulised, on ujukoma arvud väärt kasutamist.

VT935G valgustustiheduse (E) ja elektritakistuse (R) vaheline seos

Fototakisti valgustustiheduse ja elektritakistuse vahelise seose kohta annab anduri andmeleht ligikaudse valemi. Nagu kõrvalolevalt graafikult näha, on logaritmskaalas valgustustihedus 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 lx valgustustiheduse (EA) juures. Seega on olemas 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 valgustustiheduse (EB). Avaldame joone võrrandist EB:

log(EB) = log(RA/RB) / γ + log(EA)

EB = 10log(RA/RB) / γ + log(EA)

Sellega on takistusest valgustustiheduse 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 asendatud väärtustega ja alaindeksid ära jäetud:

U = 5 ⋅ (ADC / 1024)

R = (10 ⋅ 5) / U - 10

Valgustustiheduse 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 arvväärtusi. Järgnevalt on toodud näidisprogrammi lähtekood, mis teostab ADC-ga mõõtmist, arvutamist ja valgustustiheduse kuvamist LCD ekraanile. Kuid veel enne programmi kompileerimist tuleb projektis teha seadistused ujukoma arvude kasutuselevõtuks. Selle kohta on lühiõpetus tarkvara paigaldamise peatükis.

Näidisprogrammis defineeritakse pinge, takistuse ja valgustustiheduse muutujad ujukoma tüüpi arvuna double. Arvud, mida soovitakse kindlasti ujukoma tehetes kasutada, peavad alati sisaldama komakohta (C-keeles punkti), 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 valgustustihedus luksides
//
#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;
 
		// Valgustustiheduse luksides arvutamine		
		illuminance = 255.84 * pow(resistance, -10/9);
 
		// Valgustustiheduse 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);
	}
}

Infrapuna kaugusandur

Vajalikud teadmised: [HW] Andurite moodul, [HW] LCD moodul, [AVR] Analoog-digitaalmuundur, [LIB] Analoog-digitaalmuundur, [LIB] Alfabeetiline LCD, [LIB] Andurid

Teooria

Sharp GP2Y0A21YK

Objekti kauguse mõõtmiseks on olemas triangulatsioonimeetodil töötavad optilised andurid. Levinuimad neist on firma Sharp poolt toodetavad infrapuna (inglise keeles infra-red, lühend IR) 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ühend 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. Erinevatelt kaugustelt peegelduvate kiirte teekonda näitab kõrvalolev joonis.

IR kaugusmõõdiku valguskiire teekond

Sharp-i kaugusandurite väljund on pöördvõrdeline - kauguse kasvades see väheneb ja järjest aeglasemalt. Täpne kauguse ja väljundi vaheline 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 valguse intensiivsuse 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äljundpinge 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.

Praktika

Tüüpiline Sharp IR kaugusmõõdiku pinge-kauguse graafik

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 pinge kauguseks teisendamise protsessi tutvustamine.

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 juba on, ning sellest on suhteliselt lihtne leida valem pinge kauguseks teisendamiseks. Valemi leidmiseks tuleb sama graafiku punktid sisestada mõnda tabelarvutuse programmi ja nendest uuesti graafik luua. Tabelarvutusprogrammides on graafiku punktide põhjal võimalik arvutada automaatselt välja trendijoon. 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.

Kauguse ja ADC väärtuse lineariseerimise graafik

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-eksitusmeetodil - läbi on proovitud erinevaid arve, kuni on leitud selline, mille korral graafik kattub trendijoonega kõige rohkem. 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

  • d on kaugus sentimeetrites
  • k on korrigeerimiskonstant (leitud katse-eksitusmeetodil)
  • ADC on pinge digitaliseeritud väärtus
  • a on lineaarliige (väärtus tuleb trendijoone võrrandist)
  • b on vabaliige (väärtus tuleb trendijoone võrrandist)

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 (saadud jooniselt), 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, mis on ebaloogiline.

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 hiljem programmi lihtsalt lisada uusi IR kaugusandurite mudeleid.

 

//
// 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)
{
	signed short value, 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 saab kauguse või veateate kuvada ?
		if (distance >= 0)
		{			
			sprintf(text, "%d cm   ", distance);
		}
		else
		{
			sprintf(text, "Viga   ");
		}
 
		// Teksti kuvamine LCD teise rea alguses
		lcd_alpha_goto_xy(0, 1);
		lcd_alpha_write_string(text);
 
		// Paus
		sw_delay_ms(500);
	}
}

Ultraheli kaugusmõõdik

Vajalikud teadmised: [HW] Andurite moodul, [HW] LCD moodul, [AVR] Loendurid/Taimerid, [LIB] Taimerid, [LIB] Alfabeetiline LCD, [LIB] Andurid, [PRT] Riistvaraline viide

Teooria

SRF04 ultraheli kaugusmõõdik

Ultraheli kaugusmõõdik määrab objekti(de) kaugust, mõõtes helilaine objektilt tagasipeegeldumise aega. 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 ja teine registreerib tagasipeegelduva kaja. 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õõdiku tööpõhimõte

Ultraheli kaugusmõõdikutel on igapäevaelus mitmeid rakendusi. Neid kasutatakse mõõdulintide asendajatena kauguse mõõtmise seadmetes, näiteks 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 pärivoolu kiiremini.

Praktika

Kodulabori Andurite mooduli komplektis on Devantech SRF04 või SRF05 ultraheli kaugusmõõdik. SRF04/SRF05 on ainult andur, mis otseselt kauguse infot ei väljasta. Anduril on peale toiteviikude veel 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 niikauaks, 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 kõrvalolev graafik.

SRF04 signaalid

Devantech-i ultrahelianduri 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 lubatust pikemaks. Mida kiiremini kaja saabub, seda kiiremini saab mõõtetulemuse. Kui kaja ei saabugi, ootab funksioon seda ~36 ms ja tagastab seejärel 0. Oluline on mõõtmiste vahele jätta mõnikümmend millisekundit pausi, et eelmisel mõõtmisel tekitatud helilaine jõuaks sumbuda ega rikuks uut mõõtmist. Kui kasutatakse samaaegselt mitut ultraheli andurit, tuleb samuti jälgida, et helilained ei kattuks.

#define ULTRASONIC_SPEED_OF_SOUND 33000 // cm/s
 
//
// Ultraheli kaugusanduriga mõõtmine
//
unsigned short ultrasonic_measure(pin trigger, pin echo)
{	
	// Viikude seadistus
	pin_setup_output(trigger);
	pin_setup_input_with_pullup(echo);
 
	// Taimer 3 normaalrežiimi
	// perioodiga F_CPU / 8
	timer3_init_normal(TIMER3_PRESCALE_8);
 
	// Päästiku viik kõrgeks
	pin_set(trigger);
 
	// Taimeri nullimine
	timer3_overflow_flag_clear();
	timer3_set_value(0);	
 
	// ~10 us ootamine
	while (timer3_get_value() < 18) {}
 
	// Päästiku viik madalaks
	pin_clear(trigger);
 
	// Kaja signaali alguse ootamine
	while (!pin_get_value(echo))
	{
		// Liiga kaua oodatud ?
		if (timer3_overflow_flag_is_set())
		{
			return 0;
		}
	}
 
	// Taimeri nullimine
	timer3_set_value(0);
 
	// Kaja signaali lõpu ootamine
	while (pin_get_value(echo))
	{
		// Liiga kaua oodatud ?
		if (timer3_overflow_flag_is_set())
		{
			return 0;
		}
	}
 
	// Mõõdetud aja kauguseks teisendamine
	//   kaugus = aeg * (1 / (F_CPU / 8)) * heli kiirus / 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 kus on ruumi. Lisaks võimaldab viikude valiku vabadus funktsiooni kasutada ka mujal kui Kodulabori komplektis. Toodud funktsioon kuulub ka Kodulabori teeki, nii et seda ei pea oma programmi eraldi kirjutama. Peab aga arvestama, et Kodulabori teegis on see funktsioon jäigalt seotud Kodulabori Kontrollermooduli 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/SRF05 ultrahelianduri 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);
	}
}

Harjutusülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Potentsiomeetri takistuse väärtus kuvatakse LCD-l oomides. Potentsiomeetri takistuse nimiväärtus on 5 kΩ.

Algajale

  1. Potentsiomeetri takistuse väärtus vahemikus (0…999 Ω) kuvatakse LCD-l oomides ja (1000…5000 Ω) kilo-oomides. Potentsiomeetri takistuse nimiväärtus on 5 kΩ. Tulemus näidata korrektsete ühikute ja sümbolitega.
  2. Objekti kauguse mõõtmine. Infrapuna anduriga mõõdetakse objekti kaugust nupu S1 vajutamisel. Mõõtmise ajal vilgutatakse korraks kollast LED-i. Kui objekt on kaugemal kui 50 cm, süttib roheline LED, kui objekt on lähemal kui 50 cm, süttib punane LED.
  3. Mõõdetakse objekti kaugust infrapuna anduriga ja tulemus kuvatakse kolme valgusdioodi (LED1…LED3) abil kahendkujul. Kauguse suurenemisel peab vastavalt kasvama ka kuvatav väärtus. Skaalaks võtta ligikaudu 1 bit = 1 dm.
  4. NTC temperatuurianduri väärtus kuvatakse LCD-l kraadides. Nupu S2 abil saab muuta ühikuid: Kelvin (K), Fahrenheit (F) ja Celsius (C). Temperatuuri näidatakse korrektsete ühikute ja sümbolitega.
  5. Kasutades valgustugevuse andurit, tuvastatakse järsk valgustugevuse muutus (laevalgustuse sisse-välja lülitamine). Kui muutus on järsk, alarmeeritakse sellest punase LED-i vilkumisega (5 sekundit). Kui valgustugevus muutub sujuvalt, näidatakse selle muutumise suunda. Roheline LED tähistab valgusetugevuse suurenemist ja kollane valgustugevuse vähenemist.

Edasijõudnule

  1. Andmesalvestaja. Pidevalt mõõdetakse kõigi analoogandurite väärtusi ja jooksvalt salvestatakse miinimum- ja maksimumväärtused. Nupuga S1 saab vahetada LCD-l kuvatava anduri infot. Kuvada tuleb anduri nimi (lühidalt) ja käesolev-, minimaalne- ning maksimaalne näit. Andurite vahetusjärjekord: IR kaugusandur → Fototakisti → Termistor → Potentsiomeeter.
  2. Kaugusmõõtur. Vajutades nupule S2, tehakse 10 järjestikulist mõõtmist ühe sekundi jooksul. Pärast mõõtmist kuvatakse mõõdetava objekti keskmine kaugus detsimeetrites 7-segmendilisel LED numberindikaatoril. Vajutades nupule S1, kuvatakse minimaalne mõõtetulemus, ja vajutades nupule S3, kuvatakse maksimaalne mõõtetulemus.
  3. Liikumise kiirus. Vastavalt objekti kauguse muutuse suurusele näidatakse seda LED-idel: aeglane muutus rohelise LED-iga, mõõdukas muutus kollase LED-iga ja kiire muutus punase LED-iga. Kiirust võib kuvada ka LCD ekraanil.
  4. Automaatne mõõtepiirkond. Vastavalt jooksvale mõõtetulemusele leitakse minimaalne ja maksimaalne mõõdetav temperatuur ning vastavalt sellele piirkonnale skaleeritakse näitu numbrist 0 numbrini 9. Näit kuvatakse 7-segmendilisel numberindikaatoril.
  5. Kombineerides infrapuna ja ultraheli kaugusanduri, määratakse objekti kaugus, liikumise kiirus ja suund. Tulemused kuvatakse LCD-l.

 

Kordamisküsimused

  1. Mis on ATmega128 mikrokontrolleri analoog-digitaalmuunduri (ADC) täpsus? Milline on vähim sisendi pinge muutus, mida on võimalik mõõta?
  2. Kaua võtab aega üks ADC muundamise protsess? Kuidas saab muuta muunduri töösagedust?
  3. Milline on ADC sisendpinge piirkond? Kas ja kuidas on võimalik seda muuta?
  4. Mis vahe on positiivse temperatuuri koefitsiendiga (PTC) ja negatiivse temperatuuri koefitsiendiga (NTC) termistoril? Loetlege ühe eelised teise ees.
  5. Mis on pingejaguri eesmärk mõõteahelas?
  6. Koostage pingejagur, mis võimaldaks ATmega128 mikrokontrolleriga kasutada analoogandurit, mille maksimaalne väljundpinge on 10 V. Määrake vastavalt ka ADMUX registri sisu.
  7. Kui potentsiomeetri otstele lisada eraldi takistid ja rakendada neile pinge 5 V, siis millised peavad olema lisatakistite ja potentsiomeetri takistus, et pinget potentsiomeetri liuguril saaks reguleerida 1 V ja 2 V vahel (potentsiomeetrit servast-serva pöörates)? Potentsiomeetrit ei tohiks läbida suurem vool kui 10 mA.
  8. Millised keskkonnaparameetrid mõjutavad ultraheli kaugusanduri tööd? Mil määral ja miks?
  9. Milliseid valgustundlikke andureid võiks kasutada robootikaprojektis? Loetlege vähemalt kolm põhimõtteliselt erinevat komponenti ning selgitage nende erinevusi.
  10. Kuidas mõõdetakse valguse abil veel kaugust peale triangulatsioonimeetodi? Nimetada vähemalt 3 meetodit.

Mootorid

Mootorid

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 kasutusel peamiselt erinevad elektrimootorid. Elektrimootor on seade, mis muudab elektrienergia mehaaniliseks pöörlevaks energiaks ja mille töö põhineb elektromagnetismi nähtusel.

Elektrimootorite liigitamiseks on mitu erinevat viisi, kuid 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 enimlevinud elektrimootorile robootikas: püsimagnetiga alalisvoolu mootor, RC (radio-controlled)) servomootor ja samm-mootor.

Alalisvoolumootor

Vajalikud teadmised: [HW] Mootorite moodul, [AVR] Digitaalsed sisendid-väljundid,
[LIB] Mootorid, [LIB] Viide

Teooria

Alalisvoolu mootor

Püsimagnetiga alalisvoolumootorid on laialt levinud erinevates rakendustes, kus olulised on väikesed mõõtmed, suur võimsus ja madal hind. Nende suhteliselt suure pöörlemiskiiruse tõttu kasutatakse neid tihti koos ülekandega (reduktoriga) madalama kiiruse ja suurema pöördemomendi saavutamiseks.

Ideaalne alalisvoolumootori kiiruse (V), voolutugevuse (I), võimsuse (P), efektiivsuse (η) ja jõumomendi (T) vahelise sõltuvuse graafik

Püsimagnetiga alalisvoolumootorid 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 koormusest ja toitepingest. Ideaalse alalisvoolumootori jõumomendi ja kiiruse suhe on lineaarne, mis tähendab seda, et mida suurem koormus on võllil, seda madalam on kiirus ja seda suurem on mähist läbiv vool.

Harjadega alalisvoolumootorid 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-silla tööprintsiip lülitite näitel.

H-sillas tüürivad mootori pöörlemiseks vajalikku voolu neli transistori (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öörlemissuund 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 lisaks ka müra ja seepärast kasutatakse enamasti ü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 integreeritud komponendina ehk ajurina, suuremate voolude jaoks kasutatakse spetsiaalseid võimsustransistore (Power MOSFET). H-silda koos sinna kuuluva elektroonikaga nimetatakse ka mootorikontrolleriks.

Märkus: Mitte ajada segamini RC (raadiojuhitav servomootor) PWM signaali tavaliste PWM signaalidega.

Praktika

Kodulaboris kasutatav alalisvoolumootorite ajur L293D sisaldab endas kahte integreeritud H-silda ja kaitsedioode. Mootorit juhitakse kolme digitaalse signaaliga, millest üks on üldine tööd lubav signaal (inglise keeles 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.

Kodulabori Mootorite mooduli plaadil on võimalus kuni nelja alalisvoolumootori ü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 lubamise viik on konstantselt kõrge. Kui mõlemal juhtviigul on sama väärtus, siis mootor ei liigu, kui erinev, siis mootor 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

Alalisvoolumootoreid võib juhtida otse, manipuleerides mikrokontrolleri viikudega mootoriajuri sisendviike, kuid Kodulabori teegis on selleks olemas ka lihtsustavad funktsioonid:

//
// Alalisvoolumootori kontrolleri 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 alalisvoolumootori juhtimise lubamine
//
void dcmotor_init(unsigned char index)
{	
	pin_setup_output(dcmotor_pins[index][0]);
	pin_setup_output(dcmotor_pins[index][1]);
}
 
//
// Valitud alalisvoolumootori töötamise ja töötamise 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 vastavad viigud väljundiks. Juhtimiseks on dcmotor_drive funktsioon, millega antakse valitud mootorile negatiivse direction parameetriga üks ja positiivse parameetriga teine pöörlemissuund ning 0 puhul mootor peatatakse.

 

Järgnevalt on toodud näidisprogramm, mis juhib esimest ja teist alalisvoolumootorit, nii et need muudavad oma pöörlemissuunda iga sekundi järel. 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;
	}
}

Servomootor

Teooria

RC servomootor
Servomootori PWM signaali laiuse ja võllil oleva hoova asendi vaheline seos

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 pulsilaiusmodulatsiooni (PWM) signaal, kus pulsi laius määrab ära rootori asendi. Signaali perioodiks on 20 ms (sagedus 50 Hz) ja kõrge poolperioodi laiuseks 1-2 ms. 1 ms tähistab rootori üht ää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.

 

Praktika

Kodulabori Mootorite mooduli plaadil on kaks pistikut RC servomootorite ühendamiseks. Pistikute PWM signaali otsad on ühendatud mikrokontrolleri PB5 ja PB6 viikudega, mille alternatiivfunktsioonideks on 16-bitise taimer 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 signaali 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 signaali 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 makrofunktsioonidega 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 genereeriv taimer tööle servomotor_init funktsiooniga. Servomootori asendi väärtus saadakse analoog-digitaalmuunduri kanalist 3, kuhu on Andurite mooduli 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. Täpseks liigutuseks tuleb rakendustes PWM poolperioodi laius siiski katse- ja eksitusmeetodil määrata. Ka raadiojuhitavate mudelite pultidel on täpseks seadistuseks vastavad võimalused (inglise keeles trim). Programmi käivitades muutub vastavalt potentsiomeetri asendile ka servomootori võlli 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);
	}
}

Samm-mootor

Vajalikud teadmised: [HW] Mootorite moodul, [AVR] Digitaalsed sisendid-väljundid,
[LIB] Mootorid, [LIB] Viide

Teooria

Invalid Link
Samm-mootor

Samm-mootoreid kasutatakse laialdaselt täpsust nõudvates rakendustes. Erinevalt alalisvoolumootorist puuduvad samm-mootoris harjad ja kommutaator - selleks on seal mitu eraldiseisvat mähist, mida kommuteeritakse välise elektroonikaga (ajuriga). 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 (suur täpsus, madal pöördemoment, madal hind)
  • püsimagnetiga (madal täpsus, kõrge pöördemoment, madal hind)
  • hübriidne (suur täpsus, kõrge pöördemoment, kõrge hind)

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 mootori võ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

Unipolaarse samm-mootori mähised

Unipolaarne samm-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 ainult maaga, mistõttu nende juhtelektroonika on suhteliselt lihtne.

Bipolaarne samm-mootor

Bipolaarse samm-mootori mähised

Bipolaarne samm-mootor erineb unipolaarsest samm-mootorist selle poolest, et mähiste polaarsust muudetakse kommutatsiooni ajal. Korraga aktiveeritakse pooled mähised, mis tagab võrreldes unipolaarse samm-mootoritega suurema efektiivsuse. Bipolaarsetel samm-mootoritel on neli juhet, mis ühendatakse kõik eraldi poolsillaga. Kommuteerimisel rakendavad poolsillad mähiste otstele kas positiivset või negatiivset pinget. Unipolaarseid samm-mootoreid saab käivitada ka bipolaarse ajuri abil: selleks tuleb ühendada vaid 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. Kuna unipolaarsete samm-mootorite ajurite puhul toimub vaid transistoride avamine, siis nende samme on kujutatud loogiliste arvudega 0 ja 1. Bipolaarse samm-mootori juhtimine võib vajada rohkem signaale, ja selle samme on kujutatud ajuri väljundite polaarsusega.

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 + - - +

Praktika

Harjutuse eesmärk on tööle panna bipolaarne samm-mootor, mille asemel saab eespool nimetatud meetodil kasutada ka unipolaarset samm-mootorit. Mootorite mooduli plaadil on olemas kaks ajurit L293D, mida tuleb mikrokontrollerist 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.

Bipolaarse samm-mootori juhtimiseks on Kodulabori teegis olemas funktsioon bipolar_init, mis seadistab viigud väljundiks ja funktsioon bipolar_halfstep, mis teostab pöörlemist määratud arvu poolsammude võrra. Kommuteerimine toimub poolsammude tabeli järgi, mille tekitamiseks 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);
	}
}

Harjutusülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Alalisvoolumootori juhtimine Digitaalmooduli plaadi nuppudega. Vajutades nupule S1 pöörleb mootor päripäeva. Vajutades nupule S3 pöörleb mootor vastupäeva. Vajutades nupule S2 mootor seisab.

Algajale

  1. Alalisvoolumootori juhtimine. Simuleeritakse alalisvoolumootori ja puuteandurite kasutamisega roboti liikumist. Puuteanduriteks on Digitaalmooduli nupud S1, S2 ja S3. Mootorit juhitakse nuppude allavajutamisega. S1 ja S2 eraldi vajutamisel peatab mootori kaheks sekundiks ning seejärel käivitab mootor uuesti. Kui mõlemad nupud on samaaegselt alla vajutatud, siis mootor seisab kuni nuppude vabastamiseni. (Robotil tuleks rakendada sarnast skeemi kahe eraldi mootori juhtimiseks).
  2. Servomootor. Servomootorit juhitakse Digitaalmooduli plaadi nuppude abil. S1 allavajutamisel pöörleb servomootori hoob ühe sammu võrra vasakule, S3 allavajutamisel pöörleb servomootori hoob ühe sammu võrra paremale ning S2 allavajutamisel liigub hoob algasendisse (keskmine positsioon). Servomootori hoova asendit näidatakse sammudena 7-segmendilisel indikaatoril (keskmine asend on number 5).
  3. Radar. Simuleeritakse infrapuna kaugusanduriga radari tööd. Andur tuleb paigaldada servomootori hoovale. Servomootori hoob koos anduriga liigub pidevalt ühest äärmisest asendist teise. Kui andurist lähemale kui 0,5 m ilmub objekt, peatatakse servomootor 5 sekundiks ning Kontrollermooduli plaadil oleva LED-i (PB7) abil antakse märku, et objekt on leitud. Peale 5 sekundilist LED-i vilgutamist jätkatakse skaneerimist.
  4. Samm-mootor. Samm-mootor pöörleb iga nupule S1 ja S3 vajutamise järel 50 sammu, vastavalt päri- või vastupäeva. Nupp S2 katkestab pöörlemise viivitamatult.
  5. Ühendatud on kõik kolm eri tüüpi mootorit. Nupule vajutus käivitab ja peatab vastava mootori. S1 juhib alalisvoolumootorit, S2 servomootorit ja S3 samm-mootorit.

Edasijõudnule

  1. Alalisvoolumootor kiirendab S1 nupu allavajutamisel ning hoiab S1 nupu vabastamisel saavutatud kiirust. S2 nupu allavajutatud asendis hoidmise ajal mootor aeglustub sujuvalt. S3 allavajutamisel peatub mootor viivitamatult. Erineva kiiruse saab genereerides pulsilaiusmodulatsiooni signaali.
  2. Objekti jälgimine. Kasutades ultraheli kaugusandurit, mis on paigaldatud servomootori hoovale, peab servomootor jälgima mööduvat objekti. Mootor pöörab vastavalt objekti liikumisele nii, et objekt oleks kogu aeg anduri vaatevälja keskel.
  3. Samm-mootoriga teha analoogkella sekundiosuti. Mootor peab ühe täispöördega täpselt 60 sammu tegema. Liikumine peab olema astmeline mitte sujuv. Kasutada tuleb pool- või mikrosammu.
  4. Kiirendav samm-mootor. Programm võimaldab muuta samm-mootori kiirendamist/aeglustamist. Kasutage lineaarseid kiirusekaldeid, mida saab visuaalseks ülevaatuseks lihtsalt tuvastada. Pikemad liikumised peavad toimuma järgmise skeemi järgi: kiirendamine → püsiv kiirus → aeglustamine.
  5. Koostage alalisvoolumootorile PID regulaator. NB! Harjutus vajab tagasisidega mootorit. Ülesande võib lahendada ka teoreetiliselt.

 

Kordamisküsimused

  1. Milleks kasutatakse H-silda? Milline on selle tööprintsiip?
  2. Kuidas on määratud RC servomootori võlli asend?
  3. Milline on põhierinevus uni- ja bipolaarsete samm-mootorite vahel?
  4. Kuidas rakendada samm-mootoris poolsamm- ja mikrosamm režiime?
  5. Kuidas juhitakse alalisvoolumootori pöörlemiskiirust?
  6. Millist pulsilaiusmodulatsiooni (PWM) töötsüklit on vaja, et saavutada alalisvoolumootori võlli pöörlemiskiiruseks 70% nominaalsest pöörlemiskiirusest?
  7. Kuidas määratakse koodri kasutamisel mootori pöörlemissuund?
  8. Kuidas saab alalisvoolumootorit elektriliselt pidurdada?
  9. Mis juhtub, kui samm-mootori puhul on kommutatsioon liiga kiire?
  10. Kas ja kuidas on võimalik kasutada dünaamilist pidurdamist?

Sideliidesed

Sideliidesed

Mikrokontrolleritega saab juhtida täitureid, lugeda andurite väärtusi ja teha 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 seadme juhtimiseks vajaminevate juhtsignaalide liiga suur arv või suur andmehulk. Seepärast on nii mikrokontrolleritele kui muule elektroonikale 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 vahel 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.

RS-232

Vajalikud teadmised: [HW] Kontrollermoodul, [AVR] USART, [LIB] Jadaliides,
[LIB] Alfabeetiline LCD

Teooria

RS-232 kaabel. Vasakpoolne pistik on “isa-tüüpi”, parempoolne “ema-tüüpi”

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 nime kandva riistvaralise andmesidemooduliga, millel on protokoll standardiseeritud, kuid mis jällegi ei määra ära pistikuid jms. Seega RS-232 täiendab UART-i. Kuna UART on enamasti üks perifeeriamoodul mikrokontrolleris, mille digitaalsed sisendid-väljundid ei vasta RS-232 elektrilistele parameetritele, siis omavahel viiakse need kokku spetsiaalsete nivoomuunduritega. Üks tuntumaid RS-232 ja TTL/CMOS vahelisi 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, 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. Kui andmeid liigutatakse kahel liinil samaaegselt on tegu täisdupleks-siiniga.

UART kaader, kus S on startbitt, 0-7 andmebitid, P paarsuse bitt (olemasolul) ja T stoppbitt (või 2)

Andmete edastamine toimub UART liideses kaadri (inglise keeles frame) kaupa, milles on andmebitte olenevalt seadistusest 5 kuni 9. Enamlevinud andmehulk on siiski 8 bitti, ehk 1 bait. Peale andmebittide edastatakse 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. Paarsuse 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 (inglise keeles 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 andmevoo-kontrolli 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 originaaleesmärk oli ühendada arvuteid modemiga, siis mõned signaalid on (pigem olid) kasutusel telefoniliini seisundi näitamiseks.

Praktika

Kodulabori Kontrollermooduli plaadil 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_write_string("Ootan teadet");
 
	// Kursori teise rea algusesse viimine
	lcd_alpha_goto_xy(0, row);
 
	// Arvutile tere ütlemine
	usart_send_string(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_clear_line(row);
			}
			else
			{
				// Märgi otse ekraanile väljastamine
				lcd_alpha_write_char(c);
			}
		}
	}
}
HyperTerminal aken

Windows XP operatsioonisüsteemiga on kaasas programm HyperTerminal. See avaneb Start menüüst Accessories → Communications → HyperTerminal valides. Ühenduse seadeteks valida 9600 bps, 1 start- ja 1 stoppbitt ilma paarsuse- ja vookontrollita. Kui HyperTerminal on avatud mikrokontrolleri tööle panemise ajal, tekib ekraanile tervitussõnum. Aknas sisestatud tähed kuvatakse aga alfabeetilise LCD ekraanil. Klahvi Enter vajutus muudab rida LCD ekraanil.

Harjutusülesanded

Eesmärgiks on koostada programm, mis täidab kirjeldatud ülesannet.

Soojendusülesanne

  • Saadetakse arvutile kord sekundis järjest suurenevat numbrit. Number peab olema teksti kujul ja lõppema reavahetusmärgiga (\n).

Algajale

  1. Oodatakse arvutilt RS-232 liidese kaudu käsklusi (tähemärke). Käsk 'R' süütab rohelise LED-i, 'K' süütab kollase LED-i, 'P' punase LED-i ja 'S' kustutab kõik LED-id.
  2. Nupule vajutades saadetakse arvutisse RS-232 liidese kaudu vastava nupu nimi (S1, S2, S3).

Edasijõudnule

  1. Kahe Kontrollermooduli RS-232 vaheline suhtlus. Nupule vajutades saadab kontroller nupu numbri. Numbri saabumisel muudetakse vastava LED-i olekut. '1' → roheline, '2' → kollane, '3' → punane. Ülesanne vajab kahte Kontrollermoodulit ja Digitaalmoodulit, kuid tarkvara on mõlemas kontrolleris identne.
  2. Teha “teletype”-seade, mis võimaldab kahe kontrolleri vahel RS-232 liidese kaudu vahetada tekstisõnumeid. Sõnumite kuvamiseks kasutada LCD ekraani, mille esimesel real on näha oma sisestatavat sõnumit, teisel viimane vastuvõetud sõnum. Sõnumi sisestamiseks võib kasutada potentsiomeetrit ja/või nuppe.

Kordamisküsimused

  1. Kirjelda UART kaadrit.
  2. Mis asi on boodikiirus?
  3. Mis vahe on täis- ja poolduplekssidel?
  4. Leida vähemalt 3 erinevat andurit, mis kasutavad jadaliidest.
  5. Mis vahe on UART ja USART liidestel? Kumb on kiirem?
  6. Kuidas töötab SPI liides?
  7. Nimetage liideseid, mis võimaldavad ühele siinile ühendada vähemalt 100 seadet.
  8. Loetlege erinevaid topoloogiaid ja selgitage nende erinevusi.
  9. Mis pingenivool toimivad RS-232 ja UART ühendused?
  10. Kui palju aega kulub 1 MiB edastamiseks boodikiirusel 9600 bps, kui andmebitte on 8, stoppbitte 1 ja paarsuse kontroll puudub?

Näidisprojekt

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 ühe tüüpilise projekti dokumentatsioon. 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.

Dokumentatsioon

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:

  • Tiitelleht
  • Lühikokkuvõte
  • Lühikokkuvõte (võõrkeeles)
  • Sisukord
    1. Lähteülesanne
    2. Nõuded ja piirangud süsteemile
    3. Süsteemi üldine mudel
      Süsteemi struktuuri ja funktsionaalsuse mudelid plokkdiagrammidena. Lisaks võib koostada kasutusjuhtude diagrammi, liideste diagrammi jms.
    4. Ideelahendused
      Vähemalt kolm erinevat kontseptuaalset lahendust, kuidas antud ülesanne lahendada. Sobivad täiesti skaneeritud käsitsi visandatud skeemid, visandid jms. dokumentatsioon koos kommentaaridega.
    5. Mehaanika
      Soovitatavalt 3D mudel koos oluliste sõlmede tööjooniste ja valmistamisjuhistega. Kui mingi sõlm nõuab erijuhiseid koostamiseks, siis ka koostejoonis ja juhendid, võimaluse korral animatsioon süsteemi toimimisest.
    6. Elektroonika
      Üldine plokkskeem, kus on näidatud kasutatavad moodulid (nn. kontroller, mootori ajur, mootor, kooder jne., ning nendevahelised ühendused). Võimalusel standardne elektroonikaskeem ja trükkplaadi montaažiskeem.
    7. Juhtimine
      Juhtimise algoritm ja algkood. Kui on kasutatud omaloodud funktsioone, siis ka funktsioonide ja parameetrite tabel, katkestuste prioriteetide tabel jms.
    8. Valmislahendus
      Kirjeldus ja pildid
    9. Majanduskalkulatsioonid
      Komponentide nimekiri koos maksumusega, tööaja kalkulatsioonid jms.
    10. Projektijuhtimine
      Projekti ajakava, ressursside jaotus, tööjaotus, meeskonnaliikmete panus, koosolekute protokollid jms.
    11. Kokkuvõte ja järeldused
      Mis oli keeruline, mida teeks edaspidi teisiti, mida projekt andis jne. Kokkuvõttes kirjeldatakse lühidalt tehtud tööd, esinenud probleeme ja lõpptulemuse kirjeldust. Samuti on kokkuvõttesse hea lisada oma arvamus projekti vajalikkusest, mida see annab projekti liikmele, mida teeks tulevikus teisiti, mida õpiti ja mida soovitatakse juhendajale ja projekti korraldajatele.
  • Viited ja kasutatud materjal
  • Lisad

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.

Liikurroboti platvorm

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 eemalhoidmist 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 dokumentatsiooni ja selle projekteerimise erinevaid etappe.

Lähteülesanne

Projekteerida ja valmistada Kodulabori komponentide baasil multifunktsionaalne liikurroboti platvorm koos baasnavigatsiooni funktsionaalsusega. Robotplatvorm peab võimaldama lihtsalt muuta tema operatiivfunktsionaalsust, varustades teda erinevate seadmetega:

  • Manipulaator
  • Radar
  • Kaamera

Robot peab olema võimeline liikuma tasasel pinnal sisetingimustes.

Nõuded
  • Maksimaalsed gabariidid: 20 cm x 20 cm x 20 cm
  • Maksimaalne kaal 2 kg
  • Liikumiskiirus max. 0,2 m/s
  • Täisautonoomne
Piirangud projekteerimisele
  • Peab olema koostatud valdavalt Kodulabori komponentidest
  • Ei tohi ületada maksumust 10 000 krooni

 

Süsteemi üldine mudel

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.

Süsteemi struktuuri mudel

Ideelahendused

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.

Ideekavandid

 

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) 1927 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

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.

Algne 3D mudel robotist ja selle komponentide omavahelistest paiknemisest

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.

Põrkeraua plaadi tööjoonis

Elektroonika

Süsteemi elektroonika on kirjeldatud põhimõttelahendusena ja klassikalise elektriskeemina koos trükiplaadi montaažiskeemina.

Elektroonikakomponentide plokkskeem

 

Näitena on toodud roboti põrkeraua joonejälgimise andurite elektriskeem ja vastava trükiplaadi (PCB) montaažiskeemiga.

Põrkeraua andurite elektriskeem
Põrkeraua montaažiskeem

 

Juhtimine

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

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 juba suhteliselt lihtne koostada. Algoritmis on kasutatud põhiliselt kahte erinevat objekti: ümardatud nurkadega ristkülik, mis tähistab mingit tegevust ja väike romb mingi tingimuse kontrollimiseks, millele järgneb vastavalt kontrolli tulemusena edasiste tegevuste käivitamine.

Algoritmis kasutatud tähiste tähendused:

TähisTähendus01-1
M1vasak mootorseisabpöörleb päripäevapöörleb vastupäeva
M2parem mootorseisabpöörleb päripäevapöörleb vastupäeva
Fesimene keskmine puuteandursignaal puudubsignaal olemas
FResimene parem puuteandursignaal puudubsignaal olemas
FLesimene vasak puuteandursignaal puudubsignaal olemas
dviide
Algoritmi olekudiagramm
Lähtekood

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);
 
	// Andurite viigud sisendiks
	pin_setup_input_with_pullup(front);
	pin_setup_input_with_pullup(frontleft);
	pin_setup_input_with_pullup(frontright);
 
	// Lõputu tsükkel
	while (true)
	{
		// Mootorite päripäeva käivitamine
		dcmotor_drive(0, 1);
		dcmotor_drive(1, 1);
 
		// 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(0, 1);
 
			// Paus 2 sekundit
			sw_delay_ms(2000);
		}
 
		// Vasaku anduri signaali kontroll
		else if (pin_get_value(frontleft))
		{
			// Parema mootori reverseerimine
			dcmotor_drive(1, -1);
 
			// Paus 2 sekundit
			sw_delay_ms(2000);
		}
 
		// Parema anduri signaali kontroll
		else if (pin_get_value(frontright))
		{
			// Vasaku mootori reverseerimine
			dcmotor_drive(0, -1);
 
			// Paus 2 sekundit
			sw_delay_ms(2000);
		}
	}
}

 

Valmislahendus

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. Teise lahendusena paigaldati platvormile intelligentne kaameramoodul masinnägemise ülesannete lahendamiseks. Mõlemad variandid on näidatud allolevatel piltidel. Kolmandaks seadmeks katsetati standardmanipulaatorit, mille lülisid juhitakse samuti standardsete RC servomootoritega, kasutades nende ajuri juhtimiseks jadaliidest.

Robot infrapuna radariga
Robot intelligentse kaameramooduliga (CMUcam3)

 

Majanduskalkulatsioon

Majanduslik kalkulatsioon hõlmab endas komponentide maksumust ja roboti detailide valmistamise ning koostamise kulusid.

Komponentide maksumuse tabel

KomponentMarkKogusHindMaksumus
MootorM LE149.6.432500.-1000.-
MikrokontrolleruC ATmega1281900.-900.-
Mootorite juhtplaatActuator Board v1.21700.-700.-
ToiteplaatTP1500.-500.-
Joonejälgimise anduridLFS QRD1114830.-240.-
PuuteanduridTS Microswitch825.-200.-
Kere plaatABS 450.-200.-
Trükiplaadi toorik 250.-100.-
Mootorikinnituse profiilAl-L 210.-20.-
Ratas60/10 mm 230.-60.-
AkuNI-MH 9,6 V1350.-350.-
Erinevad kaablid 1020.-200.-
Mutrid-poldid 150.-50.-
Muud tarvikud 1100.-100.-
Kokku 4620.-

Hinnanguline tööjõu- ja tootmiskulu üksikeksemplari korral.

TööAeg (h)HindMaksumus
Konstruktsioonidetailide freesimine1300.-300.-
Trükiplaatide (põrkerauad) freesimine0,5500.-250.-
Roboti konstruktsiooni koostamine0,5250.-125.-
Põrkeraudade koostamine (komponentide jootmine)1300.-300.-
Programmeerimine5300.-1500.-
Dokumentatsiooni koostamine3250.-750.-
Kokku 11 3225.-

Roboti hinnanguline maksumus kokku 7845.-

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.

Projektijuhtimine

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.

Projekti tegevusdiagramm

Kokkuvõte ja järeldused

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.

Viited ja kasutatud materjalid

  1. Kodulabori juhendmaterjal http://home.roboticlab.eu
  2. ATmega128 andmeleht
  3. Dudziak, R., Köhn, C., Sell, R., Integrated Systems & Design, TUT Press, 2008
  4. Friendenthal, S., Moore, A., Steiner, A., A Practical Guide to SysML, Elsevier, 2008
  5. Perens, A. Projektijuhtimine, Külim, 1999
  6. Bräunl, T. Embedded Robotics, Springer-Verlag, 2003

Mis edasi?

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 Robot 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 või 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. Peale infomaterjalide leiab veebist ka kasutajafoorumi, kus saad kindlasti vastused oma tekkinud 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 ning andke administraatorile märku, et olete õpetaja. Siis saate juurdepääsu harjutusülesannete lahendustele ja kordamisküsimuste vastustele ;)

Veebikeskkond asub aadressil
http://www.roboticlab.eu

MÄRKUSED

 

info@ittgroup.ee

Mikrokontrollerite arendusplaadid, andurid ja programmaatorid –
KÕIK VAJALIK HOBIROBOOTIKAKS e-poest http://pood.ittgroup.ee

Arduino, Mikrovega, Devantech Ltd (Robot Electronics) ametlik esindaja Eestis.

et/book.1266837969.txt.gz · Last modified: 2020/07/20 09:00 (external edit)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0