Tehted ja tehete järjekord
Matemaatika tehete järjekord on C keeles põhimõtteliselt sama, nagu matemaatika tunnis - korrustused jagamised kõigepealt, siis liitmised-lahutamised jne. Kasuta sulgusid, et tehete järjekord vajalikul viisil korrastada.
Tehete järjekorras kõige viimasena tehtav on omistamine (=). Muutujale saab uut väärtust omistada ka tehtena tema olemasolevast väärtusest. Näiteks:
result = result*2;
või
result = result + result / divider;
Võrdlusteheteks nimetatakse avaldist, mille tulemuseks on true (=1) või false (=0) ja kasutada saab järgnevaid märke:
== |
on võrdne |
|
!= |
ei ole võrdne |
|
< |
väiksem kui |
|
<= |
väiksem või võrdne |
|
> |
suurem kui |
|
>= |
suurem või võrdne |
|
Loogikatehteid saab teha true/false väärtustega ja need on järgmised:
! |
loogiline eitus - pmst väärtuse pööramine !true => false ja !false => true.
Näiteks
!digitalRead(2)
annab tulemuseks 0, siis kui digitalRead(2) parasjagu annab 1.
|
|
|| |
VÕI (ehk loogiline liitmine, OR) - kui üks VÕI-st ühel või teisel pool olev osa on true, siis on ka koguvastus true.
Näiteks
digitalRead(2) || digitalRead(3)
avaldise tulemused:
digitalRead(2) väärtus |
digitalRead(3) väärtus |
avaldise digitalRead(2) || digitalRead(3) väärtus |
|
0 |
0 |
0 |
|
1 |
0 |
1 |
|
0 |
1 |
1 |
|
1 |
1 |
1 |
|
|
|
&& |
JA (ehk loogiline korrutamine, AND) - annab tulemuseks true ainult siis, kui mõlemad JA-st ühel ja teisel pool olevad avaldised on true.
Näiteks
digitalRead(2) && digitalRead(3)
avaldise tulemused oleks:
digitalRead(2) väärtus |
digitalRead(3) väärtus |
avaldise digitalRead(2) && digitalRead(3) väärtus |
|
0 |
0 |
0 |
|
1 |
0 |
0 |
|
0 |
1 |
0 |
|
1 |
1 |
1 |
|
|
|
For korduslause
For korduslauset kasutatakse teadaoleva arvu korduste tegemiseks. For tahab sulgudesse kolme avaldist: loenduseks kasutatava muutuja algväärtus, jätkamise tingimus (mingi võrdlus loenduseks kasutatavast muutujaga) ja loenduseks kasutatava muutujaga iga korduse lõpus tehtav tehe. Lihtsaim ja kõige tihedamini tarvitatav on :
int i;
for (i=0; i<10; i++) {
...
}
i väärtuseks saab esimeses avaldises määratud täisarv, selles näites 0. Kui keskmise avaldise, siin i<10, tulemus on tõene, siis loogelistes sulgudes olev koodiblokk tehakse ära. Seejärel teostatakse kolmas tehe, praeguses näites i väärtust suurendatakse 1 võrra. Kui i uus väärtus ei muutunud veel keskmist võrdlust vääraks, siis minnakse uuele ringile.
Pane tähele, et for-i sulgudes kasutatav muutuja tuleb ka eelnevalt deklareerida.
Traditsiooniliselt kasutatakse loendusmuutuja nimena i tähte. Kui for-kordusi on üksteise sees mitu, siis jägmistele j, k jne tähestikust. i++ on lühivorm kirjutamaks “suurenda ühe võrra”, samaväärne käsuga i=i+1; Seda nimetatakse inkrement tehteks ja eksisteerib ka dekrement tehe nt i--, mis on samaväärne i=i-1;
Mõnel juhul on koodi lühiduse huvides kasulik nullist ühe kaupa mingi arvuni loendamise asemel kasutada muud loogikat for korduse loendamiseks - kui loenduse muutujat saab millekski muuks kasutada. Näiteks LEDi heleduse vähendamiseks 5 sammuna:
int brightness;
for (brightness = 255; brightness>0; brightness = brightness - 51) {
analogWrite(13, brightness);
delay(1000);
}
analogWrite(13, brightness);
//kui brightness sai väärtuseks 0, siis for sisu enam ei läbitud,
//et LED päriselt välja lülituks, mitte 51 peale ei jääks, on siin vaja veelkord analogWrite teha
Sama asja on võimalik saavutada eelpool kirjeldatud tavapärase lähenemisega, aga see nõuab rohkem koodiridu:
int i;
int brightness = 255;
for (i=0; i<5; i++) {
analogWrite(13, brightness);
delay(1000);
brightness=brightness - 51;
}
analogWrite(13, brightness);
While kordus
While kordus sarnaneb if lausega selle poolest, et sulgudesse pannakse üks avaldis, mille tõeväärtuse järgi otsustatakse, kas loogelistes sulgudes olevat koodi läbida või mitte. Kuid while sisemise koodiga lõpetamise järel kontrollitakse uuesti tingimust ja kui see on jätkuvalt tõene, siis korratakse. Tähendab järgneva koodini ei jõuta enne, kui while tingimus on vääraks muutunud.
While-i kasutatakse tihti selleks, et sisendist loetud tulemuse põhjal midagi teha, millegi järele oodata. Näiteks kui mootor liigutab kasvuhoone luuki ja seda, millal luuk on jõudnud täielikult lahtisesse asendisse, saab lugeda lüliti järgi:
int endSwitch = 4; //lõpu lüliti on ühendatud piniga 4
int motor = 6; //mootori relee ühendatud piniga 6
while ( !digitalRead(endSwitch) ) { //endSwitch näitab 0, kui luuk veel pole sinnani jõudnud, seetõttu “pöörame” väärtuse tõeseks !0 => 1
digitalWrite(motor, HIGH); //kuni nupu vajutust ei tuvasta, lülitame mootori sisse
}
digitalWrite(motor, LOW); //nupp sai vajutatud, seetõttu kordus lõppes. Lülitame mootori välja.
(See on lihtsustatud näide, kahte pidi töötaval - kinni ja lahti kerival mootoril tuleb tegelikult lülitada mitut releed H-bridge formatsioonis.)
Library-te kasutamine
Library on koodikogum, millega tehakse teatud tegevused lihtsasti kasutatavaks ja taaskasutatavaks (minu definitsioon). Arduinoga tegeledes vajad sa library-sid enamasti siis, kui kasutad mõnd elektroonikakomponenti või moodulit, millega suhtlemine on keerukam, kui ühe pini lugemine või kirjutamine. Aga ka korduvate käskude automaatseks ja nähtamatuks tegemine ning välja kirjutatavate käskude inimkeelsemaks tegemine võib olla mõne library point. Näiteks servo puhul on tegemist ühe pini ühendusega, aga library abiga saad anda inimesele loetavat käsku myServo.write(angle), selle asemel, et iga kord teha oma koodis arvutusi ja mitmeid koodiridu ajastuste paika saamiseks, millist PWM-i laadset signaali peab soovitud asendi saamiseks servole saatma.
IDE-ga on kaasas enamlevinud komponentide libraryd, näiteks servo, LiquidCrystal tüüpilisemate LCD-de jaoks … (ma jään nende nimetamisega hätta, sest mul endal on neid palju juurde installitud ja ei tea, millised olid kaasas…).
Enne komponendi hankimist guugelda, kuidas seda kasutatakse - kuidas ühendatakse, kas koodi poolest on keeruline, kas keerukuse vähendamiseks on library olemas. Näiteks LCD-sid on olemas suures valikus, aga nendega suhtlemine võib olla erinev ja osade puhul peaksid tegema ise meeletu programmeerimise töö, et toimima saada. Algajana vali selline, millele on Arduino library olemas.
Library installimiseks lae see alla, paki lahti. Selles kataloogis, kuhu IDE tahab asju salvestada (nimega Arduino või sketchbook, oleneb süsteemist) peaks olema alamkataloog libraries. Paiguta uue library kataloog sinna. Kontrolli, et kataloogi ja seal sees olevate .h ja .cpp failide nimed oleks samad. Githubist saadud libraryte kataloogi nimele on tavaliselt lisatud “-master”, mis tuleb ära kustutada, et asjad toimima saada. Taaskäivita IDE. File -> Examples menüüsse peaks olema ilmunud uue library nimi ja mõned näited. Uuri näidete koodi ja kasuta seda oma koodi kokkupanekuks.
Olulised osad Servo libra näitel on:
#include <Servo.h>
See peab paiknema põhimõtteliselt sketchi kõige alguses ja selle rea lõpus ei käi semikoolonit. Kui kasutad mitut libraryt, siis mõnikord on järjekord oluline, mõnikord mitte. Kui library kaasas olevas näites on mitu #include rida, siis arvatavast vajad neid kõiki.
Servo myservo;
See on objekti loomine, mis tuleb teha enne setupi. Siin annad sa oma komponendile nime (myservo) ja ütled, et ta on Servo library objekt.
myservo.attach(9);
Üks library meetod, rakendatuna sinu loodud objektile myservo. Konkreetselt siin antakse objektile teada, et ta peab 9-nda pini kaudu signaale välja saatma.
myservo.write(180);
Teine library meetod. Sellega ütled millisesse asendisse soovid servo keerata, nt 180 kraadi. myservo nime järgi saadetakse see signaal välja 9nda pini kaudu, sest eespool .attach() sidus nime myservo asukohaga 9.
Kui sul oleks mitu servot, siis peaksid tegema nii:
#include <Servo.h>
...
Servo myservo1;
Servo myservo2;
void setup() {
myservo1.attach(9);
myservo2.attach(10);
...
myservo1.write(180);
myservo2.write(90);
}
Kodune ülesanne
-
Ühenda Arduinoga servo (guugelda üle, kuidas see käib) ja üks nupp (pulldown või pullup takistiga koos muidugi). Leia Servo library näide nimega “sweep” ja tutvu sellega veidi, proovi see oma servoga tööle saada.
Kirjuta kood, kasutades while loopi ja if lauseid, mis teeb järgmist:
Kui nuppu ei vajutata, siis servo liigub rahuliku kiirusega vasakusse äärmisesse asendisse. Äärele jõudes jääb seisma - nullist väiksemaid ega 180-st suuremaid arve mitte servo asendiks kirjutada.
Kui nuppu vajutatakse, siis servo hakkab oma hetke asendist liikuma samasuguse rahuliku tempoga paremale poole. Äärde jõudes jääb sinna seisma. Ja eelnevast tulenevalt, kui nupp lahti lastakse, siis liigub hetke asendist uuesti vasakule.
-
Guugelda välja vajalik informatsioon ja ühenda arduinoga ultraheli kaugussensor HC-SR04. Kui libraryt nimega NewPing pole su IDEs, siis installi see. Proovi näite NewPingExample kood oma Arduino ja sensoriga tööle saada.*
Kirjuta kood, mis teeb järgmist:
Kui sensor tuvastab objekti 10cm ja 100cm vahepeal, siis hakka sisseheitatud 13. pini ledi sisse lülitama heledust tõstes nii aeglaselt, et seda mitme sekundi jooksul jälgida saab. Kasuta while lauset ja && tingimuste 10cm ja 100cm kontrollimiseks. Kui led jõuab täie heleduseni, siis jääb sellisena põlema, kuni kauguse tingimus on täidetud. Kui objekt lahkub vahemikust 10 ja 100cm vahel, siis vähenda ledi heledust alates sellest seisust, kus ta parasjagu oli, samuti rahuliku jälgitava tempoga.
* - NewPing näite koodis kasutatakse lauseid stiilis
#define TRIGGER_PIN 12
NewPing sonar(TRIGGER_PIN, ...
samahästi võid kasutada
int triggerPin = 12;
NewPing sonar(triggerPin, …
Erinevus on selles, et #define puhul pin ei ole muutuja ja salvestatakse teises mälu osas, mis mõnikord võib mälus ruumi optimeerimiseks vajalik olla. Aga hetkel muutuja kasutamine midagi katki ei teeks.