Moin!
runnersteffen hat folgendes geschrieben : |
die Ampelkreuzung habe ich auf einer Pappschachtel aufgebaut und mit LEDs bestückt... |
Davon hätte ich ja gerne mal das Foto gesehen, weil:
haentschman hat folgendes geschrieben : |
Zitat: | Hab an den CheckBoxen am Velleman Board meine LEDs angeschlossen | Da mich das technisch interessiert...kannst du mal ein Foto davon machen ?  |
Ich glaube kaum, dass man an einer Checkbox (die es auf dem Velleman-Board auch gar nicht gibt) eine LED anschließen kann...
runnersteffen hat folgendes geschrieben : |
Es geht... hier mein Code von der ersten Ampel !!! |
Da du offensichtlich Anfänger bist, aber Hardware dabei ist, kannst du eigentlich nur aus der technischen Richtung (irgend eine technische Fachschule oder sowas) kommen. Mich wundert aber, dass man dich derart alleine oder offensichtlich ohne jegliche Vorbereitung auf so ein Projekt loslässt.
Du hast da einige Probleme im Code, auch wenn für dich vermutlich erstmal nur das "geht-doch"-Prinzip zählt. Lass dir einen Rat geben: nach dem "geht-doch"-Prinzip programmieren, wird dir irgendwann den Hals brechen (und wenn du mal Aufzugsteuerungen oder Airbuscomputer baust, vielleicht sogar uns allen

)...
Da ich an meinem Hals hänge, hier ein paar Tipps, was man besser machen kann:
runnersteffen hat folgendes geschrieben : |
Delphi-Quelltext 1:
| if (CheckBox1.Checked=true) and (CheckBox2.Checked=false) and (Checkbox3.Checked=false) Then | |
Niemals (zumindest in Delphi) Booleans auf TRUE oder FALSE vergleichen, sondern direkt als logischen Wert verwenden. Willst du auf FALSE vergleichen, dann nimm ein NOT dazu:
Delphi-Quelltext
1:
| if (CheckBox1.Checked and NOT CheckBox2.Checked and NOT Checkbox3.Checked) then |
runnersteffen hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4:
| CheckBox3.Checked :=false; timer1.interval:=1000; timer1.interval:=1000; | |
Mehrfaches Zuweisen des selben Wertes bringt nix.
runnersteffen hat folgendes geschrieben : |
Delphi-Quelltext 1:
| Timer1.Enabled :=False; | |
Das ist keine Schleife, sondern ein Timer, also eine Komponente, die in einstellbaren Zeitabständen ein Ereignis produziert. Eine Schleife ist ein Sprachkonstrukt, also z.B: for oder repeat-until.
Gut, sind genau genommen Kleinigkeiten. Was ich aber wirklich bedenklich finde, ist die Tatsache, dass du offensichtlich noch nichts von einer Zustandssteuerung gehört hast (oder wenn, erfolgreich ignoriert).

Und das bei so starkem Technikbezug.

Dein Ansatz ist auf dem Level "geht so grade", aber das kann doch nicht das Ziel gewesen sein. Ich würde mich als Betreuer mit dieser "Lösung" nicht zufrieden geben, das ist ineffizient und fehleranfällig.
Nunja, Meckern ohne Besser-Machen geht nicht, also hier mein Vorschlag, wie man das lösen könnte.

