Ampelschaltung mit millis()

Hallo zusammen,

Folgendes will ich programmieren: Eine Ampelschaltung mit 3 Ampeln, 2 davon laufen immer ihre Zustände durch, während die dritte abhängig von einem Ultraschallsensor ist. Misst dieser einen Abstand <20cm, so soll Ampel 3 für einen bestimmten Zeitintervall umschalten, während Ampeln 1 und 2 jeweils Rot (beim Code hier aus, da zur Vereinfachung vorerst nur 3 rote LEDs verwendet). Nun hänge ich am Problem, wie ich den Zustand der 3. Ampel in die switch/case-Konstruktion implementieren kann. So wie ich es sehe, brauche ich ja noch eine weitere if-Schleife (if (cm < 20) ), nur weiß ich hier nicht wie/wo ich sie einfügen muss…
Ich bin für jede Hilfe dankbar!

// Ampel Belegung der Ausgaenge
const byte RotPin1 = 6;
const byte RotPin2 = 9;
const byte RotPin3 = 11;
//
const boolean ein = HIGH;
const boolean aus = LOW;
//
const int ZEITROTPHASE1 = 3000;
const int ZEITROTPHASE2 = 3000;
const int ZEITROTPHASE3 = 3000;
const int ZEITNIX1 = 1000;
const int ZEITNIX2 = 1000;
const int ZEITNAHDRAN = 2000;
unsigned long ampelMillis;
unsigned long ampelIntervall;
long laenge;
long cm;
//
enum ZUSTAENDE {ROT1, ROT2, ROT3, NIX1, NIX2, NAHDRAN};
byte zustand = ROT1;
//
void setup() {
  // Definiert die Pins als Ausgang
  pinMode(RotPin1, OUTPUT);
  pinMode(RotPin2, OUTPUT);
  pinMode(RotPin3, OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(5,INPUT);
  pinMode(7,OUTPUT);
  Serial.begin (9600);
}

void loop() {
  
digitalWrite(3,LOW);
delayMicroseconds(2);
digitalWrite(3,HIGH);
delayMicroseconds(5);
digitalWrite(3,LOW);

laenge = pulseIn(5,HIGH);
cm = (laenge*34)/2000;
Serial.print(cm);
Serial.println("cm");
delay(500);
// bis hierhin nur Ultraschallsensor  
      
  if (millis() - ampelMillis >= ampelIntervall) {
    switch (zustand) {
      case ROT1:
        digitalWrite(RotPin1, HIGH);
        zustand = NIX1;
        ampelMillis = millis();
        ampelIntervall = ZEITROTPHASE1;
        break;
        //
      case NIX1:
        digitalWrite(RotPin1, LOW);
        digitalWrite(RotPin2, LOW);
        zustand = ROT2;
        ampelMillis = millis();
        ampelIntervall = ZEITNIX1;
        break;
        //
      case ROT2:
        digitalWrite(RotPin2, HIGH);
        zustand = NIX2;
        ampelMillis = millis();
        ampelIntervall = ZEITROTPHASE2;
        break;
        //
     case NIX2:
        digitalWrite(RotPin1, LOW);
        digitalWrite(RotPin2, LOW);
        zustand = ROT1;
        ampelMillis = millis();
        ampelIntervall = ZEITNIX2;
        break;
    }
  }
  }

Spontane Idee:

enum ZUSTAENDE {ROT1, ROT2, ROT3, NIX1, NIX2, NIX3};
...
if (cm < 20) {zustand = ROT3;}
if (millis() - ampelMillis >= ampelIntervall) {
...
case ROT3:
...
case NIX3:
...

agmue: Spontane Idee: ....

Du enttäuscht mich.

Ich habe mich schon auf den endlichen Automaten gefreut! ;)

guntherb: Ich habe mich schon auf den endlichen Automaten gefreut! ;)

Und ich dachte, das ist ein endlicher Automat ;)

Ein schönes Beispiel, wie jemand den von mir empfohlenen Lesestoff gelesen und für seine Verhältnisse adaptiert hat. Die Feinheiten bekommt er sicher auch noch hin :)

agmue:
Spontane Idee:

