Arduino programmering
Det finnes mange forskjellige programmeringsspråk, og språket man bruker for Arduino, er en såkalt dialekt, det vil si en variant av C og C++ som inneholder litt færre funksjoner. Man kan også skrive kode til Arduino i en del andre språk, men vi anbefaler at man holder seg til den koden som følger med eksemplene fra SparkFun. Når man etter hvert har koplet opp alle kretsene og forstår den koden som brukes der, kan man eventuelt vurdere å prøve å konvertere koden, det vil si skrive den på nytt i et annet språk. Ett slikt språk er JavaScript. Dette er et språk primært for programmering av nettsider og kan være et nyttig tilskudd til dataelektronikerens fremtidige verktøyskrin.
Kommentar
Når man åpner opp et eksempel i Arduino IDE, vil man se et stort vindu hvor all koden til prosjektet er skrevet. Ofte begynner eksempelet med en kommentar. Man bruker en kommentar hvis man ønsker å skrive noe som er ment som informasjon til en selv eller andre som skal lese koden. Kommentaren blir ikke kjørt av datamaskinen. Man kjenner igjen en kommentar på at linjen enten begynner med to skråstreker, // hvis det er en enlinjes kommentar, eller med /* hvis det er en flerlinjes kommentar. Man avslutter en flerlinjes kommentar med */
// Dette er en enlinjes kommentar
/*
Dette er en
kommentar over
flere linjer
*/
Kommentarene, selv om de ikke «gjør noe», er en veldig viktig del av koden. Uten kommentarer som beskriver hva selve koden gjør, kan det være vanskelig å forstå hva som foregår. Det er veldig lurt å skrive så grundige kommentarer som mulig, særlig til å begynne med.
Libraries
Når man leser videre i eksempelkoden, vil man noen ganger se en linje som begynner med #.
Dette er en måte å bruke kode som andre har skrevet tidligere, i ditt prosjekt. Et eksempel kan være dersom du ønsker å bruke en LCD-skjerm. Da vil du ønske å hente inn kode fra et såkalt bibliotek/library som heter LiquidCrystal. Dette gjør du med kommandoen
#include <LiquidCrystal.h>
I større prosjekter kan man fort bruke en håndfull eller flere libraries. Man kan finne en oversikt over de fleste på denne siden: http://www.arduino.org/learning/reference#tab_8611.
Funksjoner
Fortsetter man videre nedover koden, kommer man alltid til to såkalte funksjoner, setup() og loop().
En funksjon (også kalt prosedyre, metode eller rutine) er en samling kode som utfører en spesifikk oppgave og som er uavhengig av resten av koden. Ofte lager man funksjoner for å unngå å skrive det samme flere ganger. Det er også lettere å forstå kode som bruker funksjoner, særlig hvis man har gode navn på funksjonene. Basert på navnet skjønner man at funksjonen spillMelodi() spiller en melodi. Det kan være vanskeligere å forstå all koden som funksjonen består av, det vil si alle instruksjonene som står mellom { og } etter navnet på funksjonen.
De to funksjonene nevnt over, setup() og loop(), er spesielle systemfunksjoner som til sammen utgjør strukturen i programmet ditt. I setup() forteller vi hvilke deler av Arduino-kortet vi ønsker å bruke, og hva de skal gjøre, om de er input eller output, samt hvilke biblioteker vi ønsker å bruke. For eksempel kan det stå
pinMode(13, OUTPUT); //
Dette betyr at pinne 13 skal være en output, for eksempel en lysdiode.
Setup()-funksjonen kjøres kun når man laster opp koden til en Arduino, eller når en USB-kabel koples til. Man starter også serieporten fra setup().
Loop()-funksjonen kjører når setup() er ferdig og vil kjøre om og om igjen inntil en laster opp et nytt program til Arduinoen. Det er i loop() man har oppgavene man ønsker å få utført.
For å gå tilbake til eksempelet ovenfor med pin 13, vil man da typisk en plass i loop() ha linjen:
digitalWrite(13, HIGH); //
Denne linjen gir strøm til dioden koplet til pin 13 slik at den vil begynne å lyse.
Programmeringsspråkets syntaks, datatyper og struktur
Mye av koden i skissene du ser i eksemplene i Arduino IDE eller i SIK-guideboka, består av kode som fremdeles kan virkes litt kryptisk, ting som:
int x;
eller
int noenTall[] = {3,1,4,1,5};
Eller ting som er enda mer kryptisk, for eksempel
for (int x = 0; x < 10; x++) {
Serial.println(x);
}
Dette er kanskje ikke så lett å forstå enda, men det vil gi mening etter hvert.
Håndverk og kunst
Programmering blir ofte omtalt som en blanding av håndverk og kunst. Når man er ny, er nok det viktigste å lære seg håndverket, og det finnes mange gode guider til programmering for Arduino. Hvis du går til hjemmesiden til Arduino > Learning > Reference, finnes det en oversikt som forklarer alle de forskjellige ordene og tegnene som kan benyttes. Her kommer en kortfattet oversikt:
Syntaks er på en måte grammatikken i et språk, det vil si hva som er lov å skrive, og hva som gir mening for datamaskinen. Hvis syntaksen ikke er riktig, vil programmet ikke kompilere, det vil si at programmet ikke greier å oversette koden til et språk som datamaskinen forstår, og den vil ikke kunne utføre instruksjonene dine. Hvis du har skrevet noe feil, må du debugge koden, det vil si finne feil. Når du har rettet noen (mistenkte) feil, kan du kompilere på nytt og se om det fungerer.
Datatypen definerer hva slags data vi jobber med, i den forstand at datatypen bestemmer hvilke verdier dataene kan ha, og hvilke operasjoner som kan gjøres med disse verdiene. For eksempel vil man ikke kunne legge sammen tallet 3 og en elefant – de har to forskjellige datatyper, de er ikke samme ting.
Strukturen i programmeringsspråket betyr i denne sammenhengen hvordan koden er skrevet, i hvilken rekkefølge ting kommer, og hvilke funksjoner som blir brukt.
Variabler brukes til å lagre data. Eksempel: Man lagrer verdien 3 i en variabel som heter x ved å skrive
x = 3;
Variabler kan deklareres, det vil si at man setter av en plass i minnet, uten å legge en verdi der:
int x;
boolean y; // vi har reservert en plass til en boolsk variabel som skal hete y.
Man kan også sette variablen til en bestemt verdi samtidig med deklareringen. Dette kalles tilordning:
int x = 20;
boolean y = true;
Noen datatyper
int: 16-bits verdi mellom –32 768 og 32 767int x = 12;x++; // x økes med 1, til 13
float/double:
Desimaltall, verdier fra –3.4028235E+38 til 3.4028235E+38. Desimaltall i programmering oppfører seg ikke nødvendigvis slik man forventer, særlig hvis man prøver å kombinere dem med heltall. Eksempel:
int x;
int y;
float z;
x = 1;
y = x / 2; // y er nå 0, siden en int bare holder heltall
z = (float)x / 2.0; // z er nå 0,5 (det viktige her er å faktisk skrive 2.0, ikke 2 – da blir det tolket som int). Ved å skrive (float) foran x tvinger vi x til å tolkes som en float i stedet for en int.
char:
En char er bare ett enkelt tegn, en byte. Man kan sette en char-variabel med et hvilket som helst tegn fra ASCII-tabellen, enten gitt som char (det vil si selve tegnet) eller som desimalverdien.
char x = ‘A’;
char x = 65; // samme resultat
boolean:
true eller false // Har det regnet i dag? Spørsmålet er enten sant eller usant.
Boolean regnetIDag = false;
array:
En samling av indekserte variabler.
int etArray[6]; // her reserverer vi en plass til en tabell som kan holde fem heltall. Den ekstra plassen er til en «null-character», som avslutter/lukker arrayet.
int noenTall[] = {1,9,3,7,5}; // Her har vi deklarert en array og tilordnet den fem heltall.
char noenTegn[5] = "jepp"; // Bokstaver i hermetegn kalles en string. Char arrays må også være én større enn verdien arrayet skal inneholde, i likhet med vanlige arrays.
For å hente eller endre verdier i en array:
noenTall[0] returnerer 1 – det første tallet/den første posisjonen i arrayet.
noenTall[6] gir feilmelding. Det finnes ikke en syvende posisjon i arrayet.
noenTall[1] = 6; // Bytter ut det andre tallet i arrayet, en 9-er, med en 6-er.
OBS: Arrayer begynner på 0. Det vil si at det første tallet i et array har index/posisjon 0, ikke 1. Se eksempelet ovenfor.
Aritmetikk
int x;
Int y;
x = 7 / 3; // x blir satt til 2
y = x + 5; // legger fem på verdien til x og lagrer den nye verdien som y.
x++; // samme som x = x + 1;
y /= 2; // samme som y = y / 2;
Sammenlikninger
x == y // x er lik y
x != y // x er ulik y
x <= y // x er mindre eller lik y
Logiske operatorer
x > 0 && x < 1 // OG – sann hvis begge er sanne
x > 0 || x < 2 // ELLER – sann hvis minst én er sann
!x < 0 // IKKE – sann hvis uttrykket er usant
KontrollstrukturerKontrollstrukturer brukes for å styre flyten i programmet basert på valg brukeren tar eller andre situasjoner hvor det er flere alternativer å velge mellom. Det å styre flyten i programmet basert på valg som blir gjort og forskjellige situasjoner som oppstår, er i ganske stor grad kjernen i det programmering handler om.
Nedenfor er eksempler på syntaksen til to forskjellige kontrollstrukturer.
If-løkkerIf-løkker (engelsk: loop) kan være veldig nyttige dersom du vil styre flyten i programmet basert på valg brukeren tar, eller hvis det finnes flere alternativer.
int alder // brukeren av programmet må skrive inn sin alder via tastaturet
.…
if (alder < 18)
{
// “Du er under 18 år”;
}
if (alder > 18)
{
// “Du er over 18 år”
}
else
{
// “Du er nøyaktig 18 år!”
}
En annen nyttig såkalt kontrollstruktur er switch. Man kan gjøre det samme som med if-løkker, og det er litt smak og behag hva man bruker. Mange bruker if der man har bare et par mulige utfall, og switch i tilfeller hvor det er flere valg (og spesielt hvis de henger sammen («Vil du spise fårikål, pizza, taco, indisk eller grøt til middag?»).
Switch-strukturen
switch (ønsketmiddag) {
case fårikål:
// hvis ønsketmiddag er lik fårikål, server fårikål
break;
case pizza:
// hvis ønsketmiddag er lik pizza, server pizza
break;
// .… osv
default:
// hvis ingen av alternativene – gjør følgende
// default er valgfritt
}
Det finnes selvsagt flere ord, konsepter og strukturer som må til før man virkelig forstår programmering med Arduino. Som med all programmering er det aller viktigste å faktisk skrive kode. Man må prøve, feile, endre og etter hvert får man det inn i fingrene. Men uansett er dette noen av de mest sentrale tingene du vil komme borti når du skal sette i gang.