Analyse av programkode for ultralydsensor
Vi bruker programmeringsverktøyet Arduino IDE når vi skal programmere Arduino-mikrokontrollere. Dette verktøyet har programmeringsspråket C++ som grunnkode, men i en variant som er spesialtilpassa Arduinoene. I tillegg er det utvikla ulike grafiske programmeringsverktøy for Arduino, såkalte blokkprogrammeringsverktøy.
Eksempelet vi skal gå gjennom, er programmert i Tinkercad Circuits. I dette verktøyet kan vi få henta ut Arduino-koden automatisk. (Når du står inne i Tinkercad, kan du klikke på rullegardinmenyen til venstre og velge menypunktet "Blocks + Text", så får du Arduino-koden generert av kodeblokkene.)
Eksempelet vårt er en programkode for en ultraydsensor. Programmet er koda med blokkprogrammering i TinkerCad Circuits og deretter konvertert til Arduino IDE kodespråk.
Nå skal vi se nærmere på hvordan de enkelte delene av programmet er bygd opp.
Variabler
I starten av programmet lager vi en variabel for å lagre verdien som ultralydsensoren leser av.
Mikrokontrolleren kan programmeres til å lagre ulike typer verdier i variablene. I eksempelet vårt er koden int benytta fordi vi vil at verdiene skal være heltall, altså tall uten desimaler. Med int kan vi handtere heltall fra –32 768 til +32 767.
// Sett startverdi på variabel
int cm = 0;
Lese verdier
Den neste delen er en spesiell kodebit for lesing av ultralydavstandssensoren. Denne kodebiten er et lite program inni programmet, og den kan kalles seinere ved å skrive ei enkel kodelinje.
Enkelte sensorer kan for øvrig også ha egne programkoder som kan hentes inn fra et bibliotek.
long readUltrasonicDistance(int triggerPin, int echoPin)
{
pinMode(triggerPin, OUTPUT); // Definer pinne for trigger, og sett den til utgang
digitalWrite(triggerPin, LOW); // Slå av trigger ved å sette den til LOW
delayMicroseconds(2); // Vent i 2 mikrosekunder
// Skru på trigger i 10 mikrosekunder
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW); // Skru av trigger
pinMode(echoPin, INPUT); // Definer pinne for ekko, og sett den til INPUT
// Les verdi på ekkopinne, og lagre hvor lang tid i mikrosekunder signalet tok, i variabelen pulseIn
return pulseIn(echoPin, HIGH);
}
readUltrasonicDistance()
I eksempelet over har vi brukt funksjonen readUltrasonicDistance() for å beskrive sensorkoden og holde den atskilt fra hoveddelen av programmet.
long
Funksjonen starter med at vi oppgir hvilken type data den skal sende tilbake til hovedprogrammet. I dette tilfellet returnerer funksjonen en verdi av typen long, som er et heltall med mange sifre.
En long-variabel bruker 4 byte i minnet, og den kan representere heltall fra
–2 147 483 648 til +2 147 483 647 (inkludert null). Variabeltypen er særlig nyttig når vi for eksempel arbeider med tid og tellere, der store verdier må lagres eller beregnes nøyaktig.
Navn på funksjonen
Valg av navn på funksjonen er i grunnen opp til programmereren. Det er vanlig med engelske navn fordi engelsk brukes i kodinga, men det går fint an å lage norske navn.
pin
I parentesen etter navnet står argumentene funksjonen tar. Her er det int triggerPin og int echoPin som er de variable erklæringene for tilkoplingsstiftene til sensoren.
Pin-numrene vil bli spesifisert når du kaller opp funksjonen i loop(). Inne i denne funksjonen brukes de lokale variablene triggerPin og echoPin til å referere til informasjonen vi sendte til den fra hoved-loopen (eller fra en annen funksjon).
Selve funksjonen gir ultralydsensoren beskjed om å sende ut et signal gjennom triggerPin og å "lytte etter" signalets ekko gjennom echoPin (som i eksempelet vårt er samme pinne). Programmet starter ei avansert stoppeklokke når signalet sendes ut, og stopper denne når signalet returnerer og kommer tilbake til Arduinoen. Så blir avstanden kalkulert.
Vi kan selv velge hvilke navn vi vil gi de enkelte pinnene.
digitalWrite
digitalWrite beskriver hvilken verdi pinnen skal sende, altså LOW (0, Av) eller High (1, På).
delayMicroseconds
Denne koden forteller mikrokontrolleren at den skal ta en pause på et angitt antall mikrosekunder før den går videre i programmet.
Denne pausen må tilpasses avstanden vi skal måle, for vi må ta hensyn til hvor raskt lyden beveger seg gjennom lufta (ca. 340 m/s). Måler vi lange avstander, kan vi ha lange pauser, måler vi korte avstander, må pausen være kort.
pinMode
Vi bruker kommandoen pinMode for å programmere den aktuelle pinnen til å sende ut eller motta signaler.
I eksempelet vårt har ultralydsensoren kun 3 pinner (triggerPin, echoPin og Spenning), og pinnene kan både sende og motta signaler. Mikrokontrolleren må da få instruks om når pinnen skal motta signal, når den skal sende, og hvor lenge den skal gjøre dette.
return pulseIn
Denne funksjonen får mikrokontrolleren til å lese avstandsverdien fra ultralydsensoren. Ultralydsensoren har da kalkulert avstanden ut fra når signalet blei sendt, og når det blei tatt imot.
Setup
Setup bruker vi for å angi innstillinger mikrokontrolleren skal bruke.
void setup()
{
Serial.begin(9600); // Start kommunikasjon med omverdenen
pinMode(2, OUTPUT); // Sett pinne 2 til utgang
pinMode(3, OUTPUT); // Sett pinne 3 til utgang
pinMode(4, OUTPUT); // Sett pinne 4 til utgang
}
I void setup() gir vi mikrokontrolleren noen faste parametere den skal forholde seg til. I eksempelet vårt får mikrokontrolleren beskjed om at den skal kommunisere med datamaskin og andre komponenter med en hastighet på 9600 baud.
I tillegg forteller vi mikrokontrolleren at den skal benytte pinnene 2, 3 og 4, og at disse pinnene skal benyttes til å sende signaler ut. Her skal mikrokontrolleren sende signaler fram til diodene slik at disse lyser.
void loop
void loop() er selve hovedprogrammet som gjentas om og om igjen. Det går "i løkke".
void loop()
{
// Les verdi fra sensor og skriv verdien på skjermen
cm = 0.01723 * readUltrasonicDistance(7, 7);
// Skriv verdi på skjerm (Serial monitor)
Serial.print("Avstanden er: ");
Serial.print(cm);
Serial.println(" cm");
Her er det lagt inn en kalkulasjon som beregner vår variabel cm ved å benytte verdien fra ultralydsensoren i forhold til lydhastigheten i luft. I tillegg får mikrokontrolleren beskjed om at den skal benytte pinne 7 både til å sende og til å motta signaler.
Mikrokontrolleren får beskjed om å oppdatere variablen cm ved å hente inn delprogrammet readUltrasonicDistance (skriv og les på pinne 7) og kalkulerer denne verdien ved å multiplisere med 0,01723.
Til slutt følger en instruks om at programmet skal skrive verdien på skjermen sammen med fast tekst.
Om vi hadde en ultralydsensor med separate pinner for sending og mottak, kunne vi for eksmpel brukt pinnene 6 og 7. Da måtte vi ha deklarert begge pinnene og satt den ene som utgang og den andre som inngang.
serial.print
Serial.print forteller mikrokontrolleren at den skal skrive tekst og variabler på skjermen. Vanlig tekst settes i hermetegn, mens variabler angis med kun variabelnavnet.
// Hva skal skje hvis avstanden er mellom 200 og
// 300 cm?
if (cm <= 300 && cm > 200) {
digitalWrite(2, HIGH); // Aktiver pinne 2
digitalWrite(3, LOW); // La pinne 3 være avslått
digitalWrite(4, LOW); // La pinne 4 være avslått
}
Vi vil at verdiene vi avleser, skal sette i gang noe. For å få til dette bruker vi logiske funksjoner du kanskje kjenner igjen fra matematikken.
I koden over gir vi mikrokontrolleren instruks om hva den skal gjøre hvis verdien den lagrer i variabelen cm, er større enn 200 og mindre eller lik 300. I så fall skal den aktivere pinne 2 (HIGH), mens pinne 3 og 4 fortsatt skal være avslått (LOW). Bare dioden som er kopla til pinne 2, skal lyse.
Vi kan selv velge hvilke verdier som skal benyttes som referansetall. I ruta under finner du eksempler for alle diodene, med definerte verdier for når de skal lyse eller være avslått.
Målehyppighet
Hvor ofte vi trenger å få et måleresultat, avhenger av hva vi skal måle. Måler vi noe som beveger seg raskt, bør vi velge en kort pause, skal vi måle noe som beveger seg sakte, kan vi eksempelvis måle hvert femte minutt.
I eksempelet vårt nedenfor måles verdien 10 ganger i sekundet (100 millisekunder = 0,1 sekund).
// Hvor ofte skal avstanden sjekkes?
delay(100); // Vent i 100 millisekunder før programmet kjøres igjen
}