1 Tarkistetaan että kaikki toimii

Samankaltaiset tiedostot
Arduinon ohjelmointi. Sami-Petteri Pukkila. 6. helmikuuta 2017

Ohjelmointiharjoituksia Arduino-ympäristössä

ELEC-A4010 Sähköpaja Arduinon ohjelmointi. Peter Kronström

Tällä ohjelmoitavalla laitteella saat hälytyksen, mikäli lämpötila nousee liian korkeaksi.

ELEC-A4010 Sähköpaja Arduinon ohjelmointi. Jukka Helle

Liikennevalot. Arduino toimii laitteen aivoina. Arduinokortti on kuin pieni tietokone, johon voit ohjelmoida toimintoja.

LUMA SUOMI -kehittämisohjelma LUMA FINLAND -utvecklingsprogram LUMA FINLAND development programme Ohjelmointia Arduinolla

////// VENETIETO.FI \\\\\\ //// Autopilotti 2014 \\\\ //-PID säätimellä. #include <EEPROM.h> #include <SoftwareSerial.h>

Java-kielen perusteet

Java-kielen perusteet

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Arduinon ohjelmointi. Sami-Petteri Pukkila. 1. helmikuuta 2016

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Arduinon ohjelmointi. Sami-Petteri Pukkila. 26. syyskuuta 2016

Ohjelmoinnin perusteet Y Python

Ohjelmoi Arduino Grovella

Tarkempaa tietoa saat myös kurssin GitHub-alustalta. Sen wiki-osio on kattava ja yksityiskohtainen, kun tämä vihkonen taas on vain ensihätään.

////// VENETIETO.FI \\\\\\ //// Autopilotti 2014 \\\\ #include <EEPROM.h> #include <SoftwareSerial.h> SoftwareSerial gps(10, 0); // RX, TX -pinnit

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

TAITAJA 2007 ELEKTRONIIKKAFINAALI KILPAILIJAN TEHTÄVÄT. Kilpailijan nimi / Nro:

Ohjelmoinnin peruskurssi Y1

Arduino. Kimmo Silvonen (X)

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Java-kielen perusteita

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

14. Hyvä ohjelmointitapa 14.1

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Metodien tekeminen Javalla

Ohjelmoinnin perusteet Y Python

Harjoitus 3 (viikko 39)

Zeon PDF Driver Trial

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin perusteet Y Python

13. Hyvä ohjelmointitapa (osa 1) 13.1

Javan perusteet. Ohjelman tehtävät: tietojen syöttö, lukeminen prosessointi, halutun informaation tulostaminen tulostus tiedon varastointi

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Osoitin ja viittaus C++:ssa

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjausjärjestelmien jatkokurssi. Visual Basic vinkkejä ohjelmointiin

Ohjelmoinnin perusteet Y Python

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

11. Javan valintarakenteet 11.1

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

Tietotyypit ja operaattorit

AALTO-VALVONTALAITE TST5102

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

Ohjelmoinnin peruskurssi Y1

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

1. Omat operaatiot 1.1

Harjoitus 2 (viikko 45)

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Harjoitustyö: virtuaalikone

11. Javan valintarakenteet 11.1

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

Python-ohjelmointi Harjoitus 2

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

11. Javan toistorakenteet 11.1

17. Javan omat luokat 17.1

Java-kielen perusteita

Ohjelmoinnin perusteet Y Python

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

7. Näytölle tulostaminen 7.1

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

8. Näppäimistöltä lukeminen 8.1

Taulukot. Jukka Harju, Jukka Juslin

Tietueet. Tietueiden määrittely

Ohjelmoinnin peruskurssi Y1

Taitaja semifinaali 2010, Iisalmi Jääkaapin ovihälytin

13 Operaattoreiden ylimäärittelyjä

Toinen harjoitustyö. ASCII-grafiikkaa 2017

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

Muuttujatyypit ovat Boolean, Byte, Integer, Long, Double, Currency, Date, Object, String, Variant (oletus)

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

12. Javan toistorakenteet 12.1