Ich hatte allerdings keinen Bock, das Velleman-Board vom Boden zu holen und auf dem Steckbrett mit LEDs zu hantieren, also mal nur der programmtechnische Teil, die Hardware wirst du hoffentlich alleine angesteuert bekommen (ich schätze nämlich mal, du hast dir die (grauslige) Demo-Anwendung von Velleman genommen und "umgebaut", die ist aber so schlecht gemacht, davon brauchst du eigentlich nur die Hardware-Connect/Disconnect-Prozeduren, der Rest kann getrost weg).
Zunächst mal, ohne irgendetwas anderes zu betrachten, machen wir uns mal einen Gedanken, was denn da passieren soll:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| const ChannelData: array[0..8] of Integer = ( 9, 11, 12, 10, 9, 25, 33, 17, 9 ); |
Du hast dich dafür entschieden, die LEDs an die Ausgänge wie oben abgebildet anzuschließen, wobei die über kreuz stehenden Ampeln vermutlich parallel aufgeschaltet sind, so dass jeweils 2 LEDs gegenüberliegend gleich leuchten. Guter Ansatz.
Du hast in deinem Code vermutlich die Checkboxen und -Handler von der Velleman-Demo drin gelassen und dann deinen Ansatz zur Ansteuerung dazu geschrieben. Das ist allerdings "suboptimal".

Es ist wesentlich effizienter, die Methode WriteAllDigital() zu verwenden und damit gleich alle Ausgänge auf einmal umzuschalten.

Wozu sollte es auch gut sein, die LEDs nacheinander umzuschalten (auch wenn das so schnell geht, dass man es mit dem bloßen Auge nicht sieht)? Es erzeugt unnötig viele Hardwarezugriffe und damit nutzlos Last auf dem Bus.
In der Tabelle haben wir einfach notiert, welche LED wann an sein soll, dann die Bitwerte addiert und als Dezimalzahl einem Status zugeordnet. In der Konstantendeklaration unter der Tabelle zählen wir einfach nur die ermittelten Werte für das Steuerregister auf. Das war schon der schwierigste Teil!
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| type TForm1 = class(TForm) Button1: TButton; Timer1: TTimer; Edit1: TEdit; procedure Button1Click(Sender: TObject); procedure Timer1Timer(Sender: TObject); private FAmpelState: Integer; public end; |
Das ist mein Demo-Formular, da liegt nur ein Button, ein Editfeld als Hardware-Simulation und ein Timer als Zeitgeber drauf. Kann man natürlich nach Belieben weiter dekorieren...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled := FALSE; FAmpelState := 0; Timer1Timer(Self); Timer1.Enabled := TRUE; end;
procedure TForm1.Timer1Timer(Sender: TObject); begin WriteAllDigital(ChannelData[FAmpelState]); Inc(FAmpelState); if (FAmpelState > High(ChannelData)) then begin Timer1.Enabled := FALSE; Button1.Enabled := TRUE; end; end; |
Jetzt zu den spannenden Sachen: Beim Button-Klick passiert noch nicht viel, hier wird der Startzustand 0 gesetzt, direkt einmal der Timer-Handler aufgerufen (sonst wird die erste Ausgabe erst verzögert gemacht) und dann der Timer aktiviert, so dass der Handler regelmäßig wieder aufgerufen wird.
Die eigentliche "Arbeit" passiert aber im Timer-Ereignis-Handler: Als erstes wird er aus der Tabelle ermittelte Zustand der Digitalkanäle auf einmal an die Hardware übertragen (es gibt eine entsprechende Prozedur beim dem Velleman-Zeugs dazu, solltest du direkt so übernehmen können). Dann wird der nächste Zustand der Ampel bestimmt (simpel: +1) und geschaut, ob es diesen Zustand überhaupt noch gibt. Wenn nicht, ist der Zyklus abgelaufen, also den Timer stoppen, damit keine weiteren Ereignisse mehr erzeugt werden und den Button wieder aktivieren.
Ich sehe allerdings gerade, dass du unterschiedliche Zeiten für die Ampelphasen verwendet hast. Das habe ich jetzt nicht umgesetzt, aber ein bischen was kannst du ja auch selbst noch ergänzen, oder?
Tipp: Einfach ein zweites, konstantes Array anlegen, dass die Zeit zu dem Zustand speichert. Wenn du es ganz schick machen willst, kannst du auch ein record definieren, dass Status und Zeit enthält und daraus ein konstantes Array machen. Das ist aber schon nicht mehr ganz simpel.
cu
Narses
There are 10 types of people - those who understand binary and those who don´t.