Syventävä: R2D2

Johdanto

Harjoituksessa tehdään Star Warsista tuttu R2D2. Robotti päästelee normaalioloissa monenlaisia ääniä. Kun se kaatuu eikä enää pääse ylös, se alkaa päästellä avunpyyntöääntä. Kun R2D2 nostetaan takaisin pystyyn, se jatkaa taas tavallista pulinaansa.

Tätä harjoitusta voi oikein hyvin kehitellä eteenpäin vaikka loppuprojektiksi saakka - voit etsiä itseäsi kiinnostavia paperimalleja, lisätä työhön ledejä tai vaikka liikettä moottorien avulla.

Tehtävässä käsiteltäviä teemoja

  • Projekti-idean kehittely
  • Nuottien määrittely ja äänen tuottaminen Arduinolla
  • Asennon havainnointi tilt-kytkimen avulla
  • Omien funktioiden käyttö
  • Satunnaisuus

Tarvikkeet

Mehackit boardin (tai Arduinon), USB-johdon ja johtimien lisäksi tarvitset seuraavia asioita.

OsaKuvaKuvaus
Naaras-naaras jatkojohto x 4
Tilt-kytkinTilt-kytkin toimii kuin painonappi, mutta se mittaa kallistumista. Kun kytkintä kallistaa, sen sisällä oleva pieni kuula vierii toiseen päähän ja yhdistää kytkimen jalat.
Piezo-kaiutinPiezo on yksinkertainen kaiutin, jolla voi muuttaa jännitteen vaihtelun ääneksi. Monia piezoja voi käyttää myös anturina. Piezo-kaiuttimen ulkonäkö voi vaihdella paljon - kuvassa on Maker kitistä löytyvä piezo.
R2D2-paperimalli ja saksethttp://www.cubeecraft.com/cubee/r2-d2Voit tulostaa paperimallin ylläolevan linkin kautta. Kysy apua tulostamiseen ohjaajaltasi!
Kertakäyttömuki tai pahvia
Teippiä

Virtapiiri

  • Tässä kytkennässä ei tarvita ollenkaan kytkentälevyä, vaan kaikki johdot voi kiinnittää suoraan Arduinoon tai Mehackit-boardiin.
  • Huomaa, että piezo-kaiutin ja tilt-kytkin eivät kuvassa näytä ihan samalta kuin Mehackit Maker Kitin komponentit.
  • Kytke piezon ja tilt-kytkimen jalkoihin ensin jatkojohdot, ja niiden päihin vielä tavalliset kytkentäjohdot - tällä systeemillä voit myöhemmin kiinnittää antureita ja komponentteja mielekkäämpiin paikkoihin projekteissasi. Jos jatkojohdot loppuvat kesken, johtoja voi myös pidentää myös juottamalla niitä yhteen.

R2D2-paperimalli

Tulosta ensin malli osoitteesta.

http://www.cubeecraft.com/cubee/r2-d2

Kun olet leikannut ja kasannut tulostetun paperimallin, komponentit kiinnitetään mallin sisäpuolelle. Osat kannattaa teipata ensin kiinni pahviin tai sopivaksi leikattuun kertakäyttömukiin: näin niiden korjailu on helpompaa tarvittaessa, ja robotista tulee tukevampi. Jalkoja voi olla tarpeen vahvistaa lisäpahvilla.

Ohjelman tavoite

Kun R2D2 on pystyssä, Arduino soittaa piezolla sattumanvaraisesti yhden kahdeksasta erilaisesta äänivaihtoehdosta. Jos R2D2 kaatuu, piezosta kuuluu tietty, hätätilaa ilmoittava ääni. Kun R2D2 nostetaan taas pystyyn, se jatkaa alkuperäisten äänten päästelyä.

Uudet komennot

Ohjelmointi 1/4 - Nuottitiedoston lisääminen

Tehtävä
Aloita uusi Arduino-ohjelma ja tallenna se (File > Save As) ennen kuin olet tehnyt koodiin mitään muutoksia. Anna ohjelmalle jokin tunnistettava nimi!

Tässä ohjelmassa tarvitaan ylimääräinen tiedosto nimeltä musical_notes.h, jossa määritellään piezolla soitettavien nuottien nimet ja lukuarvot.