Transkriptio:

Harjoituksen lopputuloksena on laite joka morsettaa vilkuttamalla Arduinon sisäänrakennettua lediä. Haluttu morsesarja annetaan laitteeseen kytketyltä tietokoneelta. Harjoitusta varten tarvitaan pelkästään Arduino. 1 Tarkistetaan että kaikki toimii Arduinon ohjelmoinnissa on hyvä edetä mahdollisimman pienin askelin. Haluamme käyttää Arduinon sisäistä lediä morsetukseen, ensimmäinen askel lienee siis varmistaa että pystymme laittamaan ledin päälle ja pois. Arduinon sivuilta löytyykin blink-niminen esimerkki joka on hyvä lähtökohta. Esimerkki löytyy osoitteesta https://www.arduino.cc/en/tutorial/ blink const int ledpin = LED_BUILTIN; void setup() pinmode(ledpin, OUTPUT); void loop() digitalwrite(ledpin, HIGH); delay(1000); delay(1000); Nyt jos lataat koodin Arduinoon, ledin pitäisi alkaa vilkkua. Mikäli näin käy, voidaan siirtyä seuraavan ongelman pariin. 1.1 Mitä tämä kaikki tarkoittaa? Esimerkissä määrittelemme ensimmäiseksi ledpin-nimisen muuttujan. Muuttujaan sijoitamme arvoksi Arduinon standardin mukaisen LED_BUILTINvakion. Tämän vakion arvo riippuu käytössä olevasta mikrokontrollerista (Uno, Teensy...) ja UNOn tapauksessa se on pinninumero 13. Tuon taikanumero 13:n voisi siis sijoittaa LED_BUILTIN-vakion paikalle, mutta LED_BUILTIN 1

kuvastaa paljon paremmin sisäänrakennetun ledin pinninumeroa kuin pelkkä 13. Seuraavaksi huomio kiinnittyy muuttujan edessä olevaan kahteen avainsanaan: const ja int. Int, eli integer tarkoittaa kokonaislukua. Arduinon kielessä, toisin kuin esimerkiksi pythonissa, jokaisella muuttujalla on oltava oma tyyppinsä. Muuttujan tyyppejä on esimerkiksi kokonaisluku, merkki, desimaaliluku, totuusarvo jne. Const taas tarkoittaa vakioarvoa. Tämän muuttujan arvo siis määritetään ohjelmointihetkellä ja sitä ei voida enää myöhemmin ohjelman suorituksen aikana muuttaa. Muuttujan määrittely vakioksi estää meitä vahingossa yrittämästä muuttaa sen arvoa ja toisaalta myös antaa kääntäjän tehdä sille erilaisia optimointeja liittyen tietoon, että muuttujan arvo ei tule koskaan muuttumaan. pinmode, digitalwrite ja delay ovat funktioita. pinmode kertoo mitä haluamme tehdä pinnille, tapauksessamme haluamme käyttää sitä ulostulona. digitalwrite asettaa halutulle pinnille halutun tilan, eli tapauksessamme kytkee ledille jännitteen päälle ja pois. delay taas odottaa tekemättä mitään halutun määrän millisekunteja. Esimerkissä myöskin määritetään kaksi funktiota: setup ja loop. Kyseiset funktiot ovat erikoisia Arduinon kannalta: setup funktio ajetaan automaattisesti joka kerta kun Arduinoon kytketään virrat. Setup-funktion ajamisen jälkeen Arduino ajaa loop-funktiota uudelleen ja uudelleen kunnes siitä katkaistaan virrat. Voit myös tehdä omia funktioita joiden avulla koodia pystyy jakamaan pienempiin palasiin. 1.2 Mistä tämän kaiken olisi voinut tietää? Ohjelmoinnissa hakukoneet ovat ystäviä: virheilmoituksen copy&paste Googleen tuottaa usein hyviä hakutuloksia käsillä olevaan ongelmaan. Myöskin "How to do x in arduino" tai "How does x work in arduino" ovat hyviä hakusanoja. Arduinon kieli on käytännössä C/++:aa, jolloin samat ohjeet loopeista, muuttujista ja muista perusasioista yleensä toimivat. Näitä kannattaa siis googlata myös jos arduino-spesifiä ohjetta ei löydy. Erittäin hyvä tietolähde on Arduinon referenssi: https://www.arduino.cc/ en/reference/homepage. Kyseiseltä sivustolta löytyy jokaisen Arduinon funk- 2

