Kategori: Tilstandsmaskin
Treff: 7612

En tilstandsmaskin er en måte å skrive et program på som lar oss kontrollere flyten basert på hendelser og forskjellige moduser.

Tilstandsmaskiner kan brukes i veldig mange typer programmer. Et godt eksempel kan være et menysystem med flere nivåer, hvor du bruker knapper til å endre nivå eller tilstand, mens du hele tiden har en eller annen form for display som viser hvor i menyen du er.

Vi skal starte med å lage en veldig enkel tilstandsmaskin med bare en knapp og en lysdiode. Hendelsen vi skal endre tilstand på er da selvsagt når knappen blir trykt inn. De to forskjellige modusene for lysdioden er da naturlig nok AV eller PÅ, eller LEDOFF og LEDON som vi kaller det i programmet. Jeg skal ikke forklare koden nærmere her, men prøver å kommentere godt slik at koden blir lesbar og forståelig.

I eksempel to utvider vi dette med en ekstra tilstand hvor lysdioden blinker.

Eksempel 1


Enkelt eksempel

 
/*
 * Arduino - enkel tilstandsmaskin
 * 
 */
#define LEDOFF 0 //Tilstand 0
#define LEDON 1 //Tilstand 1

 void setup() {
pinMode(2,INPUT_PULLUP); //Setter opp pinne for trykknappen
pinMode(13,OUTPUT); //Bruker pinne 13 (med innebygd LED) som utgang
Serial.begin(9600); //Bruker serie-konsollet for å skrive debug-informasjon
}

int tilstand=LEDOFF; // Oppretter tilstand-variabelen og setter den til "LEDOFF" (0) i starten.

void loop() {
if(!digitalRead(2)){ //Sjekker om knappen er trykt inn (knappen kortslutter pinnen til jord,
//så vi må sjekke om pinnen er 0)
  while(!digitalRead(2)); //Fjerning av prell (debounce) Løkken fortsetter til knappen slippes.
  tilstand++; //Endrer tilstand (øker med 1)
  if(tilstand>1) tilstand=0; //Siden vi har bare 2 tilstander, må vi sette den til 0 igjen
//hvis den blir 2 (eller mer)
  Serial.print("Tilstand: "); //Skriver til serieporten
  Serial.println(tilstand); //Skriver tilstandsnummeret til seriporten
    delay(50);  //Ekstra fjerning av prell (debounce)
  }
if(tilstand==LEDOFF){ //Hva skal gjøres hvis tilstanden er "LEDOFF"
  digitalWrite(13,LOW); //Slukker lysdioden på pinne 13
  }
if(tilstand==LEDON){ //Hva skal gjøres hvis tilstanden er "LEDON"
  digitalWrite(13,HIGH); //Tenner lysdioden på pinne 13
  }
 
}
 

Eksempel 2


Eksempel 2

Et litt mer mer avansert eksempel:

/*
 * Arduino - enkel tilstandsmaskin
 * 
 */
/*
 * Arduino - enkel tilstandsmaskin
 * 
 */
#define LEDOFF 0 //Tilstand 0
#define LEDON 1 //Tilstand 1
#define LEDBLINK 2 //Tilstand 2

long sisteSkift=millis(); //Lager, og initialiserer en variabel for når lysdioden skiftet tilstand sist
//Funksjonen millis() returnerer antall millisekunder siden programmet startet
//Vi bruker long, siden dette tallet kan bli større enn den en int kan lagre
long tid; //Variabel for å lagre "gjeldende tid"

void setup() {
pinMode(2,INPUT_PULLUP); //Setter opp pinne for trykknappen
pinMode(13,OUTPUT); //Bruker pinne 13 (med innebygd LED) som utgang
Serial.begin(9600); //Bruker serie-konsollet for å skrive debug-informasjon
}

int tilstand=LEDOFF; // Oppretter tilstand-variabelen og setter den til "LEDOFF" (tilstand 0) i starten.

void loop() {
if(!digitalRead(2)){ //Sjekker om knappen er trykt inn (knappen kortslutter pinnen til jord, så vi må
// sjekke om pinnen er 0)
while(!digitalRead(2)); //Fjerning av prell (debounce) Løkken fortsetter til knappen slippes.
tilstand++; //Endrer tilstand (øker med 1)
if(tilstand>2) tilstand=0; //Siden vi har bare 3 tilstander, må vi sette den til 0 igjen hvis den
//blir 3 (eller mer)
Serial.print("Tilstand: "); //Skriver til serieporten
Serial.println(tilstand); //Skriver tilstandsnummeret til seriporten
delay(50);  //Ekstra fjerning av prell (debounce)
}
if(tilstand==LEDOFF){ //Hva skal gjøres hvis tilstanden er "LEDOFF"
digitalWrite(13,LOW); //Slukker lysdioden på pinne 13
  }
if(tilstand==LEDON){ //Hva skal gjøres hvis tilstanden er "LEDON"
digitalWrite(13,HIGH); //Tenner lysdioden på pinne 13
  }
if(tilstand==LEDBLINK){ //Hva skal gjøres hvis tilstanden er "LEDBLINK"
  tid=millis(); //For å unngå å bruke "delay" bruker vi millis for å holde styr på hvordan
// lysdioden skal blinke. Dette gjør at vi kan skifte tilstand med knappen
// når som helst, uansett hvor lange blink vi har
  if(tid-sisteSkift>400) { //Sjekker om det er mer enn 400 ms siden sist lysdioden skiftet tilstand.
    digitalWrite(13,!digitalRead(13)); //Leser nivået på pinne 13, inverterer det, og skriver tilbake
//til pinnen (en "toggle"-funksjon)
    sisteSkift=tid; //Nå har vi skiftet tilstand, så vi setter variabelen sisteSkift
//til den nåværende tiden.
    }
  } 
}

 

Oppgaver


Oppgaver:

1: Start på et nytt prosjekt. Lag en tilstandsmaskin med 4 tilstander. Hver tilstand skal lyse opp eller blinke hver sin lysdiode, gjerne med hver sin farge. Tilstand skal endres med et knappetrykk. Skriv tilstandene underveis serieporten (Serial Monitor)

2: Bruk teknikken du har lært til å realisere et enkelt trafikklys med 3 lysdioder.

 

Løsningsforslag


Løsningsforslag:

Oppgave 1:  

Kommer