Tehtävä
Klikkaa Arduino IDE:n oikean ylälaidan nuolta ja valitse New Tab, kuten alla olevassa kuvassa. IDE pyytää sinua nimeämään tiedoston: anna sille nimeksi musical_notes.h. Arduino IDE tallentaa nyt projektikansioosi tiedoston musical_notes.h.
Tehtävä
Käy kopioimassa tämän linkin takaa kaikki koodi ja liimaa se musical_notes - ikkunaan. Tallenna lopuksi ohjelma.

Avaa kopioimasi koodi musical_notes.h. Koodissa toistuu monta kertaa termi const float. Tämä ilmaus merkitsee jonkinlaista tietotyyppiä, kuten aiemmin käytetty int.
Mitä ilmauksella "const float" tarkoitetaan?

Ohjelmointi 2/4 - Toimintojen arpominen

Tehtävä
Siirry seuraavaksi takaisin ohjelman puolelle (ensimmäinen välilehti IDE:ssä) ja kopioi alla oleva koodi sinne. Ohjelmoi itse kolme alimpana kommentoitua riviä.
#include "musical_notes.h" // tässä liitetään luomasi nuottitiedosto varsinaiseen ohjelmaan

int speakerPin = 9;   // portit määritellään muuttujina: 
int tiltPin = 2;      // niihin viitataan ohjelmassa hyvin monta kertaa


void setup() {
  pinMode(speakerPin, OUTPUT);     // portti 9 on piezo eli output
  pinMode(tiltPin, INPUT_PULLUP);  // portti 2 on tilt-kytkin eli input
  Serial.begin(9600);              // debuggaus on aina paikallaan
}

void loop() {
   int which = random(9);           // arvotaan kokonaisluku 0-8 ja tallennetaan se muuttujaan which
   if (digitalRead(tiltPin) == HIGH) {
     // muuta which-muuttujan arvoksi 9
   }
   // tulosta which-muuttuja serial monitoriin
   // lisää 1-2 sekunnin viive, jotta arvot ehtii lukea monitorista
}

R2D2-robotilla tulee olemaan 9 erilaista, sattumanvaraista ääntä, kun se on pystyssä, sekä kymmenes hätähuutoääni. Ohjelma toteuttaa jo logiikan, jolla eri vaihtoehdot määräytyvät - kohta pääset ohjelmoimaan mukaan eri äänet!

Tehtävä
Avaa Serial Monitor ja katso, mitä lukuja tulostuu, kun tilt-kytkintä kääntelee. Vastaa sitten monivalintaan.

Mitä arvoja Serial monitoriin tulostuus silloin, kun tilt-kytkin on suljettuna? (digitalRead(2) == LOW)

Ohjelmointi 3/4 - Funktioiden lisääminen

Tehtävä
Käy kopioimassa tämän linkin takaa kaikki koodi. Lisää kopioimasi koodi loop-osan alle eli ei sen sisälle. Katso esimerkki alta. Klikkaa koodintarkistinta (v-merkki IDEssä, lähetysnapin vieressä) niin näet, kopioituiko koodi oikein.
void loop() {
   int which = random(8);           
   if (digitalRead(tiltPin) == HIGH) {
     // muuta which-muuttujan arvoksi 9
   }
   // tulosta which-muuttuja serial monitoriin
   // tähän 1-2 sekunnin viive, jotta arvot ehtii lukea monitorista
} // loop loppuu tähän, uusi koodi liimataan alle:

void beep (int speakerPin, float noteFrequency, long noteDuration) {    
  // Tämä kohta suoritetaan aina, kun kutsutaan funktiota beep
}

void r2D2(){
  // Tämä kohta suoritetaan aina, kun kutsutaan funktiota R2D2
}

// jne.

Kopioimasi funktiot tuottavat ääniä ja ovat nimeltään beep, r2d2, closeEncounters, ariel, laugh2, squeak, waka, catcall, ohhh, uhoh ja laugh.

Ääniä soitetaan kutsumalla funktioita loop-osan sisältä esimerkiksi alla olevalla tavalla. Beep-funktio on erikoistapaus - sitä ei kutsuta loopista, vaan muiden funktioiden sisältä - sen tehtävä on auttaa nuottien soittamisessa.

squeak();

Koodi jonka kopioit on Erik Kringenin kirjoittama ja julkaisema: https://blog.mycontraption.com/?s=sound+effects. Käytämme koodia työohjeessa Erikin luvalla.

Ohjelmointi 4/4 - Viimeistely