tion ja tietotyypin käyttöohje myös yllä mainittujen funktioiden ja tyyppien. Arduinon kielestä on myös olemassa oppaita. Esimerkki tällaisesta: http:// playground.arduino.cc/uploads/main/arduino_notebook_v1-1.pdf Oppaassa on tarkemmin selitetty Arduinon ohjelmointia. 2 Tiedon säilöminen 2.1 Tietotyyppi Tällä hetkellä tiedämme, että ledimme on kunnossa. Seuraavaksi on siis vuorossa sen ohjaaminen. Haluamme että laitteemme toistaa sille annettua morsekoodia, eli kyseinen koodi on oltava jossakin tallessa. Voisimme tehdä ohjelman joka muuntaa yksittäisen kirjaimen morsekoodiksi, mutta yksinkertaisuuden vuoksi emme tee sellaista nyt. Tyydymme ratkaisuun jossa laite ottaa vastaan kolmenlaista morsekoodin osaa: lyhyttä vilautusta, pitkää vilautusta ja taukoa. Näitä voitaisiin kuvata vaikkapa kirjaimilla S - short L - long P - pause Morsekoodimme muodostuu edellä mainittujen "komentojen"jonoista. Tarvitsemme siis jonkinlaisen tavan säilöä monta asiaa peräkkäin. Yksi ratkaisu voisi olla taulukko kirjaimia tai kokonaislukuja. Merkkijonon, tuttavallisemmin tekstinpätkän, säilömiseen on Arduinossa olemassa String-tyyppi. Tämä tyyppi sopii tarkoitukseemme hyvin, joten valitaan mielummin se. 3

2.2 Muuttujan näkyvyys Alustetaan muuttuja sequence seuraavalla tavalla: const int ledpin = LED_BUILTIN; String sequence = "LSSSP"; void setup() pinmode(ledpin, OUTPUT); void loop() digitalwrite(ledpin, HIGH); delay(1000); delay(1000); Huomattavaa on, että alustamme muuttujan kaikkien funktioiden ulkopuolella. Muuttuja on tällöin ns. globaali muuttuja. Globaalia muuttujaa voi muuttaa ja lukea mistä tahansa funktiosta, huonona puolena muuttujaa voi muuttaa mistä paikasta tahansa ja isommassa projektissa tämä muodostuu ongelmaksi. Globaalin muuttujan vastakohta on lokaali muuttuja. Tällainen muuttuja luodaan jonkin funktion sisällä ja se on olemassa vain siellä. Globaaleja muuttujia tulisi käyttää vain jos on erillinen syy käyttää niitä. Tapauksemme jono on muuttuja joka on ohjelmassa keskeinen ja haluamme päästä siihen käsiksi kaikista funktioista, olkoot se siis globaali. 3 Itse morsetus Tässä kohtaa tiedämme että ledimme toimii ja meillä on haluttu morsekoodi tallessa. Seuraava vaihe on miettiä, miten kyseinen koodi muunnetaan ledin vilkkumiseksi. String-tyypistä saadaan helposti yksittäisiä kirjaimia ulos halutusta kohdasta ja kyseisen tekstin pituuskin saadaan tietää yhdellä komennolla. char kirjain = sequence[3]; 4

