Sami-Petteri Pukkila sami-petteri.pukkila@aalto.fi 1. helmikuuta 2016
Ohjelman rakenne # include <math. h> / / Matemaattisia funktioita const i n t ledpin = 13; / / Merkkivalo i n t sensorpin = 4; / / Anturi bensatankissa void setup ( ) / / Suoritetaan vain kerran alussa / / I/O-porttien alustus pinmode ( ledpin, OUTPUT) ; pinmode ( sensorpin, INPUT ) ; void loop ( ) / / Suoritetaan kerta toisensa perään / / analogread palauttaa arvon välillä [0, 1023]. i n t gaslevel = analogread ( sensorpin ) ; i n t ledon = gaslevel < 300; / / LED sytytetään kun tankki lähes tyhjä d i g i t a l W r i t e ( ledpin, ledon ) ; 2
Funktiot "Maaginen laatikko" Voi ottaa vastaan määrätyn tyyppisiä muuttujia (parametrit) Tekee sisäisesti jotakin Voi palauttaa määrätyn tyyppisen paluuarvon. (tai void, jos ei mitään) 3
Funktiot int laskeyhteen ( int numero1, int numero2 ) return numero1 + numero2 ; int a = laskeyhteen (1, 2); // a==3 Parametrien muokkaus funktion sisällä ei vaikuta alkuperäisiin muuttujiin! 4
Muuttujat <tyyppi> <nimi> = <arvo>; Jokainen muuttuja on jonkin tyyppinen (kokonaisluku, kirjain,...) Vrt. esim Python, missä muuttujalla on vain nimi ja arvo Mikäli muuttujalle ei luomishetkellä anneta arvoa, se voi olla mitä tahansa int muuttuja; Muuttujan arvon ei voida olettaa olevan nolla! 5
Muuttujien näkyvyys int koira = 1; void setup () int kissa = koira + 2; // T o i m i i void loop () kissa = koira + 2; // Ei toimi, kissa näkyy // vain setup-funktiossa 6
Globaali vs lokaali muuttuja Globaali (esimerkissä koira) Voidaan käyttää kaikkialla ohjelmassa Hyviä kun samaa muuttujaa käytetään kaikkialla ohjelmassa. Esim. Arduinoon kytketyn ledin pinninumero Vältä mikäli mahdollista. Hankala tutkia mitkä kaikki ohjelman osat vaikuttavat muuttujaan. Lokaali (esimerkissä kissa) Voi käyttää vain niiden aaltosulkeiden välissä jossa määritetty Laitteen tarvitsee säilöä tieto ainoastaan pienessä osassa ohjelmaa tehokkaampaa Vaikeampi tehdä mokia 7
Muuttujatyypit Kieli on vahvasti tyypitetty Jokaisen muuttujan tyyppi on siis määritelty luomisvaiheessa Tyyppi määrää: Millaisia arvoja muuttuja voi sisältää Mitä muuttujalla voi tehdä Paljonko muuttuja vie tilaa ohjelman muistissa 8
Muuttujatyyppejä void boolean (0, 1, true, false) char ( a, -128, 127) int (-32768... 32767) long (-2147483648... 2147483647) unsigned char (0.. 255) byte (0.. 255) unsigned int (0.. 65536) word (0.. 65536) unsigned long (0.. 4294967295) float (-3.4028e+38 to 3.4028e+38) double (toistaiseksi sama kuin float) jne. 9
Muuttujatyypit Kokonaisluku (int, long) int muuttuja = -4; Liukuluku (float, double) float muuttuja = 4.0; Arduinon tämän hetkisessä toteutuksessa float ja double käytännössä sama asia merkki (char) char muuttuja = a ; Vain ASCII-järjestelmän merkit Aakkoset ja numerot löytyvät, ääkköset eivät Totuusarvo (boolean) boolean muuttuja = true; Tosi (true) tai epätosi (false) false = 0, true jotakin muuta 10
Muuttujatyypit Lukuja voi merkata myös erilaisissa lukujärjestelmissä. Kannattaa myös huomata, että laskutoimituksissakin luvuilla on jokin tyyppi. 123 (kokonaisluku) 0267 (oktaali) 0b10100011 (binääri) 0xA3 (heksadesimaali) 7U (unsigned) 11L (long) 15UL (unsigned long) 12.3 (liukuluku) 3.4e3 (3.4 10 3 ) 11
Muuttujatyypit int kokonaisluku = 2; float muuttuja1 = 3/ kokonaisluku ; // 1 float muuttuja2 = 3.0/2.0; // 1. 5 float muuttuja3 = 3.0/( float ) kokonaisluku ; // 1. 5 (tyyppi)muuttuja-notaatio muuntaa muuttujan tyypin Muunnos isommasta tyypistä pienempään saattaa aiheuttaa ongelmia (long int) 12
Under-/overflow Mikäli muuttujan arvo menee muuttujatyypin alueen yli, "pyörähtää muuttuja yli" byte c = 0; // c = 0 --c; // c = 2 5 5 c = c + 1; // c = 0 13
Mikä tyyppi pitäisi valita? Pienin mahdollinen joka sovellutukseen kelpaa unsigned-etuliite, mikäli negatiivisia arvoja ei tarvita Enemmän tilaa "positiivisella"puolella const-etuliite, mikäli muuttujan arvoa ei tarvitse ohjelman ajon aikana muuttaa Esim kytkentäpinnien numerot 14
Tärkeimpiä operaattoreita summa 1+2 3 erotus 1-2 -1 tulo 1*2 2 osamäärä 1/2 0.5 jakojäännös 5%3 2 15
Tärkeimpiä operaattoreita Muutama oikotie onneen muuttujien kanssa summa a+=2 a = a+2 erotus a-=2 a = a-2 tulo a*=2 a = a*2 osamäärä a/=2 a = a/2 kasvata yhdellä a++ a = a+1 vähennä yhdellä a a = a-1 16
Taulukot Hyvä väline esimerkiksi useamman ledin nastanumeroiden säilömiseen. int led_ pin [3] = 3, 5, 6; // l e d _ p i n [ 0 ] on n y t 3 // l e d _ p i n [ 1 ] v a s t a a v a s t i 5 Taulukon jäseniä kutsutaan alkioksi. Alkioon pääsee käsiksi syntaksilla nimi[alkio] Indeksointi alkaa nollasta led_ pin [1] = 2; // l e d _ p i n v a s t a a n y t määritelmää 3, 2, 6 17
Teksti C-kielessä ei erillistä muuttujatyyppiä tekstille, vain merkeille (char) Merkkijonot esitetään char-taulukkona char materiaali [] = " puu "; // materiaali-muuttuja vastaa nyt // määritelmää p, u, u, \0 Merkkijonon lopussa ns. nollatavu Kertoo apufunktioille merkkijonon loppukohdan Kolmen merkin merkkijonon tallentamiseen tarvitaan siis neljä merkkiä! 18
Merkkijonojen käsittely Merkkijonojen käsittelyyn on olemassa apufunktioita strcpy Kopioi osa merkkijonosta toiseen merkkijonoon strcat Yhdistä kaksi merkkijonoa toisiinsa strcmp Vertaile kahta merkkijonoa toisiinsa itoa ja atoi Muunna kokonaisluku merkkijonoksi tai toisin päin 19
Vaikeaa? Merkkijonojen käsittely hieman hankalaa C-kielessä Apuun tulee Arduinon olento nimeltä String Kuluttaa kuitenkin muistia enemmän kuin c-tyyliset merkkijonot käytä vain jos on tarvetta String merkkijono = " elaimia on " + 3 + " kpl "; // m e r k k i j o n o on n y t m u o t o a " e l a i m i a on 3 k p l " 20
String muuntaminen Jotkut funktiot palauttavat tai vaativat c-tyylisiä merkkitaulukoita String kuitenkin vain piilottaa merkkitaulukon taakseen. muuntaminen onnistuu String koirateksti = " koira "; koirateksti. c_ str () // vastaa c-tyylistä merkkijonoa. // Vain lukemiseen, // ei muokkaamiseen char merkkijono [] = " kissa "; String kissateksti = String ( merkkijono ); 21
Ehtolauseet if ( false ) // Tee jotakin jos ehto on tosi else // Hyppää tänne jos ehto epätosi 22
Ehtolauseet Mikäli ehto on tosi, suoritetaan kyseessä oleva lohko // Tässä ehto ei ole tosi, eli lohkoa ei suoriteta // vaan siirrytään eteenpäin if ( false ) // Tee jotakin jos ehto on tosi 23
Ehtolauseet Mikäli lohkoa ei suoritettu, suoritetaan else-lohko. tai ei mitään, jos else-lohkoa ei ole // Tässä ehto ei ole tosi, eli lohkoa ei suoriteta // vaan siirrytään eteenpäin if ( false ) // Tee jotakin jos ehto on tosi else // Tämä lohko suoritetaan, koska edellisen // lohkon ehto oli epätosi 24
Näitä voi myös yhdistää boolean kissat_ kivoja = false ; boolean linnut_ kivoja = false ; if ( linnut_ kivoja ) // Eivät ole, eli tänne ei päädytä else if ( kissat_ kivoja ) // epätosi // Eivät ole, eli tännekään ei päädytä else // Päädytään siis tänne 25
Mielekkäitä totuuksia Vertailu a == b a yhtä suuri kuin b a!= b a eri suuruinen kuin b a < b a pienempi kuin b a > b a suurempi kuin b a <= b a pienempi tai yhtäsuuri kuin b a >= b a suurempi tai yhtäsuuri kuin b true jos ehto täyttyy false (0) jos ehto ei täyty 26
IF-lauseissa on jo jotain järkeä int kissat = 2; int koirat = 3; if ( koirat < kissat ) // epätosi // koirat ovat huonompia kuin kissat else // koirat ovat parempia kuin kissat 27
Totuuksien yhdistäminen Mitä jos halutaankin tutkia, ovatko koirat parempia kuin kissat JA ovatko linnut huonompia kuin kissat 28
Boolen logiikka a && b a ja b molemmat tosia (and) a b a tai b on tosi (or)!a a on epätosi (not) true jos ehto toteutuu, muuten false 29
Boolen logiikka IF-lauseessa voi käyttää sulkuja kuten matematiikassa int linnut = 1; int kissat = 2; int koirat = 3; if ( ( koirat > kissat ) && ( linnut < kissat ) ) // koirat ovat parempia kuin kissat //ja // linnut ovat huonompia kuin kissat 30
Boolen logiikka int linnut = 1; int kissat = 2; int koirat = 3; if ( true && true ) // koirat ovat parempia kuin kissat //ja // linnut ovat huonompia kuin kissat 31
Boolen logiikka int linnut = 1; int kissat = 2; int koirat = 3; if ( true ) // koirat ovat parempia kuin kissat //ja // linnut ovat huonompia kuin kissat 32
Helpot asiat mokata! Varoitus! a=b ja a==b ovat eri asioita! a=b; sijoita b:n arvo a:han a==b; tarkista ovatko a ja b saman arvoiset C-tyylisiä merkkijonoja ei voi vertailla ==-operaattoreilla 33
Silmukat Silmukoita käytetään kun samankaltaisia asioita pitää tehdä useita kertoja peräkkäin. Silmukoita käytetään kun samankaltaisia asioita pitää tehdä useita kertoja peräkkäin. Silmukoita käytetään kun samankaltaisia asioita pitää tehdä useita kertoja peräkkäin. 34
While while ( ehto ) // Tee jotakin niin kauan kuin ehto //on tosi 35
For for ( alkuarvo ; ehto ; askel ) // Tee jotakin niin kauan kuin ehto //on tosi 36
For esimerkki int ledpin [3] = 3, 5, 6; void setup () for ( int i =0; i <3; i ++) //i=0, 1, 2 pinmode ( ledpin [i], OUTPUT ); 37
For vs while Oikeastaan for-silmukan voi ajatella hienompana versiona while-silmukasta alkuarvo on vain lause joka ajetaan ennen while-silmukkaa ehto on while-silmukan ehto askel on lause joka sijoitetaan viimeiseksi while-silmukan sisälle. 38
For vs while int ledpin [3] = 3, 5, 6; void setup () int i =0; while (i <3) pinmode ( ledpin [i], OUTPUT ); i ++; 39
Break ja continue Silmukoiden kulkuun voidaan vaikuttaa myös kahdella komennolla: break Lopeta silmukan suoritus heti ja siirry siitä ulos continue Hyppää takaisin silmukan alkuun. For-silmukassa kuitenkin suoritetaan askel-vaihe. Täten vertaus whileen ei ole aivan täysin toimiva. 40
Break ja continue int i =0; while ( true ) Serial. println (i); i ++; if (i < 3) continue ; break ; 41
Arduinon pääpiirteet Flash-muistia 32 kilotavua, josta 0,5 KB varattu Arduinon bootloaderille Tähän tilaan ohjelman pitää siis mahtua 2 kilotavua SRAM-muistia Käyttömuisti. Esim muuttujat asuvat täällä Tieto häviää kun virrat katkeavat 1 kilotavu EEPROM-muistia Muisti joka ei häviä virtojen katketessa Esimerkiksi laitteen asetusten säilöminen Vrt. tietokoneen kovalevy Arduinon kirjastot piilottavat AVR-C:n paljon helpompaan muotoon. 42
Arduino 43
digitalread Lukee pinnin tilan LOW, pinni kytketty maahan (GND) HIGH, pinni kytketty jännitteeseen. (3-5 volttia) void setup () pinmode (3, INPUT ); void loop () byte arvo = digitalread (3) ; 44
Ylös-/Alasvetovastukset Mikäli pinniä ei ole kytketty mihinkään, sanotaan että se kelluu digitalwrite palauttaa satunnaisesti HIGH tai LOW Ratkaisuna alasvetovastus Kytketään pinni vastuksella (n. 10KΩ) GND:hen Pinnin arvo on nyt LOW kunnes se kytketään myös +5V:iin Ylösvetovastus lähes sama asia: Kytketään pinni vastuksella (n. 10KΩ) +5V:iin Pinnin arvo on nyt HIGH kunnes se kytketään myös GND:iin 45
INPUT_PULLUP Arduinosta löytyy sisäänrakennettuna ylösvetovastus Aktivoidaan määrittämällä pinnin modeksi INPUT_PULLUP void setup () pinmode (3, INPUT_PULLUP ); void loop () byte arvo = digitalread (3) ; 46
digitalwrite Asettaa pinnin arvon LOW tai HIGH. LOW, "pois päältä" HIGH, "päällä" Esimerkiksi ledin vilkutus void setup () pinmode (13, OUTPUT ); void loop () digitalwrite (13, HIGH ); // LED päällä delay (1000) ; //Odota sekunti digitalwrite (13, LOW ); // LED pois päältä delay (1000) ; //Odota sekunti 47
analogread analogreadilla voidaan lukea pinnin jännite Onnistuu vain pinneistä jotka on nimetty A0, A1... Kyseisten pinnien takana on 10-bittinen analogidigitaalimuuntaja (AD) Arvo 0-5V väliltä saadaan siis lukuna väliltä 0-1023. (2,5V siis vastaisi lukua 512) (Kyseisiä pinnejä voi käyttää myös digitaaliseen I/O:hon) void setup ( ) pinmode ( A1, INPUT ) ; void loop ( ) i n t arvo = analogread ( A1 ) ; 48
analogwrite Arduinossa ei ole DA-muunninta analoginen ulostulo pitää tehdä "keinotekoisesti" PWM, eli Arduino kytkee pinniä nopeasti 0V ja 5V välillä. (kanttiaalto) "Teho"määräytyy kauanko pinniä pidetään HIGH- ja kauanko LOW-tilassa Esimerkiksi LEDien himmentämisessä ja normaalien moottorien tehon säädössä riittävä Vain tildellä ( ) merkittyjä pinnejä voi käyttää void setup () pinmode (3, OUTPUT ); void loop () // Ledi palaa "puolella teholla" analogwrite (3, 127) ; 49
Muut millis() aika Arduinon käynnistyksestä millisekunneissa map() muuttujan arvovälin muuntaminen toiselle välille esim. [0, 1023] [0, 256] min(), max(), abs(), sin(), cos()... random() satunnaislukuja Servo kirjasto Servomoottorin liikutteluun... 50
Arduino IDE Kaikki in tarvittava Koodieditori Kääntäjä Koodin lataus Arduinolle Sarjaportin kuuntelu 51
Ohjelma laitteelle 52
Muistin loppuminen Mikäli itse ohjelmakoodi on liian iso, saat virheviestin Mikäli jossakin kohtaa käyttömuisti loppuu, todennäköisesti vain tapahtuu kummallisia asioita. (laite ei toimi kuten pitää, tai ei toimi lainkaan,...) Vältä globaaleja muuttujia Helpointa rajoitukseen on törmätä säilömällä iso määrä tekstinpätkiä Esimerkiksi LCD-näytön käyttöliittymän tekstit voisivat olla ongelma PROGMEM. Tallenna data flash-muistiin. Pienissä projekteissa tuskin tulee kuitenkaan vastaan 53
Ohjelman debuggaus: sarjaportti Arduino osaa USB:n kautta emuloida sarjaporttia Helpoin tapa tietää mitä Arduinossa tapahtuu Kun ohjelma ei toimi kuten sen pitäisi, kannattaa sarjaporttiin tulostaa eri muuttujien arvoja ja tutkia, että ovatko lukemat järkeviä Tekstin tulostaminen ennen ja jälkeen jonkin ohjelman osan auttaa selvittämään, jääkö ohjelma jumiin johonkin kohtaan. Huom! jos käytät sarjaporttia, pinnejä 0 ja 1 ei voi enää käyttää muuhun! 54
Ohjelman debuggaus: sarjaportti int nappi = 3; void setup () Serial. begin (9600) ; pinmode ( nappi, INPUT ); void loop () byte napintila = digitalread ( nappi ); Serial. println ( napintila ); delay (1) ; 55
Ohjelman debuggaus: sarjaportti 56
Ohjelman debuggaus: sarjaportti 57
Ohjelman debuggaus: kumiankka 58
Vinkit ohjelmointiin: funktiot Yksi toiminto, yksi funktio Yksi ongelma, monta "aliongelmaa" Voi käyttää myös ryhmän työnjakoon Esimerkiksi Ongelma: Aja robotti pisteeseen x Missä ollaan nyt Miten pisteeseen x pääsee Miten robotin saa liikkumaan 59
Enum enum OhjelmanTila kysyy_ nimea, sanoo_ moi ; OhjelmanTila tila = kysyy_ nimea ; void loop () String nimi ; if ( tila == kysyy_ nimea ) nimi = kysy_ nimi (); if ( tila == sanoo_ moi ) sano_moi ( nimi ); 60
Vinkit ohjelmointiin: Sisennys Joissakin kielissä (Python) sisennyksellä on väliä ohjelman toiminnan kannalta Arduinon kielessä ei. Sisentämällä koodi kuitenkin on paljon helpompilukuista ja virheet helpompia huomata // Ei siis näin. Hankala lukea ja helppo laittaa // kaarisulkuja vääriin paikkoihin void loop () if ( anturi > raja ) sulje_ venttiili1 (); sulje_ venttiili2 (); 61
Vinkit ohjelmointiin: Manuaalien lukeminen Arduinon sivuilla hyvät ohjeet useimpien funktioiden käyttöön Kertovat yleensä myös missä mitäkin kannattaa käyttää ja milloin mennään metsään Muista että useimmat asiat toimivat C:ssä samalla tavalla Joihinkin osiin löytyy hyviä ja helppoja oppaita, joihinkin hieman teknisiä ja joihinkin huonosti mitään Google yleensä osaa auttaa kun kirjoittaa ongelman englanniksi ja osien tapauksessa liittää tunnistekoodin 62
Vinkit ohjelmointiin: Google Lähes kaikki kääntäjän ilmoittamat virheet googlautuvat hyvin. Maailmassa tehty paljon asioita jo ennestään: how to * with arduino/c Englannin kielellä parhaat hakutulokset Ehkä tärkeimpiä asioita oppia! 63
Versionhallinta "Tää toimi vielä eilen, mut sit tein jotakin ja nyt mikään ei enää toimi" Helpottaa kun useampi ihminen haluaa koodata samaa projektia Git Githubin student-ohjelmassa saa muutaman privarepon ilmaiseksi 64
Arduinon tekstieditori Arduinon asetuksista voi valita käyttöön ulkopuolisen tekstieditorin jos kokee tarpeelliseksi. Kääntäminen ja upload toimivat edelleen ohjelman kautta. Inotool jos pitää komentorivistä 65
Linkkejä https://www.arduino.cc/en/tutorial/homepage https://www.arduino.cc/en/reference/homepage http://cslibrary.stanford.edu/101/essentialc.pdf https://github.com/liffiton/arduino-cheat-sheet http://tronixstuff.com/ http://www.asciitable.com/ http://www.atmel.com/images/ atmel-8271-8-bit-avr-microcontroller-atmega48a-48pa-88a datasheet_complete.pdf 66