I de fleste artiklene som jeg har lagt ut har vi ganske utbredt bruk av delay-funksjonen. Når Arduino er inne i en delay-funksjon, vil den ikke ha mulighet til å gjøre noe annet samtidig. Hvis vi for eksempel trykke på en knapp mens delay sørger for å holde en lysdiode aktiv i en viss periode, vil ikke knappetrykket registreres. Da sier vi at koden vår "blokkerer". 

Det er flere måter å unngå dette på. De to viktigste er interrupt, som vi skal se på i en annen artikkel, og bruk av den innebygde funksjonen millis som vi skal prøve ut i denne artikkelen.

Millis bruker en funksjon som kjører i bakgrunnen på Arduinoen (og egentlig bruker "timer interrupts"). For hvert millisekund oppdaterer funksjonen en teller, som starter på null hver gang vi starter programmet vårt. Det vil si at når vi kaller funksjonen millis() i programmet vårt, returnerer den antall millisekunder som har gått siden programmet startet.

Eksempel på bruk av millis, men med delay:

Her bruker vi "Hello world"-eksempelet, men skriver ut tiden til serieporten for hvert blink.

unsigned long tidNaa; //Her må vi bruke unsigned long for å få lagret store nok tall
void setup() {
pinMode(9, OUTPUT); //Kobler lysdioden til pinne 9
Serial.begin(115200); //Setter opp serieporten med 115200 baud
}

void loop() {
digitalWrite(9, HIGH); //Tenner lysdioden
delay(1000); //Forsinkelse ett sekund
digitalWrite(9,LOW); //Slukker lysdioden
delay(1000); //Forsinkelse ett sekund
tidNaa = millis(); //Sjekker tiden med millis og lagrer resultatet i "tidNaa"
Serial.print("Tid: "); //Skriver ut tekst
Serial.println(tidNaa); //Skriver ut den målte tiden
}

Resultatet på serieporten vil bli noe slikt:

Tid: 1999
Tid: 3999
Tid: 5999
Tid: 8000
Tid: 10000
Tid: 12001
Tid: 14001
Tid: 16002
Tid: 18001

Vi ser at antall millisekunder skrives ut ca. hvert andre sekund.

Hva så hvis vi ønsker å sjekke om en knapp er trykt inn i denne loop'en? Prøv ut det utvidede eksempelet under og se hva som skjer.

unsigned long tidNaa; //Her må vi bruke unsigned long for å få lagret store nok tall
void setup() {
pinMode(2, INPUT_PULLUP); //Koble en knapp mellom pinne 2 og jord (GND)
pinMode(9, OUTPUT); //Kobler lysdioden til pinne 9
Serial.begin(115200); //Setter opp serieporten med 115200 baud
}

void loop() {
digitalWrite(9, HIGH); //Tenner lysdioden
delay(1000); //Forsinkelse ett sekund
digitalWrite(9,LOW); //Slukker lysdioden
delay(1000); //Forsinkelse ett sekund
tidNaa = millis(); //Sjekker tiden med millis og lagrer resultatet i "tidNaa"
Serial.print("Tid: "); //Skriver ut tekst
Serial.println(tidNaa); //Skriver ut den målte tiden
if(digitalRead(2)==LOW){ //Hvis pinne 2 er LOW er knappen trykt inn
Serial.println("Knapp trykket");
}
}

Det vi ser at knappen virker bare rett etter at tiden er skrevet til serieporten. Dermed må vi enten være utrolig heldige med når vi trykker, eller sitte og holde inn knappen til det reagerer. Dette virker som en ganske dårlig løsning.

En mye bedre løsning vil være å bruke millis til å få lysdioden til å blinke også, når den likevel står og tar tiden på programmet.
Her vil jeg bruke en litt "spansk" løsning, for å slippe å bruke en variabel for å "huske" om lysdioden er av eller på:
    digitalWrite(9,!digitalRead(9));
Funksjonen digitalWrite fungerer som vanlig, vi angir hvilken pinne det gjelder og deretter hvilken verdi. Vrien her er at vi først leser tilstanden til pinne 9 med digitalRead,og deretter bruker utropstegnet foran for å invertere den avleste verdien. Hvis vi da leser verdien 0 (LOW), inverteres denne og vi skriver 1 (HIGH), og omvendt.


unsigned long tidNaa; //Her må vi bruke unsigned long for å få lagret store nok tall
unsigned long skiftetSist=0; //Vi må ta vare på tiden når lysdioden sist skiftet status
unsigned long intervall = 500; //Antall millisekunder mellom hvert skift (500ms gir 1Hz, altså ett blink i sekundet)

void setup() {
 pinMode(2, INPUT_PULLUP); //Koble en knapp mellom pinne 2 og jord (GND)
 pinMode(9, OUTPUT); //Kobler lysdioden til pinne 9
 Serial.begin(115200); //Setter opp serieporten med 115200 baud
}
void loop() {
 tidNaa = millis(); //Sjekker tiden med millis og lagrer resultatet i "tidNaa"
 if (tidNaa - skiftetSist > intervall) { //Trekker "skiftetSist" fra "tidNaa". Hvis resultatet er større enn "intervall" skal lysdioden skifte
skiftetSist = tidNaa; //Lagrer den nye tiden i "skiftetSist"
digitalWrite(9, digitalRead(9)); //Bytter verdien på pinne 9
Serial.print("Tid: "); //Skriver ut tekst
Serial.println(tidNaa); //Skriver ut den målte tiden
 }
 if (digitalRead(2) == LOW) { //Hvis pinne 2 er LOW er knappen trykt inn
Serial.print("Knapp trykket ");
Serial.println(millis()); //Skriver ut når knappen ble trykket
 }
}


Hvis du nå tester koden, vil du se at du kan trykke knappen når som helst, og den vil fremdeles reagere. Nå får vi derimot et annet problem, og det er at mikrokontrolleren rekker å registrere trykket mange ganger for hvert trykk. Det skal vi løse i neste eksempel. (Kommer snart..)