int pituus = sequence.length(); Järkevintä lieneekin siis kasata seuraavanlainen rakenne: 1. Määritetään globaali muuttuja joka kertoo missä kohtaa jonoa liikumme 2. Alustetaan muuttuja nollaksi. 3. Tarkistetaan mikä komento jonossa on tämänhetkisessä kohdassa 4. Vilautetaan lediä komennosta riippuva aika 5. Lisätään sijaintimuuttujaamme 1, eli siirrytään jonossa yhdellä eteenpäin 6. Tarkistetaan onko sijaintimme pidemmällä kuin jonon pää, eli olemmeko menneet liian pitkälle 7. jos näin on, sijoitetaan sijaintimuuttujan arvoksi taas jonon ensimmäinen alkio, eli 0 8. Siirrytään taas kohtaan 3 5

3.1 Toteutus const int ledpin = LED_BUILTIN; const int dot_duration = 300; String sequence = "LSSSP"; unsigned int sequence_pos = 0; void setup() pinmode(ledpin, OUTPUT); void loop() if (sequence[sequence_pos] == 'S') digitalwrite(ledpin, HIGH); else if (sequence[sequence_pos] == 'L') digitalwrite(ledpin, HIGH); delay(dot_duration*3); else if (sequence[sequence_pos] == 'P') delay(dot_duration*3); sequence_pos++; if (sequence_pos >= sequence.length()) sequence_pos = 0; 6

3.2 Ja selitys Lisäsimme dot_duration-vakion joka kertoo yhden nopean välähdyksen pituuden millisekunneissa. Pidemmän välähdyksen aika on tämän vakion moninkerta taas on parempi että koodissa on nimetty vakio taikanumeroiden sijaan. sequence_pos on globaali muuttuja jotta sen arvo säilyisi loop-funktion ajokertojen välillä. Kuten aikaisemmin todettu, Arduino ajaa loop-funktiota aina uudelleen ja uudelleen. Mikäli sequence_pos määritettäisiin loop-funktion sisällä, joka ajokerralla muuttuja luotaisiin uudelleen ja funktion lopussa tuhottaisiin. 4 Toimiikohan tämä? Ledin pitäisi nyt vilkkua halutunlaisesti. Toimivuuden varmistaminen tosin voi olla hieman hankalaa jos et ole varma, missä kohtaa jonoa tällä hetkellä liikutaan. Tähän ongelmaan voisi käyttää virtuaalisarjaporttia. void setup() Serial.begin(9600); void loop() Serial.println("Moikka!"); delay(1000); Koodin lataamisen jälkeen paina Arduinon ohjelman oikeassa yläkulmassa olevaa suurennuslasia päästäksesi serial monitor-nimiseen näkymään. Valitse avautuvan ikkunan oikeasta alakulmasta sama baudinopeus kuin Serial.beginkäskyn sisällä on annettu. (9600) Näytölle pitäisi nyt tulostua teksti "Moikka!" Toimimatonta koodia voi yrittää selvittää laittamalla tällaisia väliviestejä sopiviin väleihin. Jos jokin viesti jää tulostumatta, ohjelma ei koskaan pääse kyseiseen kohtaan. Myös muuttujien arvoja kannattaa tulostella joskus ne eivät ole ihan sitä mitä luulet niiden olevan. 7

Lisätään nyt koodiimme "väliaikatietoja." 4.1 Toteutus const int ledpin = LED_BUILTIN; const int dot_duration = 300; String sequence = "LSSSP"; unsigned int sequence_pos = 0; void setup() pinmode(ledpin, OUTPUT); Serial.begin(9600); void loop() Serial.print("Position "); Serial.print(sequence_pos); Serial.print(": "); if (sequence[sequence_pos] == 'S') Serial.println("Short"); digitalwrite(ledpin, HIGH); else if (sequence[sequence_pos] == 'L') Serial.println("Long"); digitalwrite(ledpin, HIGH); delay(dot_duration*3); else if (sequence[sequence_pos] == 'P') Serial.println("Pause"); delay(dot_duration*3); sequence_pos++; if (sequence_pos >= sequence.length()) 8 sequence_pos = 0;

