Haaste: Discovalot

Johdanto

Tässä harjoituksessa kasataan musiikin mukaan vilkkuvat discovalot. Maker kitin äänianturi soveltuu musiikin seuraamiseen, ja samalla selviää, kuinka Arduinolla voi vilkuttaa viittä lediä itsenäisesti.

Olemme ajastaneet Arduinon toimintaa käyttämällä delay-komentoa. Sitä on helppo soveltaa, mutta ongelmana on, ettei Arduino tee delay-viiveen aikana yhtään mitään muuta.

Entä jos halutaankin ohjata useita laitteita samaan aikaan toisistaan riippumatta? Fiksumpaa ajanhallintaa varten on funktio millis, joka pitää kirjaa siitä, kuinka kauan Arduinolla oleva ohjelma on ollut käynnissä.

Pienissäkin ledeissä on mukavasti valotehoa, mutta ne eivät paljaaltaan näytä kovin vaikuttavilta. Katso oheinen video - siinä ledit on upotettu pingispallojen sisään, joista valo siroaa jo vähän näyttävämmin.

Mehackit: Discovalot

Tarvikkeet

Mehackit boardin (tai Arduinon), USB-johdon, koekytkentälevyn ja johtimien lisäksi tarvitset seuraavat komponentit.

OsaKuvaKuvaus
Jatkojohtoja
LED x 5Värittömällä kuvulla varustetut ledit ovat kirkkaampia kuin värillisellä kuvulla varustetut ledit. Ledin väri selviää kokeilemalla!
Vastus 330 Ω x 5Vastus vastustaa sähkövirran kulkua. Vastuksen arvo mitataan ohmeissa (Ω) ja ilmoitetaan komponentissa eri värisinä raitoina (tässä oranssi, oranssi, ruskea ja kulta).
ÄänianturiYksinkertainen mikrofoni, joka reagoi äänen voimakkuuteen.

Virtapiiri

  • Kiinnitä äänianturi jatkojohtojen päähän, jotta voit tarvittaessa helposti siirtää sen lähemmäs äänilähdettä.
  • Änianturi kytketään eri GND-porttiin kuin ledit: analogiset anturit ovat häiriöherkkiä, ja kytkeminen eri porttiin vähentää häiriöitä.

Ohjelman tavoite

Äänianturi reagoi äänen amplitudiin eli voimakkuuteen. Siitä sisään tuleva signaali on välillä 0-1023. Arvoväli jaetaan sopiviin osiin niin, että jokainen viidestä ledistä vilkkuu vain tiettyjen äänen voimakkuuksien mukaan.

  • Kun äänianturin lukema on väliltä 50-150, led 1 syttyy
  • Kun äänianturin lukema on väliltä 150-250,led 2 syttyy
  • jne. aina suurimpiin anturin antamiin arvoihin saakka.

Jokainen led on päällä tietyn aikaa. Kaikkia ledejä ohjataan itsenäisesti: jokainen niistä on jatkuvasti valmiina syttymään, eikä niiden toiminta riipu siitä, palavatko muut ledit vai eivät.

Tuttuja komentoja:

Uusia komentoja ja termejä:

  • millis(): Tämä funktio ottaa aikaa ohjelman alusta eli palauttaa tiedon siitä, kuinka kauan Arduinolla oleva ohjelma on ehtinyt pyöriä. funktion avulla on mahdollista ajastaa samanaikaisia toimintoja.
  • Kahden ehdon testaaminen ehtolauseessa ( && ): Esim. led 1 on päällä, kun äänianturin lukema on sekä yli 50 että alle 150. Kun halutaan testata useita ehtoja, tämä tehdään &&-merkkien avulla.
  • unsigned long -datatyyppi: Ohjelmassa otetaan aikaa. Unsigned tarkoittaa, että muuttujan arvo ei voi olla negatiivinen: aika on aina positiivinen arvo. Long-tyyppisen muuttujan arvo voi olla paljon suurempi kuin int- ja float -muuttujilla, mikä on aikaa otettaessa tärkeää.

Ohjelmointi 1/3 - Äänianturin testaus

Tehtävä
Täydennä ensin ohjelman setup-osa koodissa olevien kommenttien mukaisesti.
int ledPin1 = 7; 
// määrittele mallin mukaan kokonaislukumuuttujat 
// ledPin2 - ledPin5
// ja aseta niiden arvoiksi
// portit joihin loput ledit on kytketty

void setup() {
     pinMode(ledPin1, OUTPUT);
     // määrittele mallin mukaan myös
     // ledPin2-ledPin5 
     // ulostuloiksi 
     Serial.begin(9600);
}
Tehtävä
Täydennä sitten vielä ohjelman loop-osa. Avaa lopuksi Serial monitor ja seuraa lukemia. Mikä on hiljaisin äänenvoimakkuus eli pienin arvo, johon discovalojen kannattaisi reagoida? Entä suurin?
void loop() {
  // määrittele kokonaislukumuuttuja sensor ja lue sen arvoksi portin A0 lukema
  // lisää 8 ms viive
  // tulosta sensor serial monitoriin
}
  • Pieni viive, esimerkiksi 8 millisekuntia, on tarpeen, jotta sarjaliikenne ei sekoa liian tiuhaan kulkevista viesteistä.

Ohjelmointi 2/3 - Valot päälle!

Nyt kun anturi mittaa äänenvoimakkuutta, tämän datan perusteella voidaan määrätä jokaiselle ledille oma volyymikaista, joka saa valon syttymään. Pienellä säädöllä on mahdollista saada esimerkiksi yksi ledeistä reagoimaan bassorumpuun ja toinen lauluun.

