diff --git a/Sketches/sketch_jan10a-ArduinoInnlevering/sketch_jan10a-ArduinoInnlevering.ino b/Sketches/sketch_jan10a-ArduinoInnlevering/sketch_jan10a-ArduinoInnlevering.ino index a87cd9d..5964d0e 100644 --- a/Sketches/sketch_jan10a-ArduinoInnlevering/sketch_jan10a-ArduinoInnlevering.ino +++ b/Sketches/sketch_jan10a-ArduinoInnlevering/sketch_jan10a-ArduinoInnlevering.ino @@ -1,13 +1,15 @@ -// "ped" = Pedestrian -// Fotgjengerlys og bryter. -int pedGreen = 6; -int pedRed = 7; -int pedSwitch = 11; +/** + * Fotgjengerlys + bryter + * `ped` = pedestrian = fotgjenger + */ +const int pedGreen = 6; +const int pedRed = 7; +const int pedSwitch = 11; // Trafikklys -int trafficRed = 8; -int trafficYellow = 9; -int trafficGreen = 10; +const int trafficRed = 8; +const int trafficYellow = 9; +const int trafficGreen = 10; void setup() { // Pins som skal være output, brukes bare i setup. @@ -34,28 +36,29 @@ void setup() { /** * Lengde på hvor lenge hvert trafikklys, i millisekunder. */ -int redLength = 5000; -int redYellowLength = 2000; -int greenLength = 10000; -int yellowLength = 2000; +const int redLength = 5000; +const int redYellowLength = 2000; +const int greenLength = 10000; +const int yellowLength = 2000; /** * Trafficstates er: - * - -1: Oppstart av programmet. - * - 0: Rødt lys (5 sek) - * - 1: Rødt + gult (2 sek) - * - 2: Grønt (10 sek) - * - 3: Gult (2 sek) + * - -1: Oppstart av programmet/Arduino. + * + * - 0: Rødt lys (5 sek eller `redLength`) + * - 1: Rødt + gult (2 sek eller `redYellowLength`) + * - 2: Grønt (10 sek eller `greenLength`) + * - 3: Gult (2 sek eller `yellowLength`) */ int trafficState = -1; -int redState = 0; -int redYellowState = 1; -int greenState = 2; -int yellowState = 3; +const int redState = 0; +const int redYellowState = 1; +const int greenState = 2; +const int yellowState = 3; /** * Lengder som kan refereres basert på array index - * Array index vil være det samme som "trafficState" + * Array index vil være det samme som `trafficState` */ int trafficLightLengths[] = { // redState @@ -69,7 +72,7 @@ int trafficLightLengths[] = { }; /** - * Antall millisekunder siden "trafficState" var sist endret. + * Antall millisekunder siden `trafficState` var sist endret. */ unsigned long lastStateChange = millis(); @@ -87,18 +90,28 @@ unsigned long pedLastEnd = 0; /** * Antall millisekunder fotgjengere har på å "krysse". */ -int pedLength = 8000; +const int pedLength = 8000; /** * Antall millisekunder mellom hvert "blink" for fotgjengerlyset. */ -int pedBlinkLength = 250; +const int pedBlinkLength = 250; /** * Antall ganger fotgjengerlyset har blinket. */ int pedBlinkCount = 0; +/** + * Maksimum antall ganger fotgjengerlyset skal blinke. + */ +const int pedMaxBlinkCount = 10; + +/** + * Lagre sist gang fotgjengerlys "blinket" (var av). + */ +unsigned long pedLastBlinkChange = 0; + /** * Om fotgjengerne er "aktive", altså at trafikklys skal stoppe (og holde seg på rødt). */ @@ -110,19 +123,100 @@ bool pedActive = false; */ bool pedShouldActivate = false; +/** + * Lagre verdien for når `pedShouldActivate` ble oppdatert. + */ +unsigned long pedShouldActivateTime = 0; + +/** + * Hvor mange millisekunder etter at fotgjengerknappen har blitt trykket inn + * som fotgjengerlys skal aktivere. + * + * I følge oppgaven skal dette være 5 sekunder. + */ +const int pedActivateAfter = 5000; + void loop() { + /** + * Definer en felles verdi som er et resultat av millis(). + * + * Kan hende at denne verdien er noen få millisekunder feil når den brukes i diverse kode nedenfor, + * men det bør ikke være noen merkbar forskjell. + */ unsigned long currentTime = millis(); /** * Sjekk om fotgjengerknappen er trykt og * oppdater verdier basert på dette. + * + * Knappen setter et flagg (`pedShouldActivate`) som sjekkes etter at trafikklys har gått tilbake til rødt. */ - if (analogRead(pedSwitch) == LOW) { + if (analogRead(pedSwitch) == LOW && !pedActive) { pedShouldActivate = true; + pedShouldActivateTime = currentTime; } + /** + * Aktiverer fotgjengerlys. `ped` = pedestrian. + * `pedActive` er som default false, men blir satt til true + * når `pedShouldActivate` er true og trafikklysene har gått tilbake til rødt. + */ if (pedActive) { - // TODO: Oppgave 9 + bool pedLightOn = false; + if (pedBlinkCount == 0) { + pedLightOn = true; + } + + if (currentTime - pedLastStart >= pedLength) { + /** + * Om fotgjengerlyset er på starten av "avsluttingsblink", + * vil det grønne fotgjengerlyset slå seg av. + * + * `pedLastBlinkChange` vil oppdateres og dette sjekkes videre i neste if-setning. + */ + if (pedBlinkCount == 0) { + pedLightOn = false; + pedLastBlinkChange = currentTime; + } + + /** + * Sjekker om `pedLastBlinkChange` er mer eller lik `pedBlinkLength`, + * altså om siste "blink endring" var over 250 ms siden. + * + * `pedLightOn` bool vil "flippes" fra true => false, eller false => true + * som videre påvirker om det grønne fotgjengerlyset lyser. + * + * `pedLastBlinkChange` vil da oppdateres til nåværende millis(). + * + * Hvis `pedLightOn` er true etter dette, vil `pedBlinkCount` inkrementeres. + * Dette vil da bare skje når det grønne fotgjengerlyset lyser igjen + * og ikke mens det har sloknet. + */ + if (currentTime - pedLastBlinkChange >= pedBlinkLength) { + pedLightOn = !pedLightOn; + pedLastBlinkChange = currentTime; + + if (pedLightOn) { + pedBlinkCount++; + } + } + } + + /** + * Sjekker om fotgjengerlyset har blinket 10 ganger (basert på: `pedMaxBlinkCount`) + * og setter da `pedActive` tilbake til false slik at trafikklysene kan begynne vanlig syklus. + */ + if (pedBlinkCount >= pedMaxBlinkCount) { + pedActive = false; + pedLightOn = false; + } + + /** + * Om `pedLightOn` er true, vil pedGreen lyse, hvis ikke er den av. + * Noe lignende gjelder for `pedRed` bare at den sjekker om fotgjengermodus er aktiv (`pedActive`). + */ + digitalWrite(pedRed, !pedActive ? HIGH : LOW); + digitalWrite(pedGreen, pedLightOn ? HIGH : LOW); } /** @@ -137,14 +231,49 @@ void loop() { return; } + /** + * `lightLength` er antall millisekunder som nåværende lys skal lyse. + * Dette hentes fra array'et trafficLightLengths, som igjen bare refererer til satte variabler. + */ int lightLength = trafficLightLengths[trafficState]; - if (!pedActive && currentTime - lastStateChange >= lightLength) + + /** + * Denne if-setningen sjekker to forskjellige ting: + * + * 1: `pedActivateNow` + * Aller først sjekker den om fotgjengerknappen har blitt trykket. + * 5 sekunder etter (basert på variabelet `pedActivateAfter`) skal trafikklys avslutte syklusen. + * Dette vil da skje tidligere enn vanlig i visse tilfeller. + * Om trafikklys allerede er på vei til å avslutte syklusen, kan det hende at dette skjer før 5 sekunder. + * + * 2: `incrementTrafficState` + * Den vanlige sjekken er om `trafficState` skal inkrementes. Det vil da si at trafikken går som vanlig. + */ + bool pedActivateNow = (pedShouldActivate && currentTime - pedShouldActivateTime >= pedActivateAfter); + bool incrementTrafficState = (!pedActive && currentTime - lastStateChange >= lightLength); + if (pedActivateNow || incrementTrafficState) { + /** + * Definer standard lysverdier for trafikklys, overskrives i switch nedenfor. + */ + int redLight = LOW; + int yellowLight = LOW; + int greenLight = LOW; + + /** + * Inkrement `trafficState` som da sammenlignes med red-, yellow- eller greenState + */ trafficState++; + + /** + * Siden `trafficState` ble inkrementert, oppdater lastStateChange-verdien til mest nylig millis()-verdi. + */ lastStateChange = currentTime; /** * Trafikklys er ferdig med syklus, gå tilbake til rødt. + * Hvis `trafficState` er mer enn 3, betyr det at siste del av syklus (gult lys) er ferdig. + * Dermed blir denne verdien resettet tilbake til 0 for å starte syklusen på nytt. */ if (trafficState > 3) { @@ -157,38 +286,47 @@ void loop() { { pedLastStart = currentTime; pedActive = true; + pedBlinkCount = 0; } } + /** + * `trafficState` er en verdi som sammenlignes med variablene som har en `State` suffix. + * Dette brukes for å sjekke hvilke trafikklys som skal lyse. + * + * Som default er red-, yellow- og greenLight satt til LOW. + * Disse oppdateres basert på hvilke trafikklys som skal lyse, som igjen er basert på trafficState. + * Etter switch-case skrives disse til LED og de aktiveres ettersom. + */ switch (trafficState) { // Rødt lys - case 0: - digitalWrite(trafficRed, HIGH); - digitalWrite(trafficYellow, LOW); - digitalWrite(trafficGreen, LOW); + case redState: + redLight = HIGH; break; // Rødt + gult lys - case 1: - digitalWrite(trafficRed, HIGH); - digitalWrite(trafficYellow, HIGH); - digitalWrite(trafficGreen, LOW); + case redYellowState: + redLight = HIGH; + yellowLight = HIGH; break; // Grønt lys - case 2: - digitalWrite(trafficRed, LOW); - digitalWrite(trafficYellow, LOW); - digitalWrite(trafficGreen, HIGH); + case greenState: + greenLight = HIGH; break; // Gult lys - case 3: - digitalWrite(trafficRed, LOW); - digitalWrite(trafficYellow, HIGH); - digitalWrite(trafficGreen, LOW); + case yellowState: + yellowLight = HIGH; break; } + + /** + * Oppdater trafikklys etter de verdiene som er satt i switch-case. + */ + digitalWrite(trafficRed, redLight); + digitalWrite(trafficYellow, yellowLight); + digitalWrite(trafficGreen, greenLight); } }