ELEC-A4010 Sähköpaja Arduinon ohjelmointi Jukka Helle
Arduino UNO R3 6-20VDC 5VDC muunnin 16 MHz kideoskillaattori USB-sarjamuunnin (ATmega16U2) ATmega328 -mikro-ohjain 14 digitaalista I/O väylää 6 kpl PWM 6 analogista sisääntuloa
ATmega328 Kellotettavissa 20MHz asti 32 KB Flash-muistia 0.5 KB bootloaderin käytössä Ohjelmakoodin tallennuspaikka 2 KB SRAM Ohjelman käyttömuisti Tyhjenee kun virrat katkaistaan 1 KB EEPROM Kuin pieni kiintolevy, kirjoitus hidasta
Arduino-ohjelman rakenne #include <math.h> // Matemaattisia funktioita int ledpin = 13; int sensorpin = 4; void setup() pinmode(ledpin, OUTPUT); pinmode(sensorpin, INPUT); // Merkkivalo // Anturi bensatankissa // Suoritetaan vain kerran alussa // I/O porttien määrittely void loop() // Suoritetaan kerta toisensa perään // analogread palauttaa arvon välillä [0, 1023]. int gaslevel = analogread(sensorpin); int ledon = gaslevel < 300; digitalwrite(ledpin, ledon); // LED sytytetään kun tankki lähes tyhjä
Kaarisulkeet...... määräävät muuttujan eliniän int dog = 8; void setup() int cat = dog + 1; // OK: cat == 9 void loop() dog = cat; // Virhe: muuttujaa 'cat' ei ole // määritelty
Datatyypit 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 float) 183 (desimaali) 0267 (oktaali) 0b10110111 (binääri) 0xB7 (heksadesimaali) 7U (unsigned) 10L (long) 15UL (unsigned long) 10.0 (liukuluku) 2.4e5 (2.4*10^5 = 240000) Huom! Liukulukujen (float, double) laskenta on hidasta kokonaislukuihin verrattuna.
Aritmeettiset operaattorit = (asettaa muuttujan arvon) + (summa) - (erotus) * (tulo) / (osamäärä, älkää jakako nollalla!) % (jakojäännös) & (bittikohtainen ja) (bittikohtainen tai) ^ (bittikohtainen xor) Myös muita: ++a, --a, a++, a--, +=, -=, /=, *=, %=...
Vertailuoperaattorit a == b (yhtäsuuri) a!= b (erisuuri) a < b (pienempi) a > b (suurempi) a <= b (pienempi tai yhtäsuuri) a >= b (suurempi tai yhtäsuuri) Varo vaaraa! Muista kaksi = -merkkiä kun tarkastelet muuttujien yhtäsuuruutta. (a == 2) vs. (a = 2) Jälkimmäinen lauseke asettaa muuttujan a arvoksi 2.
Boolen operaattorit a && b (ja) a b (tai)!a (ei) Huomioi edellä kaksi & tai -merkkiä. Esimerkkejä: int a = 8; int b = 2; (a > b) => true (a on suurempi tai yhtäsuuri kuin b) (a < 2) (a > 12) => false (a on pienempi kuin 2 tai suurempi kuin 12) (a == b) => false (a on yhtäsuuri kuin b)!a && (b > 2) => false (a on 0, ja b on suurempi kuin 2)
Ohjausrakenteet if if(n > 100) n = 0; if(n) // Täällä oleva koodi suoritetaan aina, paitsi silloin kun // muuttujan n arvo on 0.
Ohjausrakenteet if.. else if.. else if(a < 3) digitalwrite(ledpin, 1); else if((a > 100) && (a < 150)) digitalwrite(ledpin, 0); else delay(100);
Ohjausrakenteet do... while int a = 100; do a = a - 1; while(a > 0); a = 100; while(a > 0) a = a - 1; int buttonpin = 6; void setup() pinmode(buttonpin, INPUT_PULLUP); void loop() while(1) int button = digitalread(buttonpin); if(button == 0) break; // Nappia on nyt painettu.
Ohjausrakenteet for for(int a = 0; a < 1000; a = a + 1) Serial.println(a); int b = something(); for(b = 0; b < 1000; ++b) Serial.println(b); for(byte c = 10; c >= 0; --c); // Ei pääty koskaan, miksi?
Muuttujat Under/overflow byte c = 0; // c = 0b00000000, 0 --c; // c = 0b11111111, 255 c = c + 1; // c = 0b00000000, 0 Kokonaisluvun jakaminen c = 3; // c = 0b00000011, 3 c = c / 2; // c = 0b00000001, 1 c = 7; // c = 0b00000111, 7 c = c / 8; // c = 0b00000000, 0
Taulukot Taulukkot ovat käteviä mikäli samanlaisia muuttujia tarvitaan paljon, esim. jos useampi nappi on kytkettynä Arduinoon. int nappi1 = 5, nappi2 = 7, nappi3 = 8; int napit[3] = 5, 7, 8; Taulukon jäsenet ovat alkioita. Edellinen taulukko sisältää 3 alkiota. Yleensä on myös järkevää tallentaa taulukon jäsenien määrä johonkin muuttujaan: const int nappeja = 3; // const tarkoittaa arvon olevan vakio for(int i = 0; i < nappeja; ++i) napit[i] = napit[i] + 1; napit[3] = 5; // Mitä tässä tapahtuu?
Merkkijonot Merkkijonot ovat char-taulukoita. const char *greeting = moi ; 'm', 'o', 'i', '\0' 109, 111, 105, 0 0x6D, 0x6F, 0x69, 0x00 0b01101101, 0b01101111, 0b01101001, 0b00000000 Merkkijonon muuttuja on numero, joka kertoo ainoastaan ensimmäisen merkin muistiosoitteen. Piiloitettu nolla-merkki ('\0') kertoo merkkijonon loppuvan. Jokaisella merkillä on numeroarvot. Ne löytyvät ASCII-taulukosta. Merkkijonojen käsittelyyn on funktioita esim. strcpy, strcat, strcmp.
digitalread void setup() pinmode(3, INPUT); pinmode(4, INPUT_PULLUP); void loop() byte arvo = digitalread(3); byte nappi = digitalread(4); // Jne... INPUT_PULLUP kytkee sisäisen vastuksen portin ja käyttöjännitteen (5V) välille Jännite nousee itsestään ylös kun porttia ei ole kytketty mihinkään (esim. painikkeen takia avoin piiri)
digitalwrite void setup() void loop() pinmode(13, OUTPUT); while(1) PORTB = 0 20; //LED päälle void loop() PORTB &= ~0 20;// LED pois digitalwrite(13, 1); digitalwrite(13, 0); Nyt kanttiaallon taajuus on 2.66 MHz Ylläoleva ohjelma tuottaa kanttiaaltoa ainoastaan n. 121 khz taajuudella, vaikka prosessorin kellotaajuus on 16 MHz Vielä korkeampia taajuuksia aina 8 Mhz asti voidaan tuottaa mikro-ohjaimen ajastimien avulla ATmegan I/O-rekistereihin pääsee myös suoraan käsiksi
analogread Tekee 10-bittisen analogi-digitaali muunnoksen Vertaa portin jännitettä referenssijännitteeseen (AREF, normaalisti 5 V) Tuottaa luvun väliltä [0, 1023] AREF porttiin ei saa kytkeä alle 0 V tai yli 5 V jännitettä! Kohinaa voi suodattaa koodissakin mm. laskemalla useamman mittauksen keskiarvon, tai laskemalla liukuvaa keskiarvoa int sensorvalue = analogread(sensorpin); sensorvalue += analogread(sensorpin); sensorvalue /= 2;
analogwrite analogwrite(pin, 127);// 50% pulssisuhde Tuottaa kanttiaaltoa ennaltamäärätyllä pulssisuhteella 0 => 0 % pulssisuhde 255 => 100% pulssisuhde Signaalin taajuus on noin 490 Hz Valitun I/O portin täytyy tukea PWM:ää Voidaan käyttää esim. LEDin himmentämiseen Pulssisuhde pienillä arvoilla saattaa olla hieman määrättyä suurempi Käyttää mikro-ohjaimen ajastimia, joita on rajattu määrä analogwrite(pin, 32); // Luo kanttiaaltoa 12.5 % pulssisuhteella delay(100); // Odota vähintään 100ms digitalwrite(pin, 0); // Lopeta
Lyhyesti funktioista Koodia kannattaa osioida funktiohin Osien uudelleenkäytettävyys paranee Luettavuus paranee Bugeja on helpompi metsästää Funktion kutsuminen vie sekin aikaa int sum(int a, int b) return a + b; int result = sum(1, 2); // result == 3
Tietolähteitä http://arduino.cc/en/tutorial/ http://arduino.cc/en/reference http://arduino.cc/en/reference/portmanipulation http://cslibrary.stanford.edu/101/essentialc.pdf https://github.com/liffiton/arduino-cheat-sheet http://www.asciitable.com/ http://www.atmel.com/images/doc8161.pdf