Analyse av programkode for ultralydsensor
Vi bruker programmeringsverktøyet Arduino IDE når vi skal programmere Arduino-mikrokontrollerar. Dette verktøyet har programmeringsspråket C++ som grunnkode, men i ein variant som er spesialtilpassa Arduinoane. I tillegg er det utvikla ulike grafiske programmeringsverktøy for Arduino, såkalla blokkprogrammeringsverktøy.
Dømet 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 velje menypunktet "Blocks + Text", så blir Arduino-koden vist generert av kodeblokkene.)
Dømet vårt er ein programkode for ein ultraydsensor. Programmet er koda med blokkprogrammering i TinkerCad Circuits og deretter konvertert til Arduino IDE kodespråk.
No skal vi sjå nærare på korleis kvar enkelt del av programmet er bygd opp.
Variablar
I starten av programmet lagar vi ein variabel for å lagre verdien som ultralydsensoren les av.
Mikrokontrolleren kan programmerast til å lagre ulike typar verdiar i variablane. I dømet vårt er koden int nytta fordi vi vil at verdiane skal vere heiltal, altså tal utan desimalar. Med int kan vi handtere heiltal frå –32 768 til +32 767.
// Sett startverdi på variabel
int cm = 0;
Lese verdiar
Den neste delen er ein spesiell kodebit for lesing av ultralydavstandssensoren. Denne kodebiten er eit lite program inni programmet, og han kan kallast seinare ved å skrive ei enkel kodelinje.
Enkelte sensorar kan elles òg ha eigne programkodar som kan hentast inn frå eit bibliotek.
long readUltrasonicDistance(int triggerPin, int echoPin)
{
pinMode(triggerPin, OUTPUT); // Definer pinne for trigger, og sett han til utgang
digitalWrite(triggerPin, LOW); // Slå av trigger ved å sette han til LOW
delayMicroseconds(2); // Vent i 2 mikrosekund
// Skru på trigger i 10 millisekund
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW); // Skru av trigger
pinMode(echoPin, INPUT); // Definer pinne for ekko, og sett han til INPUT
// Les verdi på ekkopinne, og lagre kor lang tid i mikrosekund signalet tok, i variabelen pulseIn
return pulseIn(echoPin, HIGH);
}
readUltrasonicDistance()
I dømet over har vi brukt funksjonen readUltrasonicDistance() for å beskrive sensorkoden og halde han åtskilt frå hovuddelen av programmet.
long
Funksjonen startar med at vi oppgir kva type data han skal sende tilbake til hovudprogrammet. I dette tilfellet returnerer funksjonen ein verdi av typen long, som er eit heiltal med mange siffer.
Ein long-variabel bruker 4 byte i minnet, og han kan representere heiltal frå
–2 147 483 648 til +2 147 483 647 (inkludert null). Variabeltypen er særleg nyttig når vi til dømes arbeider med tid og teljarar, der store verdiar må lagrast eller bli rekna ut nøyaktig.
Namn på funksjonen
Val av namn på funksjonen er i grunnen opp til programmeraren. Det er vanleg med engelske namn fordi engelsk blir brukt i kodinga, men det går fint an å lage norske namn.
pin
I parentesen etter namnet står argumenta funksjonen tek. Her er det int triggerPin og int echoPin som er dei variable erklæringane for tilkoplingsstiftane til sensoren.
Pin-nummera vil bli spesifiserte når du kallar opp funksjonen i loop(). Inne i denne funksjonen blir dei lokale variablane triggerPin og echoPin brukte til å referere til informasjonen vi sender til han frå hovud-loopen (eller frå ein annan funksjon).
Sjølve funksjonen gir ultralydsensoren beskjed om å sende ut eit signal gjennom triggerPin og "lytte etter" ekkoet til signalet gjennom echoPin (som i dømet vårt er same pinne). Programmet startar ei avansert stoppeklokke når signalet blir sendt ut, og stoppar klokka når signalet returnerer og kjem tilbake til Arduinoen. Så blir avstanden kalkulert.
Vi kan sjølv velje kva namn vi vil gi kvar enkelt pinne.
digitalWrite
digitalWrite beskriv kva verdi pinnen skal sende, altså LOW (0, Av) eller High (1, På).
delayMicroseconds
Denne koden fortel mikrokontrolleren at han skal ta ein pause på eit gitt tal mikrosekund før han går vidare i programmet.
Denne pausen må tilpassast avstanden vi skal måle, for vi må ta omsyn til kor raskt lyden bevegar seg gjennom lufta (ca. 340 m/s). Måler vi lange avstandar, kan vi ha lange pausar, måler vi korte avstandar, må pausen vere kort.
pinMode
Vi bruker kommandoen pinMode for å programmere den aktuelle pinnen til å sende ut eller motta signal.
I dømet vårt har ultralydsensoren berre 3 pinnar (triggerPin, echoPin og Spenning), og pinnane kan både sende og motta signal. Mikrokontrolleren må då få instruks om når pinnen skal motta signal, når han skal sende, og kor lenge han skal gjere dette.
return pulseIn
Denne funksjonen får mikrokontrolleren til å lese avstandsverdien frå ultralydsensoren. Ultralydsensoren har då kalkulert avstanden ut frå når signalet blei sendt, og når det blei teke imot.
Setup
Setup bruker vi for å oppgi innstillingar mikrokontrolleren skal bruke.
void setup()
{
Serial.begin(9600); // Start kommunikasjon med omverda
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 nokre faste parameterar han skal forhalde seg til. I dømet vårt får mikrokontrolleren beskjed om at han skal kommunisere med datamaskin og andre komponentar med ei hastigheit på 9600 baud.
I tillegg fortel vi mikrokontrolleren at han skal nytte pinnane 2, 3 og 4, og at desse pinnane skal nyttast til å sende signal ut. Her skal mikrokontrolleren sende signal fram til diodane slik at dei lyser.
void loop
void loop() er sjølve hovudprogrammet som blir gjenteke om og om igjen: Det går "i løkke".
void loop()
{
// Les verdi frå 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 ein kalkulasjon som reknar ut vår variabel cm ved å nytte verdien frå ultralydsensoren i forhold til lydhastigheita i luft. I tillegg får mikrokontrolleren beskjed om at han skal nytte pinne 7 både til å sende og til å få signal.
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 ein instruks om at programmet skal skrive verdien på skjermen saman med fast tekst.
Om vi hadde ein ultralydsensor med separate pinnar for sending og mottak, kunne vi til dømes brukt pinnane 6 og 7. Då måtte vi ha deklarert begge pinnane og sett den eine som utgang og den andre som inngang.
Serial.print
Serial.print fortel mikrokontrolleren at han skal skrive tekst og variablar på skjermen. Vanleg tekst blir sett i hermeteikn, mens variablar blir førte opp med berre variabelnamnet.
// Kva skal skje viss avstanden er mellom 200 og
// 300 cm?
if (cm <= 300 && cm > 200) {
digitalWrite(2, HIGH); // Aktiver pinne 2
digitalWrite(3, LOW); // La pinne 3 vere avslått
digitalWrite(4, LOW); // La pinne 4 vere avslått
}
Vi vil at verdiane vi les av, skal sette i gang noko. For å få til dette bruker vi logiske funksjonar du kanskje kjenner igjen frå matematikken.
I koden over gir vi mikrokontrolleren instruks om kva han skal gjere viss verdien han lagrar i variabelen cm, er større enn 200 og mindre eller lik 300. I så fall skal han aktivere pinne 2 (HIGH), mens pinne 3 og 4 framleis skal vere avslåtte (LOW). Berre dioden som er kopla til pinne 2, skal lyse.
Vi kan sjølv velje kva verdiar som skal nyttast som referansetal. I ruta under finn du døme for alle diodane, med definerte verdiar for når dei skal lyse eller vere avslåtte.
Målehyppigheit
Kor ofte vi treng å få eit måleresultat, avheng av kva vi skal måle. Måler vi noko som bevegar seg raskt, bør vi velje ein kort pause, men måler vi noko som bevegar seg sakte, kan vi eksempelvis måle kvart femte minutt.
I dømet vårt nedanfor blir verdien målt 10 gonger i sekundet (100 millisekund = 0,1 sekund).
// Kor ofte skal avstanden sjekkast?
delay(100); // Vent i 100 millisekund før programmet blir køyrt på ny
}