So wie ich deine Idee verstehe, läuft dann allerdings Ampel 3 bei der Zustandsänderung mit, d.h. erst wird Ampel 1, dann 2 und dann 3 Grün. Ich will aber, dass Ampel 3 NUR im Falle des Abstands <20cm umschaltet…

LoveBasketball:
So wie ich deine Idee verstehe, läuft dann allerdings Ampel 3 bei der Zustandsänderung mit, d.h. erst wird Ampel 1, dann 2 und dann 3 Grün. Ich will aber, dass Ampel 3 NUR im Falle des Abstands <20cm umschaltet…

Nö.
Wenn Abstand > 20 cm, dann ROT1 → NIX1 → ROT2 → NIX2 → ROT1 …
Wenn Abstand < 20 cm, dann ROT3 → NIX3 → ROT1 → NIX1 → ROT2 → NIX2 → ROT1 …

Möglicherweise habe ich ja was übersehen, aber so würde ich es versuchen.

agmue:
Nö.
Wenn Abstand > 20 cm, dann ROT1 → NIX1 → ROT2 → NIX2 → ROT1 …
Wenn Abstand < 20 cm, dann ROT3 → NIX3 → ROT1 → NIX1 → ROT2 → NIX2 → ROT1 …

Möglicherweise habe ich ja was übersehen, aber so würde ich es versuchen.