4.2 Selitys Serial.print ja Serial.println ovat eri asioita! Println tulostaa loppuun vielä rivinvaihdon joten viestejä on mahdollista koostaa käyttäen näitä funktioita sekaisin. 5 Morsekoodin muuttaminen Ohjelmamme osaa nyt vilkuttaa lediä tekstijonomme perusteella. Eräs vaatimus oli vielä, että morsetettavaa koodia pitäisi pystyä muokkaamaan. Ominaisuus on hyvinkin helppo tehdä sarjaportilla. 5.1 Toteutus const int ledpin = LED_BUILTIN; const int dot_duration = 300; String sequence = "LSSSP"; unsigned int sequence_pos = 0; void setup() pinmode(ledpin, OUTPUT); Serial.begin(9600); void check_update() if (Serial.available() > 0) sequence = Serial.readStringUntil('\n'); Serial.println("Sequence updated!"); void loop() check_update(); Serial.print("Position "); 9

Serial.print(sequence_pos); Serial.print(": "); if (sequence[sequence_pos] == 'S') Serial.println("Short"); digitalwrite(ledpin, HIGH); else if (sequence[sequence_pos] == 'L') Serial.println("Long"); digitalwrite(ledpin, HIGH); delay(dot_duration*3); else if (sequence[sequence_pos] == 'P') Serial.println("Pause"); delay(dot_duration*3); sequence_pos++; if (sequence_pos >= sequence.length()) sequence_pos = 0; 5.2 Selitys Loimme uuden funktion, check_update:n ja kutsumme sitä aina loopfunktion alussa. Kyseinen funktio tarkistaa onko sarjaportissa mitään luettavaa. Jos on, luetaan sarjaportista merkkijono sequence-muuttujaan ja tulostetaan operaation onnistumisesta viesti. readstringuntil-funktio lukee merkkijonon mystiseen \n-merkkiin asti. Ky- 10

seinen merkki on rivinvaihto, eli normaalisti näkymätön merkki. Rivinvaihtomerkki lähetetään kunhan serial monitorin oikeasta alakulmasta on baudinopeuden viereisessä valikossa valittuna newline. 6 Monen asian tekeminen samaan aikaan Ohjelmamme täyttää tällä hetkellä sille annetut vaatimukset: morsetus tapahtuu tietokoneelta tulevien käskyjen mukaan. Jos vilkutettavaa morsekoodia vaihtaa kesken merkin näyttämisen, käskyn vaihtamisessa huomataan olevan viivettä. Tässä tilanteessa viiveellä ei ole juurikaan merkitystä, mutta mitäpä jos meidän pitäisi samaan aikaan vilkutella lediä ja vaikkapa lukea jonkin anturin arvoa? Viiveen ohjelmaamme aiheuttaa delay-funktioiden käyttö. Ohjelmassamme odotetaan ajan kuluvan ja samalla ei tehdä mitään. Arduinossa ei ole tukea moniajolle jossa useampaa ohjelmaa voitaisiin ajaa samaan aikaan, eli ainoa vaihtoehto on keksiä tapa eliminoida delayt. 6.1 Periaate Emme voi tehdä montaa asiaa samaan aikaan, mutta voimme tehdä monta asiaa nopeasti peräjälkeen. Jos haluamme pitää lediä sekunnin päällä, voimme laittaa sen päälle ja odottaa sekunnin kuten teemme nyt. Toinen tapa on tallentaa ajanhetki jolloin ledi laitettiin päälle ja ottaa se pois päältä kun huomataan että aikaa on kulunut sekunti. Arduinossa meitä auttaa millisfunktio. Funktio palauttaa millisekunteina ajan ohjelman käynnistymisestä. 11

