perjantai 8. huhtikuuta 2016

Suoritusnauha, if ja aliohjelma

Mitään ei tapahdu samanaikaisesti. Mutta kun eri tehtävät suoritetaan hyvin nopeasti, niin ihmiselle ja myös reaalimaailman kannalta näyttä siltä, ja ovat myös käytännössä samanaikaisia tapahtumia. Pääohjelma void loop() on juuri tätä tehtävää varten. Ei toki ainoa, sillä suoritusnauhoja voi olla useampia. Niitä ”ajetaan” tarpeen mukaan. Siitä joskus myöhemmin. Tällaisen pienen mikroprosessorin resurssit ovat rajalliset, joten tärkeää on välttää tarpeetonta toimintaa.

void loop(){ …}
Kun ohjelma Arduinossa käynnistyy, suoritetaan ensimmäisenä ylin rivi. Siitä jatketaan rivi riviltä, kunnes saavutetaan pääohjelman loppusulku ( } ). Sen jälkeen hypätään alkuun ja sama toistuu. Seuraavassa toteutuksessa, missä LEDit vilkkuvat samanaikaisesti eri tahtiin tehdään juuri näin. Kunkin LEDin kohdalla tutkitaan, olisiko syytä sytyttää vai sammuttaa. Tieto läheteään aliohjelmalle, missä tehtävä toteutetaan. Aliohjelmat ovat tärkeitä, koska niitä voidaan ”kutsua” useasta kohdasta pääohjelmaa. Aliohjelmat (tässä funktiot) voivat sijaita pääohjelman edessä tai perässä, mihin tapaan minä olen tottunut.

Ohjelma 5

/**********************************
 * Ohjelma 5:  3 x LED           
 * 08.04.2016                   
 * Onnistunut 3:n LEDin vilkutus 
 *********************************/

// Määrittelyt
const int Con_LEDpun = 2; // Määritellään I/O-pinnit
const int Con_LEDkel = 3;
const int Con_LEDvih = 4;

const int Con_Viive = 500; // Perusjakso 500 ohjelmakierrosta
boolean Bol_LEDpun = true;// Alustetaan tilamuuttujat
boolean Bol_LEDkel = true;
boolean Bol_LEDvih = true;
int Int_LEDpun = 0; // Määritellään ja alustetaan viivelaskuri
int Int_LEDkel = 0;
int Int_LEDvih = 0;

// Alustukset: määritellään pinnien toiminta
void setup() {
  pinMode(Con_LEDpun, OUTPUT);
  pinMode(Con_LEDkel, OUTPUT);
  pinMode(Con_LEDvih, OUTPUT);
}

void loop() {// Pääohjema
// Punaisen LEDin käsittely
  Int_LEDpun++; // Kasvatetaan arvoa yhdellä joka kierroksella
  if(Int_LEDpun > Con_Viive){
    Fun_LEDpun(Bol_LEDpun); // Aliohjelmakutsu
    Int_LEDpun = 0; // Laskurin nollaus
    Bol_LEDpun = !Bol_LEDpun; //Tilan kääntö
  }
// Keltaisen LEDin käsittely
  Int_LEDkel++; // Kasvatetaan arvoa yhdellä joka kierroksella
  if(Int_LEDkel > Con_Viive * 6 / 10){
    Fun_LEDkel(Bol_LEDkel); // Aliohjelmakutsu
    Int_LEDkel = 0; // Laskurin nollaus
    Bol_LEDkel = !Bol_LEDkel; //Tilan kääntö
  }
// Vihreän LEDin käsittely
  Int_LEDvih++; // Kasvatetaan arvoa yhdellä joka kierroksella
  if(Int_LEDvih > Con_Viive * 24 / 100){
    Fun_LEDvih(Bol_LEDvih); // Aliohjelmakutsu
    Int_LEDvih = 0; // Laskurin nollaus
    Bol_LEDvih = !Bol_LEDvih; //Tilan kääntö
  }
delay(1); //Stabilointiviive 1 ms
 }// Pääohjelma loppu

// Aliohjelmat, eli funktiot
void Fun_LEDpun(boolean Tila){
    digitalWrite(Con_LEDpun, Tila);
}// Punaisen LEDin funktion loppu
void Fun_LEDkel(boolean Tila){
    digitalWrite(Con_LEDkel, Tila);
}// Keltaisen LEDin funktion loppu
void Fun_LEDvih(boolean Tila){
    digitalWrite(Con_LEDvih, Tila);
}// Vihreän LEDin funktion loppu

Tässä ei ole kovinkaan paljon uutta edellisiin ohjelmiin verrattuna. Kuitenkin muutama kohta on hyvä käydä läpi. Pääohjelma ja aliohjelmat ovat tyyppiä void. Se tarkoittaa sitä, että niistä ei palauteta mitään.
muuttuja++ on sama kuin muuttuja = muuttuja + 1; Joka kerta kun tämä ohjelmarivi suoritettaan, tuon LEDilaskurin arvo kasvaa yhdellä. Seuraavassa if-lauseessa tutkitaan, onko raja-arvo ylitetty, ja JOS on, välitetään aliohjelmakutsussa LEDin sen hetkinen tila lähtöön aliohjelmassa päivitettäväksi. Seuraavaksi nollataan laskuri. Tämän jälkeen käännetään LEDin tila.
Jos esim. aliohjelmassa suoritetaan laskentaa ja sieltä palautetaan kokonaisluku, on aliohjelma tyyppiä: int aliohjelmanimi(tyyppimuuttuja, ehkä useampi) { laskentalauseita… ; return laskettu arvo; }

Viimeisenä pääohjelmassa on delay(1);, siis yhden millisekunnin viive. Sitä on suositeltavaa käyttää, sillä sen tärkein tehtävä on antaa aikaa I/O-pinnien stabilointiin. Tässä ohjelmassa se antaa myös ohjelmalle noin yhden millisekunnin kiertoajan. Tuo delay(1); on tarkka, mutta kokonaiskiertoaika riippuu siitä miten kauan ohjelmarivien suoritukseen kuluu. Riippuen ohjelman rakenteesta, kiertoaika myös vaihtelee.

Muuttujista muutama sana:
Kaikissa kolmessa aliohjelmassa on Tila-niminen muuttuja. Ihmiselle se näyttää samalta, mutta koneen kannalta ne ovat eri muuttujia. Niiden kulloinenkin arvo sijaitsee eri kohdassa muistiavaruutta. Ne ovat paikallisia (local) muuttujia. Ne "näkyvät" ainoastaan oman aliohjelmansa sisällä. Muuttujat, mitkä on määritelty ohjelman alussa, ovat yleisiä (global) muuttujia. Ne näkyvät ja niitä voi käsitellä missä tahansa kohdassa ohjelmaa.

Ei kommentteja:

Lähetä kommentti