Hopp til innhald
Fagartikkel

Analyse av programkode for ultralydsensor

Ein kode for Arduino kan sjå uoversiktleg ut. Her skal vi analysere ein kode som er generert gjennom blokkodeprogrammering, og som styrer ein avstandsmålar med ultralydsensor.

Programkode C++

Vi bruker programmeringsverktøyet 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øme

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.

Dømekode

// C++ code

// Sett startverdi på variabel

int cm = 0;

long readUltrasonicDistance(int triggerPin, int echoPin)

{

pinMode(triggerPin, OUTPUT);

digitalWrite(triggerPin, LOW);

delayMicroseconds(2);

// Aktiver triggerPin i 10 mikrosekund

digitalWrite(triggerPin, HIGH);

delayMicroseconds(10); // Vent 10 mikrosekund

digitalWrite(triggerPin, LOW);

pinMode(echoPin, INPUT);

// Send og få ultralydsignal på echoPin og lagre verdien i mikrosekund i variabelen pulseIn

return pulseIn(echoPin, HIGH);

}

void setup()

{

Serial.begin(9600);

pinMode(2, OUTPUT);

pinMode(3, OUTPUT);

pinMode(4, OUTPUT);

}

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");

// Beskriv kva som skal skje viss avstanden er

// over 300 cm

if (cm > 300) {

digitalWrite(2, LOW);

digitalWrite(3, LOW);

digitalWrite(4, LOW);

}

// Kva skal skje viss avstanden er mellom 200 og

// 300 cm?

if (cm <= 300 && cm > 200) {

digitalWrite(2, HIGH);

digitalWrite(3, LOW);

digitalWrite(4, LOW);

}

// Kva skal skje viss avstanden er mellom 100 og

// 200 cm?

if (cm <= 200 && cm > 100) {

digitalWrite(2, LOW);

digitalWrite(3, HIGH);

digitalWrite(4, LOW);

}

// Kva skal skje viss avstanden er 100 cm eller mindre?

if (cm <= 100) {

digitalWrite(2, LOW);

digitalWrite(3, LOW);

digitalWrite(4, HIGH);

}

// Kor ofte skal avstanden sjekkast?

delay(100); // Vent 10 millisekund

}

Analyse av koden

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 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 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 funksjonen tek. Her er det int triggerPin og int echoPin som er dei variable 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 .

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 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 .

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 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.

Funksjonar

// 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.

Samla kode for alle avstandsnivåa

// Beskriv kva som skal skje viss avstanden er

// over 300 cm

if (cm > 300) {

digitalWrite(2, LOW); // La pinne 2 vere avslått

digitalWrite(3, LOW); // La pinne 3 vere avslått

digitalWrite(4, LOW); // La pinne 4 vere avslått

}

// 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

}

// Kva skal skje viss avstanden er mellom 100 og

// 200 cm?

if (cm <= 200 && cm > 100) {

digitalWrite(2, LOW); // La pinne 2 vere avslått

digitalWrite(3, HIGH); // Aktiver pinne 3

digitalWrite(4, LOW); // La pinne 4 vere avslått

}

// Kva skal skje viss avstanden er 100 cm eller mindre?

if (cm <= 100) {

digitalWrite(2, LOW); // La pinne 2 vere avslått

digitalWrite(3, LOW); // La pinne 3 vere avslått

digitalWrite(4, HIGH); // Aktiver pinne 4

}

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

}