Arduino programmeerimiskeeles on kohustuslikud funktsioonid setup() ja loop(), mis peavad alati eksisteerima, et kood kompileeruks. Esimest neist läbitakse vaid ühe korra ja on mõeldud üldjuhul seadistuste tegemiseks. Teist funktsiooni kutsutakse välja pidevalt ehk tegemist on lõpmatu tsükliga.
Näide Arduino programmi struktuurist:
/* Programmi selgitav kommentaar ja autor */ // Makro-deklaratsioonid #define PI 3.141 // Globaalsed muutujad int e; // Seadistuste funktsioon void setup() { // Funktsiooni läbitakse vaid ühe korra } // Peatsükkel void loop() { // Funktsiooni täidetakse korduvalt, // Tavaliselt on siin programmi põhitegevused }
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äited kahte liiki kommentaarist:
// Üherealine kommentaar // Kommentaariks loetakse kahe kaldkriipsu järel olevat teksti /* Mitmerealine kommentaar Kommentaari algus ja lõpp määratakse kaldkriipsude ja tärnidega */
Muutujad ja konstandid on erinevate andmete hoidmiseks defineeritavad mälupesad. Muutujatele saab programmi täitmise ajal omistada erinevaid ühte tüüpi väärtusi, konstantidele omistatakse kindel väärtus ühe korra ja seda programmi täitmise ajal enam ei muudeta.
Arduino programmeerimiskeele baasandmetüübid (enamus neist on täisarvud, kaks viimast on ujukomaarvud):
Tüüp | Miinimum | Maksimum | Bitte |
---|---|---|---|
boolean | false(0) | true(1-255) | 8 |
byte | 0 | 255 | 8 |
(signed) char | -128 | 127 | 8 |
unsigned char | 0 | 255 | 8 |
(signed) int | -32768 | 32767 | 16 |
unsigned int | 0 | 65535 | 16 |
(signed) long | -2 147 483 648 | 2 147 483 647 | 32 |
unsigned long | 0 | 4 294 967 295 | 32 |
float | -3.438 | 3.438 | 32 |
double | -1.7308 | 1.7308 | 64 |
Sulgudes olevat sõna signed ei pea kasutama, kuna vaikimisi on andmetüübid bipolaarsed. Arduino programmeerimiskeeles on teksti hoidmiseks String objekt, mis lubab teha erinevaid tekstitöötluse toiminguid: teksti lisamine ja eemaldamine, võrdlus ning toimingud tähemärkide kaupa.
Konstante saab tekitada kahel viisil:
Muutujate deklareerimisel ehk loomisel peab olema vähemalt 2 elementi: andmetüüp ja nimi. Muutuja deklareerimisel on võimalik see kohe ka algväärtustada ehk defineerida. Muutuja deklareerimisel väljaspool funktsiooni on tegemist globaalse muutujaga ja sellele pääsevad ligi kõik funktsioonid. Globaalsete muutujate väärtused säilivad kuni mikrokontrollerilt toite eemaldamiseni. Muutuja deklareerimisel funktsiooni sees on see kasutatav vaid selles kindlas funktsioonis ja pärast funktsiooni sulgemist kustutatakse kõik lokaalsed muutujad mälust.
Muutuja nime valikul kehtivad reeglid:
Soovitused muutujate deklareerimisel:
Näited muutujate deklareerimisest ja defineerimisest:
// Char tüüpi muutuja deklareerimine char c; // Char defineerimine numbriga 65, mis vastab ascii tabeli järgi tähemärgile A c = 65; // Char defineerimine tähemärgiga A // Tähemärkide kasutamisel programmis tuleb need ümbritseda ülakomade vahele c = 'A'; /* String objekti loomine ja teksti omistamine. Rohkem kui ühe tähemärgilise teksti kasutamisel programmis tuleb see ümbritseda jutumärkide vahele. */ String tervitus = "Hello World"; // Konstandi deklareerimine ja väärtuse omistamine const int kalibratsiooniKonstant = 187; // Mitu ühte tüüpi muutujat saab deklareerida ühel real unsigned long x, kahvel, test_systeem, toiteLED;
Arduino programmeerimiskeeles toetatud aritmeetilised tehted on liitmine (+), lahutamine (-), korrutamine (*), jagamine (/) ja mooduli võtmine (%). Keerukamate tehete koostamisel tuleb järgida tehete järjekorda. Tehted sooritatakse suunaga vasakult paremale. Esmalt tehakse * / % ja seejärel + -. Kui on vaja mingeid tehteid eelisjärjekorras teha, siis selleks kasutada sulge.
Näited aritmeetiliste tehete kasutamisest:
/* Esimesena tehakse liitmine kuna see on sulgudes, järgmisena korrutamine ning siis jagamine, x saab väärtuse 16. */ int x = 8 * (1 + 7) / 4; // Liitev-omistav operaator, x väärtuseks saab 21, lahti kirjutatud: x=x+5 x += 5; // Ühe lahutamise kiirmeetod, x väärtuseks saab 20, lahti kirjutatud: x=x-1 x--;
Loogilised tehted on eitus (!), loogiline korrutamine (&&) ja loogiline liitmine (||). Kui kasutada koos erinevaid loogikatehteid siis täidetakse esmalt eitus ja seejärel vasakult paremale järjekorras loogiline liitmine ja korrutamine. Samuti võib kindla tehte eelistamiseks kasutada sulge.
Näited tehete kasutamisest:
// Toome näite kahe toa kliima parameetri kasutamisest toa tuulutuse juhtimiseks // Kui muutuja 'tuulutus' on tõene, siis lülitatakse ventilaator sisse boolean niiske, palav, tuulutus; // Algväärtustame kliima parameetrid niiske = true; palav = true; /* Eitus Muutuja palav saab eituse tulemusena vääraks ja see väärtus omistatakse samale muutujale. */ palav = !palav; /* Loogiline korrutamine Ventilaator lülitatakse sisse ainult siis, kui toas on niiske ja palav parameetrite hetkeväärtuste puhul ventilaatorit sisse ei lülitata, kuna toas ei ole palav (eelneva tehtega eitasime muutuja 'palav'). */ tuulutus = niiske && palav; // Loogiline liitmine // Ventilaator lülitatakse sisse, kui toas on niiske, palav või mõlemad korraga. tuulutus = niiske || palav; /* Esmalt teostatakse eitus, siis loogiline liitmine ning loogiline korrutamine. Ventilaator lülitatakse sisse ainult siis, kui üks parameetritest on tõene ja ventilaator veel ei tööta. */ tuulutus = niiske || palav && !tuulutus
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 (< .
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 // Tehte tulemus on väär, sest esimene loogilise korrutise operand on väär b = (x + 4 > 15) && (y < 4);
Tingimuslause võimaldab vastavalt sulgudes oleva loogikaavaldise tõesusele täita või mitte täita tingimusele järgnevat lauset või programmilõiku. Tingimuslause võtmesõna on if. 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.
Tingimuslauseid võib moodustada lühemaid ja pikemaid:
Tõese avaldise korral täidab määratud tegevuse.
Kui avaldis ei ole tõene siis täidetakse else ehk muu juhu tegevus.
Kui esimene avaldis ei kehtinud, siis kontrollib järgnevaid ning kui ükski ei olnud tõene, siis täidab muu juhu tegevuse.
Näide tingimuslause ülesehitusest:
// Kõigi kolme elemendiga if lause struktuur if(andur1 == 1 && andur2 == 1){ // Tee midagi } else if(andur1 == 1 || andur2 == 1){ // Tee midagi muud } else if(andur3 != 0){ // Tee midagi muud } else{ // Kui ükski eelnev lause ei olnud tõene, siis tee seda osa }
Tsüklid võimaldavad ühte tegevust või programmilõiku täita mitu korda järjest. Peamised tsüklite tüübid on for ja while.
Tsüklit korratakse, kuni võrdlus annab tulemuseks tõene.
for(int i=0; i<10; i++){ x++; }
Tsüklit korratakse, kuni avaldis on tõene.
// While tsüklit täidetakse, kuni i väärtus on suurem kui 9 int i = 0; while(i < 10){ i++; } // While tsüklit täidetakse, kuni muutuja 'lipp' on võrdne nulliga int i = 0; int lipp = 0; while(lipp == 0){ i++; if(i > 10) lipp = 1; }
Tsüklis liikumine
Tsüklites on võimalik käimasoleva tsükli mõjutamiseks kasutada käske break ja continue.
/* Tsüklis suurendatakse muutujat loendur. Osadel juhtudel kasutatakse käsku continue, mis sunnib programmi alustama uue tsükliga. Seega loenduri suurendamine jääb kolmel juhul vahele. */ int loendur = 0; for(int i=10; i>=0; i--){ if(i==2 || i==4 || i==8) continue; loendur++; } // Lõputus tsüklis suurendatakse i väärtust. // Kui i väärtus on võrdne 10-ga, siis väljutakse tsüklist. int i = 0; while(1){ i++; if(i == 10) break; }
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. Funktsioon peab olema deklareeritud väljaspool teisi funktsioone ehk enne või pärast loop funktsiooni.
Näited funktsioonidest:
int x; int y = 3; void setup() {} void loop() { // Liitmisfunktsioon, kus parameetriteks on muutuja ja konstandi väärtus x = sum(y, 5); // Väljalülitamise funktsiooni väljakutsumine, parameetrid puuduvad power_off(); } // Kahe int tüüpi parameetriga funktsioon, mis 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) {}
Arduino programmeerimiseks on juba defineeritud hulk erinevaid funktsioone. Need ei ole standard C keele käsud vaid spetsiaalselt Arduino riistvara jaoks loodud funktsioonid. Kõige olulisemad ja vältimatult mikrokontrollerite programmide jaoks vajalikud on viikude juhtimise funktsioonid. Enne viikude kasutamist tuleb määrata nende töörežiim. Esmalt on vaja määrata, kas viik hakkab tööle sisendina või väljundina. Kui viik peaks töötama sisendina on vaja otsustada, kas aktiveerida sisemine pull-up takisti.
Viigu seadistamine:
Viigu oleku lugemine:
Viigu oleku muutmine:
Näited:
// Tavalise lüliti väärtuse lugemine const int nupp = 12; void setup() { pinMode(nupp, INPUT_PULLUP); } void loop(){ if(digitalRead(nupp) == 0){ // Nupu vajutusel täidetav programmi osa } }
// Analoogväljundiga anduri lugemine const int andurAN = A0; void setup() { pinMode(andurAN, INPUT); } void loop(){ if(analogRead(andurAN) > 500){ // Kui anduri analoogsisendi väärtus on suurem kui 500, // siis täidetakse see programmi osa } }
// Digitaalse väljundi seadistamine ja oleku muutmine const int led = 13; void setup() { pinMode(led, OUTPUT); } void loop(){ digitalWrite(led, HIGH); // LED-i viigu kõrgeks seadistamine }
// Analoogväljundi (PWM signaali) seadistamine ja oleku muutmine const int led = 11; void setup() { pinMode(led, OUTPUT); } void loop(){ analogWrite(led, 180); // LED-i heleduse seadmine vahemikus 0-255 }
Programmi töös on tihti vaja teostada kindla ajastusega tegevusi. Selleks on Arduino-l olemas neli funktsiooni, millest esimesed 2 on viited ja ülejäänud 2 loendurid. Loenduritel on maksimaalne arv, mille saavutamisel ehk ületäitumisel (inglise keeles overflow) alustatakse lugemist taas 0-st.
// Loenduri tekitamine, mis loendab sekundeid int stopper = 0; void loop() { delay(1000); // Programm on 1000 millisekundit ehk 1 sekund siin kinni stopper++; // Muutujale ühe liitmine }
// Loenduri tekitamine, mis loendab millisekundeid int stopper = 0; void loop() { delayMicroseconds(1000); // Programm on 1000 mikrosekundit ehk 1 ms siin kinni stopper++; // Muutujale ühe liitmine }
// Loenduri tekitamine, mis loendab sekundeid unsigned long aeg = millis(); int stopper = 0; void loop() { // Pidev millisekundite arvu võrdlemine eelneva millisekundite arvuga // Kui kahe arvu vahe on suurem kui 1000,siis suurendame muutujat stopper ühe võrra if((long)(millis() - aeg) > 1000){ stopper++; // Muutujale ühe liitmine aeg = millis(); // Millisekundite arvu salvestamine muutujasse } // Programm saab muul ajal vabalt joosta }
// Loenduri tekitamine, mis loendab millisekundeid unsigned long aeg = micros(); int stopper = 0; void loop() { // Pidev mikrosekundite arvu võrdlemine eelneva mikrosekundite arvuga // Kui kahe arvu vahe on suurem kui 1000, siis suurendame muutujat stopper 1 võrra if((long)(micros() - aeg) > 1000){ stopper++; // Liidame muutujale ühe aeg = micros(); // Millisekundite arvu salvestamine muutujasse } // Programm saab muul ajal vabalt joosta }
Kontrolleri programmeerimise lihtsustamiseks on riistvara tootjad ja/või vabatahtlikud loonud tarkvarateegid erinevate seadmete kasutamise. Tarkvarateegid on funktsioonide kogumid, mis on loodud riistvara lihtsamaks kasutamiseks ja haldamiseks. Nii on võimalik sisuliselt ühe käsureaga teha operatsioone, mis riistvara tasemel võivad nõuda lehekülgedepikkust koodi. Üldiselt on teegid ka paindlikud, mis tähendab, et üks teek võib toetada tervet tooteseeriat.
Mõned Arduino IDE-s vaikimisi olevad teegid:
Teeke võib ka ise koostada ja seda on mõttekas teha, kui on mingid funktsioonid, mida on soov läbi projektide korduvkasutada või on loodud mõni spetsiifiline riistvara, mille lihtsamaks kasutamiseks on mõistlik oma teek teha.
Uue teegi loomiseks võib alustada tavalisest Arduino programmist, kus on loodud soovitud funktsioonid. Teegiks vormistamise jaoks on vaja koostada vähemalt kaks faili: päisfail (.h laiendiga) ja koodi fail (.cpp laiendiga). Päisfailis on teegi definitsioonid, sisuliselt info, mis kirjeldab teegi koodis olevaid funktsioone ja koodifail, mis sisaldab reaalset funktsiooni sisu ja tegevusi. Päisfailis koondatakse funktsioonide kirjeldused koos parameetritega klassidesse. Funktsioonid võivad olla kas Public või Private tüüpi. Public tüüpi funktsioonid on mõeldud teegi kasutajale, Private tüüpi klassi saab kasutada aga ainult klassi siseselt. Iga klass sisaldab spetsiaalset construct tüüpi funktsiooni, mis loob klassi eksemplari. Construct tüüpi funktsioon on sama nimega, mis klass ise.
Teegi loomise täpsema juhendi leiab siit:
https://www.arduino.cc/en/Hacking/LibraryTutorial
Teegi loomise stiilinäite ja soovitused leiab siit:
https://www.arduino.cc/en/Reference/APIStyleGuide
Arduino IDE arenduskeskkonda on võimalik teeke lisada mitmel meetodil.