Tehtävä
Koodaa vielä loop-osaan lisää if-lauseita siten, että eri ääniä kutsutaan riippuen siitä, mikä numero on arvottu muuttujan which arvoksi. Kommenteissa on ohjeet tätä varten.
Tehtävä
Testaa R2D2:n kallistamista - jos robotti huutaa apua jo seistessään pystyssä, korjaa tilt-kytkimen asentoa! Vastaa lopuksi sivun alalaidassa olevaan monivalintaan.
void loop() {
   int which = random(8);           
   if (digitalRead(tiltPin) == HIGH) {
     // muuta which-muuttujan arvoksi 9
   }
   // tulosta which-muuttuja serial monitoriin
   
   if (which == 0) {
      r2d2();
   }

   if (which == 1) {
      closeEncounters();
   }

   // Tee uusia if-lauseita, kunnes kaikilla which-muuttujan arvoilla 0-9 kutsutaan eri ääntä.
   // Kutsu muuttujan arvolla 9 mielestäsi hätähuudoksi sopivaa funktiota!
   
   // Kirjoita loppuun 1-2 sekunnin viive, jotta arvot ehtii lukea monitorista
}

Koodissasi on nyt useita funktioita, joita voit kutsua loop-osassa. Tutustu funktioiden ideaan täällä.
Mikä seuraavista väitteistä ei pidä paikkansa?

Jatkokehittelyä

Tätä tehtävää voi kehitellä edelleen, vaikka loppuprojektiksi saakka. Alla on ideoita tätä varten.

  • Keksi omia paperimalleja tai googlaa “paper model”. R2D2-malli oli hyvin yksinkertainen, mutta netistä löytyy paljon tyylikkäämpiä malleja lukemattomista aiheista aina Pokemoneista oikeiden avaruussukkuloiden malleihin.
  • Paperin sisään laitetut kirkkaat ledit ovat upeita! R2D2:ta voi täydentää ledeillä, mutta myös origameja voi käyttää. Onnistuisivatko ohjelmoitavat jouluvalot kymmenestä origamista?
  • Paperimallit ovat kevyitä ja helppoja liikuttaa. R2D2:n päätä voisi käännellä servolla tai koko mallin voi laittaa liikkuvan robotin kyytiin (ks. luku 5).
  • Tai voisiko paperimalliin kiinnittää magneetin? Mehackit Maker Kitissä on vahvoja neodyymimagneetteja - jos yhden kiinnittää paperimalliin ja toisen pöydän alla liikkuvaan servoon, robottia voi liikuttaa langattomasti jopa pöydän läpi.
  • Kehittele uusia äänifunktioita!
  • Lisää malliin uusia antureita: mitä voisi tapahtua, kun R2D2 joutuu pimeään, tai jos joku yrittää ottaa sen kiinni?

Lisätietoa

Mikä musical_notes.h?

Arduino ei osaa lähettää piezolle nuottien nimiä, ainoastaan numeroita. Nuottien kirjoittaminen numeroina taas on ohjelmoijalle vaikeaa. Kun lisätiedosto musical_notes.h on liitetty Arduino-ohjelmaan, Arduino osaa etsiä koodia myös sen sisältä. Käytännössä musical_notes.h on vain lista muuttujista, joille on annettu nuottien nimet. Muuttujien arvot ovat piezolle syötettäviä lukuarvoja, jotka vastaavat tiettyjä äänenkorkeuksia.

Arduino-ohjelmaan voi liittää tämänkaltaisia tiedostoja, jotka täytyy aina tallentaa samaan kansioon kuin itse ohjelma. Oman ohjelman ulkopuolista lisäkoodia voi käyttää hyödyksi myös liittämällä ohjelmaan kirjastoja.

Funktio

R2D2-ohjelma kutsuu kopioimiasi koodinpätkiä eli funktioita loop-osan sisällä. Beep-funktio taas on apufunktio, jota käyttämällä nuottien soittaminen helpottuu.

Kopioimasi funktiot kuten laugh(), ariel() ja catcall() ovat ohjelmoijan itse kirjoittamia ja nimeämiä. Siinä missä setup()- ja loop()-funktiot täytyy laittaa jokaikiseen Arduino-ohjelmaan, muiden funktioiden käyttäminen on täysin vapaaehtoista. Kaiken funktioiden sisältämän koodin voisi kirjoittaa auki myös loop-osassa, mutta tämä tekee koodista vaikeasti luettavaa. Varsinkin, jos jotain mutkikkaampaa toimintoa tarvitaan useita kertoja loop-osan aikana, on järkevää kirjoittaa erillinen funktio ja kutsua sitä sitten loopin sisältä.