Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Ampelschaltung mit 4 Ampeln auf einem Timer
DerCaptain - Di 20.11.12 19:23
Titel: Ampelschaltung mit 4 Ampeln auf einem Timer
Hallo,
Habe Probleme mit meinem Delphi-Code.
Muss eine Ampelschaltung für eine Kreuzung mit einem if-then-else-if code machen und dabei eine RotGelb-Phase einbringen, die allerdings nur nach dem Rot-Signal ausgelöst wird.
Dabei soll die Rot/Grün-Phase von der waagerecht verlaufenden Strasse 10Sek. betragen und die der vertikal verlaufenden 5Sek.
Die Nebenphasen sollen jeweils 1Sek dauern.
Mein Code bis jetzt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| procedure TForm1.tiAmpelschaltungTimer(Sender: TObject); begin if imAmpelGruen4.Visible = true then begin imAmpelGelb1.Visible := false; imAmpelGelb3.Visible := false; imAmpelGruen2.Visible := false; imAmpelGruen4.Visible := false; imAmpelRot1.Visible := true; imAmpelRot3.Visible := true; imAmpelGelb2.Visible := true; imAmpelGelb4.Visible := true; tiAmpelschaltung.Interval := 5000; end else if imAmpelGelb4.Visible = true then begin imAmpelRot1.Visible := false; imAmpelRot3.Visible := false; imAmpelGelb2.Visible := false; imAmpelGelb4.Visible := false; imAmpelRotGelb1.Visible := true; imAmpelRotGelb3.Visible := true; imAmpelRot2.Visible := true; imAmpelRot4.Visible := true; tiAmpelschaltung.Interval := 10000; end else if imAmpelRot4.Visible = true then begin imAmpelGelb1.Visible := true; imAmpelGelb3.Visible := true; imAmpelRotGelb2.Visible := true; imAmpelRotGelb4.Visible := true; imAmpelRot2.Visible := false; imAmpelRot4.Visible := false; imAmpelRotGelb1.Visible := false; imAmpelRotGelb3.Visible := false; tiAmpelschaltung.Interval := 1000 end else if imAmpelRotGelb4.Visible = true then begin imAmpelGruen1.Visible := true; imAmpelGruen3.Visible := true; imAmpelGelb2.Visible := true; imAmpelGelb4.Visible := true; imAmpelRotGelb2.Visible := false; imAmpelRotGelb4.Visible := false; imAmpelGelb1.Visible := false; imAmpelGelb3.Visible := false; tiAmpelschaltung.Interval := 10000; end |
Könnte mir irgendjemand helfen?
Komme mit dem Timing noch nicht so ganz klar und manchmal wird noch immer eine Ampelphase übersprungen.
ub60 - Di 20.11.12 19:31
Mein Tipp:
Stelle das Timer-Intervall auf eine Sekunde und zähle im OnTimer-Event einen Zähler jeweils um 1 höher.
Frage dann den erhaltenen Zähler in der Art ab:
Delphi-Quelltext
1: 2: 3: 4: 5:
| if Zaehler=10 then ... else if Zahler=12 then ... else |
Besser geht das Ganze noch mit case .. of ...
Zeichne Dir auf alle Fälle eine "Timeline", wann die Ampel welche Zustände haben bzw. umschalten soll.
ub60
platzwart - Di 20.11.12 19:39
Außerdem...
Delphi-Quelltext
1:
| if imAmpelGruen4.Visible = true then ... |
...muss korrekt lauten:
Delphi-Quelltext
1:
| if imAmpelGruen4.Visible then ... |
Niemals auf
true oder
false prüfen (bei false dann
not verwenden).
DerCaptain - Di 20.11.12 20:24
Habe einen neuen Quelltext aufgesetzt,
bei dem ich diesmal die If-Bedingungen mit den Timer-Werten erstellt habe und alles genau nach plan gemacht habe.
Diesmal allerdings Springen Ampelreihe1 und Ampelreihe4 von Gelb auf Rot auf Rotgelb auf Gelb auf Rot und auch bei der Ampelreihe 2 und 3 wird grün übersprungen.
Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| procedure TfmKreuzung.tiAmpelschaltungTimer(Sender: TObject); begin if tiAmpelschaltung.Interval = 1000 then begin imAmpelGruen2.Visible := false; imAmpelGruen3.Visible := false; imAmpelGelb2.Visible := true; imAmpelGelb3.Visible := true; imAmpelGelb1.Visible := false; imAmpelGelb4.Visible := false; imAmpelRot1.Visible := true; imAmpelRot4.Visible := true; tiAmpelschaltung.Interval := 5000 end else if tiAmpelschaltung.Interval = 5000 then begin imAmpelGelb2.Visible := false; imAmpelGelb3.Visible := false; imAmpelRot2.Visible := true; imAmpelRot3.Visible := true; imAmpelRot1.Visible := false; imAmpelRot4.Visible := false; imAmpelRotGelb1.Visible := true; imAmpelRotGelb4.Visible := true; tiAmpelschaltung.Interval := 10000; end else if tiAmpelschaltung.Interval = 10000 then begin imAmpelRot2.Visible := false; imAmpelRot3.Visible := false; imAmpelRotGelb2.Visible := true; imAmpelRotGelb3.Visible := true; imAmpelRotGelb1.Visible := false; imAmpelRotGelb4.Visible := false; imAmpelGelb1.Visible := true; imAmpelGelb4.Visible := true; tiAmpelschaltung.Interval := 1000; end else if tiAmpelschaltung.Interval = 1000 then begin imAmpelRotGelb2.Visible := false; imAmpelRotGelb3.Visible := false; imAmpelGelb2.Visible := true; imAmpelGelb3.Visible := true; imAmpelGelb1.Visible := false; imAmpelGelb4.Visible := false; imAmpelGruen1.Visible := true; imAmpelGruen4.Visible := true; tiAmpelschaltung.Interval := 5000; end |
Edit: Mir ist gerade aufgefallen, dass das eventuell 'was damit zutun haben könnte, dass ich ganz am Ende nochmal die Interval-Eigenschaft verändere?
Werde zunächst den Tipp des Vorposters ausprobieren.
Edit2: Keine Veränderung der Lage.
Besagte Phasen werden immernoch übersprungen.
Moderiert von
Narses: Beiträge zusammengefasstHabe es geschafft.
Der Fehler lag darin, dass Delphi immer beim letzten Schritt das die erste Klammerung ausgeführt hat.
Doch ich konnte das Problem lösen indem ich einfach ein Objekt erstellt habe desses Eigenschaften eingebracht habe, um Bedingungen zu erzielen, die sich unterscheiden.
Narses - Di 20.11.12 23:37
Moin und :welcome: in der EE!
Hast du Interesse das vernünftig zu machen? Oder möchtest du weiter mit dem if-then-else-Intervall rumhampeln? :nixweiss:
Wenn du das ordentlich machen möchtest, sag bescheid, dann ziehen wir das eben in ein paar Minuten durch. ;)
cu
Narses
Narses - Do 22.11.12 12:43
Moin!
Nunja, Beratungsresistenz ist halt eine Anfänger-Krankheit... :| Egal, dann halt für die Nachwelt die Musterlösung:
Zunächstmal machen wir uns einen Plan, wann welche Lampe leuchten soll:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| R1 Y1 G1 R2 Y2 G2 Dauer Phase 0 X X 1 Phase 1 X X X 1 Phase 2 X X 15 Phase 3 X X 1 Phase 4 X X 1 Phase 5 X X X 1 Phase 6 X X 10 Phase 7 X X 1 |
Hier steht Y für Gelb, sonst kann man das ja nicht auseinanderhalten. ;)
Dann legen wir ein Demo-Projekt an:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| type TForm1 = class(TForm) imAmpelRot1: TImage; imAmpelGelb1: TImage; imAmpelGruen1: TImage; imAmpelRot2: TImage; imAmpelGelb2: TImage; imAmpelGruen2: TImage; Timer1: TTimer; private FPhase: Integer; FTakt: Integer; |
Wie man sieht, werden 6 Images gebraucht, anlegen und passend benennen, so dass das zwei Ampeln ergibt. Die beiden Klassen-Eigenschaften brauchen wir, um uns die aktuelle Phase und den Takt innerhalb der Phase zu merken.
Hier jetzt der Kern der Sache, der Timer-Ereignishandler:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.Timer1Timer(Sender: TObject); const TaktSoll: array[0..7] of Integer = ( 1, 1, 15, 1, 1, 1, 10, 1 ); begin Inc(FTakt); if (FTakt = TaktSoll[FPhase]) then begin FPhase := (FPhase +1) mod 8; FTakt := 0; imAmpelRot1.Visible := FPhase in [0, 1, 4, 5, 6, 7]; imAmpelGelb1.Visible := FPhase in [1, 3]; imAmpelGruen1.Visible := FPhase in [2]; imAmpelRot2.Visible := FPhase in [0, 1, 2, 3, 4, 5]; imAmpelGelb2.Visible := FPhase in [5, 7]; imAmpelGruen2.Visible := FPhase in [6]; end; |
Wir zählen in FTakt die Anzahl Timer-Ereignisse. Wenn die Anzahl der Vorgabe für diese Phase entspricht, dann wird zur nächsten Phase geschaltet. Beim Phasenübergang ist dann die Sichtbarkeit der Lampen anzupassen. Dazu liest man die Tabelle einfach Spaltenweise für die entsprechende Lampe ab. :idea:
Und noch etwas Kosmetik für die Initialisierung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.FormCreate(Sender: TObject);
procedure SetColor(AImage: TImage; const AColor: TColor; const AVisible: Boolean = TRUE); begin AImage.Picture.Bitmap.Canvas.Brush.Color := AColor; AImage.Picture.Bitmap.Width := AImage.Width; AImage.Picture.Bitmap.Height := AImage.Height; AImage.Picture.Bitmap.Canvas.Rectangle(AImage.Canvas.ClipRect); AImage.Visible := AVisible; end;
begin SetColor(imAmpelRot1, clRed); SetColor(imAmpelRot2, clRed); SetColor(imAmpelGelb1, clYellow, FALSE); SetColor(imAmpelGelb2, clYellow, FALSE); SetColor(imAmpelGruen1, clLime, FALSE); SetColor(imAmpelGruen2, clLime, FALSE); |
Bei Fragen - fragen! ;)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!