Als ich den Code säuberte und passende Stellen zu einer While-Schleife umbaute, fiel mir auf, dass die Logik nicht ganze passte. Die Abfrage der verstrichenen Zeit grenzte die einzelnen Ampelphasen überhaupt nicht eindeutig ab.
Die überprüfung der Phase fand nur mit einer "ist die Differenz von millis() - Zeitstempel größer als Pause?" statt. Und im nächsten Fall: "ist die Differenz von millis() - Zeitstempel größer als Pause + Pause?" Hier schlägt nun wieder einmal die Endlosschleife zu, denn wenn:
"ist die Differenz von millis() - Zeitstempel größer als Pause + Pause?"
zutrifft, dann trifft natürlich auch die vorherige Phase zu:
"ist die Differenz von millis() - Zeitstempel größer als Pause?"
es werden also nochmal beide Phasen ausgeführt. Durch die Trägheit der LEDs war das aber nicht wirklich zu sehen. Die LEDs wirkten zwar als wäre sie aus aber die "glimmten" noch ein bisschen. ;)
Meine Logik damit das verhindert wird ist jetzt:
"ist die Differenz von millis() - Zeitstempel größer als Pause?" UND "ist die Differenz von millis() - Zeitstempel kleiner als Pause + Pause?"
Jetzt glimmt nix mehr!
Bitteschön:
/* Ampel mit While */ // reichen da nicht bytes? oO byte red = 9; // Verkehrsampel Rot byte yel = 8; // Verkehrsampel Gelb byte gre = 7; // Verkehrsampel Grün byte sig = 5; // "Signal kommt" liefert dem Fußgänger zurück, ob er gedrückt hat oder nicht. byte wred = 3; // Fußgängerampel Rot byte wgre = 2; // Fußgängerampel Grün byte but = 6; // Button Pin byte safe = 0; // war butr für buttonread // Pausen int pred = 3000; // 3 Sekunden Rot int pyel = 1000 ; // 1 Sekunde Gelb int pgre = 5000; // 5 Sekunden Grün int psafety = 1000; // Puffer für Fußgänger, bis Verkehrsampel wieder auf grün springt unsigned long time; // the setup routine runs once when you press reset: void setup() { // die pins als output. pinMode(red, OUTPUT); pinMode(yel, OUTPUT); pinMode(gre, OUTPUT); pinMode(sig, OUTPUT); pinMode(wred, OUTPUT); pinMode(wgre, OUTPUT); pinMode(but, INPUT); time = millis(); // einmal die aktuelle Zeit festlegen digitalWrite(red, HIGH); // erstmal alles schön auf Rot digitalWrite(wred, HIGH); // erstmal alles schön auf Rot } // the loop routine runs over and over again forever: void loop() { /* Wenn der Button etwas anderes als 0 zurück gibt hat ihn wohl jemand gedrückt. Wenn das so ist, setze safe auf 1 und schalte die "Signal kommt" LED an. */ if(digitalRead(but) != 0) { safe=1; digitalWrite(sig,HIGH); } /* Solange wie safe kleiner oder gleich 1 ist, läuft die Verkehrsampel. */ while (safe <= 1) { digitalWrite(wred, HIGH); // Fußgängerampel auf Rot und bleibt auch so /* Nun vergleichen wir immer Schritt für Schritt, ob die abgelaufene Zeit GRÖßER ist als für diese Phase vorgesehen ABER AUCH ob sie bis jetzt noch UNTER der Zeit der übernächste Phase liegt. */ if (millis() - time > pred && millis() - time < pred + pyel)digitalWrite(yel,HIGH); // LÄNGER als Pause Rot aber KÜRZER als Pause Rot + Pause Gelb? -> schalte Gelb dazu. if (millis() - time > pred + pyel && millis() - time < pred + pyel + pgre) // LÄNGER als Pause Rot + Pause Gelb aber KÜRZER als Pause Rot + Pause Gelb + Pause Grün? { digitalWrite(red,LOW); // schalte Rot aus digitalWrite(yel,LOW); // schalte Gelb aus digitalWrite(gre,HIGH); // schalte Grün an } if (millis() - time > pred + pyel + pgre && millis() - time < pred + pyel + pgre + pyel) // LÄNGER als Pause Rot + Pause Gelb + Pause Grün aber KÜRZER als Pause Rot + Pause Gelb + Pause Grün + Pause Gelb { digitalWrite(gre,LOW); // schalte Grün aus digitalWrite(yel,HIGH); // schalte Gelb an } if (millis() - time > pred + pyel + pgre + pyel) // Hier prüfen wir nur noch obs länger ist als... denn die Anderen schließen sich ja schon vorher aus. { digitalWrite(yel,LOW); // schalte Gelb aus time = millis(); // Zeit reseten digitalWrite(red,HIGH); // schalte Rot an if (safe == 1)safe++; // Falls jemand den Knopf gedrückt hatte und safe damit auf 1 steht, ist es Zeit zur Fußgänger Schleife zu springen. Dazu erhöhren wir safe um 1 also auf 2. } break; // raus aus der while Schleife } while (safe == 2) // wenn der Knopf gedrückt wurde (safe = 1) UND der Verkehr einmal durchlief (safe = 1 + 1) dann mache... { digitalWrite(red, HIGH); // Verkehrsampel auf Rot.. sollte sie zwar schon, aber doppelt hält besser. Geht ja schließlich um die Sicherheit ;) if (millis() - time > psafety && millis() - time < psafety + pgre) // LÄNGER als Sicherheitspuffer aber KÜRZER als Sicherheitspuffer + Pause Grün? { // falls dem so ist... digitalWrite(wred,LOW); // Fußgänger Rot aus digitalWrite(sig,LOW); // "Signal kommt" aus digitalWrite(wgre,HIGH); // Fußgänger Grün an } if (millis() - time > psafety + pgre && millis() - time < psafety + pgre + psafety) // LÄNGER als Sicherheitspuffer + Pause Grün aber KÜRZER als Sicherheitspuffer + Pause Grün + Sicherheitspuffer? { // falls ja digitalWrite(wgre,LOW); // Fußgänger Grün aus digitalWrite(wred,HIGH); // Fußgänger Rot an } if (millis() - time > psafety + pgre + psafety) // Wenn wieder Rot ist, warte noch die Safety Zeit ab (Safety + Grünphase + Safety) { time = millis(); // Und resete die Zeit, damit es von vorn los gehen kann safe = 0; // Setzte Safe auf 0 damit wieder mind. 1x der Vekehr läuft } break; // raus aus der Schleife } delay(1); // kleine Pause gg. Überlastung }
Schicker Hintergrund! *____*
AntwortenLöschenist das denn safe, jedes mal millis() aufzurufen? ist mir jetzt nur beim ueberfliegen aufgefallen. wenn du also sowas machst wie
AntwortenLöschenif (millis() - time > psafety && millis() - time < psafety + pgre)
dann kann es passieren, dass millis() natuerlich zwei mal unterschiedliche rueckgabewerte hat.
Stimmt. Aber da wir uns Zeittechnisch im ms Bereich bewegen und der "aber kleiner als" Teil mindestens eine ganze Sekunde drauf gebrummt bekommt, sollte es immer passen. Aber sauber ist es nicht.
AntwortenLöschen