Ich habe jetzt bereits das ganze auf insgesamt 9 LEDs ausgeweitet (->3Ampeln).
Das Grundgerüst, dass 2 Ampeln laufend ihren Zustand ändern funktioniert. Bei meinem Versuch if mit einzubinden (nicht ganz wie vorher beschrieben in der Funktionsweise, aber das ist jetzt nebensächlich), ist nun herausgekommen, dass es funktioniert, wie ich es will. Allerdings läuft das Programm, wenn die Bedingung erfüllt ist, zu schnell ab, das heißt die Zeitintervalle stimmen nicht mehr. Den Grund warum sehe ich leider nicht…

  if (cm < 20) {
    switch (zustand) {
      case GRUEN1:
        digitalWrite(RotPin2, HIGH);
        digitalWrite(RotPin3, HIGH);
        digitalWrite(RotPin1, LOW);
        digitalWrite(GruenPin1, HIGH);
        digitalWrite(GelbPin1, LOW);
        zustand = GELB1;
        ampelMillis = millis();
        ampelIntervall = ZEITROT1;
        break;
      //
      case GELB1:
        digitalWrite(RotPin1, LOW);
        digitalWrite(GruenPin1, LOW);
        digitalWrite(GelbPin1, HIGH);
        zustand = ROT1;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB1;
        break;
      //
      case ROT1:
        digitalWrite(GruenPin1, LOW);
        digitalWrite(RotPin1, HIGH);
        digitalWrite(GelbPin1, LOW);
        zustand = ROTGELB3;
        ampelMillis = millis();
        ampelIntervall = ZEITROT1;
        break;
      case ROTGELB3:
        digitalWrite(RotPin3, HIGH);
        digitalWrite(GruenPin3, LOW);
        digitalWrite(GelbPin3, HIGH);
        zustand = GRUEN3;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB2;
        break;
      //
      case GRUEN3:
        digitalWrite(RotPin3, LOW);
        digitalWrite(GruenPin3, HIGH);
        digitalWrite(GelbPin3, LOW);
        zustand = GELB3;
        ampelMillis = millis();
        ampelIntervall = ZEITROT2;
        break;
      //
      case GELB3:
        digitalWrite(RotPin3, LOW);
        digitalWrite(GruenPin3, LOW);
        digitalWrite(GelbPin3, HIGH);
        zustand = ROT3;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB2;
        break;
      //
      case ROT3:
        digitalWrite(GruenPin3, LOW);
        digitalWrite(RotPin3, HIGH);
        digitalWrite(GelbPin3, LOW);
        zustand = ROTGELB2;
        ampelMillis = millis();
        ampelIntervall = ZEITROT1;
        break;
      case ROTGELB2:
        digitalWrite(RotPin2, HIGH);
        digitalWrite(GruenPin2, LOW);
        digitalWrite(GelbPin2, HIGH);
        zustand = GRUEN2;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB2;
        break;
      //
      case GRUEN2:
        digitalWrite(RotPin2, LOW);
        digitalWrite(GruenPin2, HIGH);
        digitalWrite(GelbPin2, LOW);
        zustand = GELB2;
        ampelMillis = millis();
        ampelIntervall = ZEITROT2;
        break;
      //
      case GELB2:
        digitalWrite(RotPin2, LOW);
        digitalWrite(GruenPin2, LOW);
        digitalWrite(GelbPin2, HIGH);
        zustand = ROT2;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB2;
        break;
      //
      case ROT2:
        digitalWrite(GruenPin2, LOW);
        digitalWrite(RotPin2, HIGH);
        digitalWrite(GelbPin2, LOW);
        zustand = ROTGELB1;
        ampelMillis = millis();
        ampelIntervall = ZEITROT2;
        break;
      //
      case ROTGELB1:
        digitalWrite(RotPin1, HIGH);
        digitalWrite(GruenPin1, LOW);
        digitalWrite(GelbPin1, HIGH);
        zustand = GRUEN1;
        ampelMillis = millis();
        ampelIntervall = ZEITGELB1;
        break;
    }
  }

  else {
    if (millis() - ampelMillis >= ampelIntervall) {
      switch (zustand) {
        case GRUEN1:
          digitalWrite(RotPin2, HIGH);
          digitalWrite(RotPin3, HIGH);
          digitalWrite(RotPin1, LOW);
          digitalWrite(GruenPin1, HIGH);
          digitalWrite(GelbPin1, LOW);
          zustand = GELB1;
          ampelMillis = millis();
          ampelIntervall = ZEITROT1;
          break;
        //
        case GELB1:
          digitalWrite(RotPin1, LOW);
          digitalWrite(GruenPin1, LOW);
          digitalWrite(GelbPin1, HIGH);
          zustand = ROT1;
          ampelMillis = millis();
          ampelIntervall = ZEITGELB1;
          break;
        //
        case ROT1:
          digitalWrite(GruenPin1, LOW);
          digitalWrite(RotPin1, HIGH);
          digitalWrite(GelbPin1, LOW);
          zustand = ROTGELB2;
          ampelMillis = millis();
          ampelIntervall = ZEITROT1;
          break;
        //
        case ROTGELB2:
          digitalWrite(RotPin2, HIGH);
          digitalWrite(GruenPin2, LOW);
          digitalWrite(GelbPin2, HIGH);
          zustand = GRUEN2;
          ampelMillis = millis();
          ampelIntervall = ZEITGELB2;
          break;
        //
        case GRUEN2:
          digitalWrite(RotPin2, LOW);
          digitalWrite(GruenPin2, HIGH);
          digitalWrite(GelbPin2, LOW);
          zustand = GELB2;
          ampelMillis = millis();
          ampelIntervall = ZEITROT2;
          break;
        //
        case GELB2:
          digitalWrite(RotPin2, LOW);
          digitalWrite(GruenPin2, LOW);
          digitalWrite(GelbPin2, HIGH);
          zustand = ROT2;
          ampelMillis = millis();
          ampelIntervall = ZEITGELB2;
          break;
        //
        case ROT2:
          digitalWrite(GruenPin2, LOW);
          digitalWrite(RotPin2, HIGH);
          digitalWrite(GelbPin2, LOW);
          zustand = ROTGELB1;
          ampelMillis = millis();
          ampelIntervall = ZEITROT2;
          break;
        //
        case ROTGELB1:
          digitalWrite(RotPin1, HIGH);
          digitalWrite(GruenPin1, LOW);
          digitalWrite(GelbPin1, HIGH);
          zustand = GRUEN1;
          ampelMillis = millis();
          ampelIntervall = ZEITGELB1;
          break;

P.S. Sorry für den ewig langen Code, aber ich weiß nicht wo der Fehler ist, von daher hab ich lieber mal den ganzen Code genommen.

EDIT: Habe den Fehler selbst gefunden, das Problem liegt beim Abfrageintervall des Sensors.

LoveBasketball: EDIT: Habe den Fehler selbst gefunden, das Problem liegt beim Abfrageintervall des Sensors.

Glückwunsch!

"Ein Programm, das tut was es soll, ist ein gures Programm!" Hast Du dennoch Interesse daran, das Programm zu optimieren?