Tehtävä
Lisää loop-osaan ehtolauseet, jotka sytyttävät jokaisen ledin voimakkuudeltaan erilaisten äänien seurauksena. Ohjelmoi lisäksi valojen sammutus. Tässä vaiheessa voit vielä käyttää tuttua delay-komentoa
Tehtävä
Testaa ohjelmaa soittamalla äänianturin edessä musiikkia. Kokeile myös muuttaa lopussa olevan delayn arvoa.
void loop() {     
 
  // määrittele kokonaislukumuuttuja sensor ja lue sen arvoksi portin A0 lukema
  // lisää 8 ms viive
  // tulosta sensor serial monitoriin

  if ((sensor > 50) && (sensor < 150)){
    digitalWrite(ledPin1, HIGH);
  }
  // Kirjoita yllä olevan mallin mukaan ehtolauseet myös muille ledeille

  delay(10);
  digitalWrite(ledPin1, LOW);
  // Ohjelmoi yllä olevan mallin mukaan muut ledit pois päältä.

}

Huomaat, että valot kyllä reagoivat ääneen - mutta vain yksi valo palaa kerrallaan. Tämä johtuu delay-komennosta: yhdellä loop-kierroksella vain yksi valo sytytetään, ja se on päällä delay-komennnossa määritellyn keston ajan. Vasta tämän jälkeen, uudella loop-kierroksella ohjelma voi sytyttää seuraavan valon.

Kuinka led saadaan syttymään, vaikka edellinen vielä palaa? Otetaan seuraavalla sivulla käyttöön uusi komento millis, jolla voi ajastaa samanaikaisia toimintoja.

Ohjelmointi 3/3 - Valojen ajastaminen

Nyt ohjelmassa korjataan aiemmin ilmennyt haaste siitä, että ledien syttymistä ja sammumista oli vaikea ajastaa.

Tehtävä
Määrittele ensin muutama uusi muuttuja ohjelman alussa, ennen setup- ja loop- komentoja. Muuttujien selitykset ovat vielä koodin alla.
unsigned long interval = 200;
unsigned long currentMillis;
unsigned long previousMillis = 0;

int ledPin1 = 7; 
// määrittele mallin mukaan kokonaislukumuuttujat 
// ledPin2 - ledPin5
// ja aseta niiden arvoiksi
// portit joihin loput ledit on kytketty
  • unsigned long merkitsee laajennetun kokoista kokonaislukumuuttujaa, jonka arvo ei voi olla negatiivinen.
  • Muuttuja interval: aika, jonka kukin led on kerrallaan päällä
  • Muuttuja currentMillis: tähän tallennetaan loop-osassa millisekunteina aika, joka on kulunut siitä, kun Arduino-ohjelma käynnistyi
  • Muuttuja previousMillis: apumuuttuja, johon kulunut aika tallennetaan 200 millisekunnin välein.
Tehtävä
Korjaa sitten loop-osaa kommenttien ohjeistamalla tavalla. Koodin alla on selvennystä siitä, mitä tehdään ja miksi.
void loop() {     
  currentMillis = millis();
 
  // määrittele kokonaislukumuuttuja sensor ja lue sen arvoksi portin A0 lukema
  // lisää 8 ms viive
  // tulosta sensor serial monitoriin

  if ((sensor > 50) && (sensor < 150)){
    digitalWrite(ledPin1, HIGH);
  }
  // Kirjoita yllä olevan mallin mukaan ehtolauseet myös muille ledeille

  // delay(10); Kommentoi tai editoi pois tämä delay.

  if(currentMillis - previousMillis >= interval) {
     previousMillis = currentMillis;
    
     digitalWrite(ledPin1, LOW);
     // Ohjelmoi yllä olevan mallin mukaan muutkin ledit pois päältä.
  
  }
}
  • currentMillis = millis(): Jokaisella loop-kierroksella katsotaan, kauanko ohjelma on ollut käynnissä.
  • Ehtolause if(currentMillis - previousMillis >= interval) tarkistaa, onko jo aika sammuttaa ledejä, eli onko kulunut 200 millisekuntia edellisestä sammutuskerrasta. Ledien sammutuskäskyt täytyy sijoittaa tämän ehtolauseen sisään.

Ohjelma voi aluksi tuntua hankalalta ymmärtää. Muista, että Arduino suorittaa noin 500 loop-kierrosta sekunnissa, ja että se on jokaisella kierroksella valmiina sytyttämään jonkin ledeistä. Jokaisella kierroksella ei kuitenkaan sammuteta valoja, vaan ne sammutetaan aina 200 millisekunnin välein. Sammuttamista seuraava loop-kierros alkaa niin pian, että led ei välttämättä ehdi edes näyttää siltä, että se on ollut hetken sammutettuna.

Tehtävä
Lue yllä oleva selitys ja kirjoittamasi koodi läpi vielä kerran ja koita hahmottaa ohjelman toiminta. Vastaa lopuksi alla olevaan monivalintaan.

Milloin ledit sammutetaan?

Jatkokehittelyä

Ledien valon häivyttäminen

for-looppia hyödyntämällä ledeille voi ohjelmoida häivytyksen, jolloin discovalot saavat analogista fiilistä.

Ledien korvaaminen muilla laitteilla

digitalWrite-komentoa ei kiinnosta, mikä laite siinä määriteltyyn porttiin on kiinnitetty. Allaoleva video on kuvattu Stadin ammattiopiston Mehackit-kurssilta, ja siinä on käytetty digitalWrite-komentoa auton releiden eli sähköllä ohjattavien kytkimien laittamiseen päälle ja pois. Videon lopussa käytetään aivan samanlaista ohjelmaa kuin discovaloharjoituksessa.

Mehackit: Car Hacking with Stadin Ammattiopisto Vocational School