Esimerkkinä blinkki ilman delay:ta. const int blinkinterval = 1000; const int ledpin = LED_BUILTIN; int ledstate = LOW; unsigned long previoustime = millis(); void setup() pinmode(ledpin, OUTPUT); void loop() long time_since_blink = millis() - previoustime; if (time_since_blink >= blinkinterval) previoustime = millis(); if (ledstate == LOW) ledstate = HIGH; else ledstate = LOW; digitalwrite(ledpin, ledstate); 1. Määritetään muuttuja ledin päälläololle. ledstate 2. Määritetään muuttuja ajanhetkelle jolloin ledin tilaa viimeksi muutettiin. previoustime 3. Loop-funktiossa lasketaan joka kerta erotus nykyisen ajanhetken ja viimeisen ledin tilan muutoshetken välillä. 4. Jos tämä erotus on suurempi kuin haluttu ledin vilkkumisnopeus: Asetetaan nykyinen ajanhetki ledin viimeiseksi muutoshetkeksi Muutetaan ledin tilan kertova muuttuja vastakkaiseen tilaan. 5. Asetetaan ledin tila vastaamaan muuttujan kertomaa tilaa 12

6. Toistetaan kohdasta 3 eteenpäin 6.2 Sovellutus Jotta pääsemme eroon delay-funktioista, meidän pitää siis keksiä tapa kertoa, pitäisikö ledin olla tällä hetkellä päällä vai pois päältä. Esimerkiksi pitkän vilautuksen tapauksessa Ledin pitäisi olla päällä kolmen dot_duration:in ajan. Tämän jälkeen ledin pitäisi olla pois päältä yhden dot_durationin verran. Tämän jälkeen voidaan siirtyä seuraavaan kohtaan jonossamme. Ohjelmointia varten ongelma lienee helpointa ratkaista seuraavalla tavalla: 13

Onko jo aika vaihtaa seuraavaan kohtaan? Eli onko aikaa kulunut ledin päälläoloaika + pimeänäoloaika Ei On Onko aikaa kulunut vähemmän kuin ledin päälläoloajan pitäisi olla? Siirry seuraavaan kohtaan jonossa Ei On Ledin pitäisi olla pois päältä Ledi päälle 6.2.1 Toteutus Funktiomme voisi näyttää vaikkapa seuraavanlaiselta: 14

unsigned long sequence_start = millis(); int apply_next_state() sequence_pos++; if (sequence_pos >= sequence.length()) sequence_pos = 0; sequence_start = millis(); if (sequence[sequence_pos] == 'S' sequence[sequence_pos] == 'L') return HIGH; else return LOW; int get_led_state() long time_elapsed = millis() - sequence_start; if (sequence[sequence_pos] == 'S') if (time_elapsed > dot_duration*2) return apply_next_state(); else if (time_elapsed <= dot_duration) return HIGH; else return LOW; else if (sequence[sequence_pos] == 'L') if (time_elapsed > dot_duration*4) return apply_next_state(); else if (time_elapsed <= dot_duration*3) return HIGH; else return LOW; else if (time_elapsed > dot_duration*3) return apply_next_state(); else return LOW; void loop() check_update(); digitalwrite(ledpin, get_led_state()); 15

6.2.2 Selitys Olemme tehneet kaksi omaa funktiota. int get_led_state() Palauttaa missä tilassa ledin pitäisi olla tällä hetkellä. (Huomaa int paluutyyppi) int apply_next_state() Etenee jonossa yhden käskyn ja kertoo missä tilassa ledin pitäisi olla. get_led_state-funktiossa huomataan, että if-lauseen sisältöä ei tarvitse laittaa aaltosulkeiden sisään jos sisältö on vain yksi rivi. Muuten toimintalogiikka on sama kuin ylempänä olevassa diagrammissa. Aluksi tarkistetaan pitäisikö jo siirtyä seuraavaan tilaan, jos ei, annetaan ledille arvo HIGH tai LOW. Loop-funktiossa ledi asetetaan joka kerta get_led_state-funktion määräämään tilaan. Näiden kahden funktion lisäksi teimme myös kolmannen funktion: apply_next_state. Tämä funktio liikkuu jonossa eteenpäin ja palaa jonon alkuun jos tarvis. Funktio myös palauttaa pitäisikö ledin olla päällä vai ei. Jos seuraava tila sattuu olemaan tauko, pitäisi ledin pysyä pois päältä. Funktion sisällä olevassa if-lauseessa käytetään -operaattoria. Tutki Arduinon referenssistä, mitä operaatio tarkoittaa! 16