Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
27.02.2014, 20:46 (Dieser Beitrag wurde zuletzt bearbeitet: 27.02.2014 20:51 von GerdW.)
Zitat:Sowas wie Speicherschaltungen (RS-Flip-Flop) scheint es ja nicht baufertig in LabView zu geben...
Weil du RS-FF in LabVIEW eben nicht benötigst.
Und "Speicherschaltungen" gibt es schon: das nennt sich Schieberegister/FeedbackNode, nötigenfalls mit ein oder zwei boolschen Operationen!
Im Ernst: Es gibt immer wieder VIs, die ein RS-FF implementieren und verwenden. Bisher konnte man sowas immer durch ein Schieberegister und eine MultipleArithmetik erstzen - man muss nur vorher genauer formulieren, was man eigentlich programmieren will…
Zitat:Gibt es in LabView eine simple Lösung, um Speicherschaltungen zu realisieren (mit Rücksetzbedingung)?
Hatte ich garantiert schon mal gepostet, bin zu faul zum Suchen…
Deshalb PseudoCode:
Code:
Q = Q_alt
IF R THEN Q=FALSE
IF S THEN Q=TRUE
Q_alt = Q ; Status für nächsten Aufruf speichern
So sieht das dann aus:
Wichtig: ein solches subVI muss aufgrund des internen Seicherelements reentrant gesetzt werden!
Erstmal ein Danke an Gerd, das mit dem Schieberegister bzw. FeedbackNode leuchtet ein. Ist halt erstmal eine kleine Umstellung, wenn man vorher mit Siemens SPS programmiert hat. Leider hapert es noch ein bisschen an der Umsetzung des aktuellen Plans. Vlt. könnt ihr mir nochmal einen Gedankenanstoß geben.
Folgendes:
Ich bin mittlerweile soweit gekommen, das ich die "Kiste" in einem vorgegebenen Bereich steuern kann. Zusätzlich möchte ich nun einen Automatikmodus implementieren. Dazu habe ich an jeder Ecke des Verfahrweges Endlagenschalter "angebracht". So, da ich die Kistensteuerung nun mit einer Ereignisstruktur umgesetzt habe (ein großes Danke nochmal für eure Hilfe), dachte ich es wäre sinnvoll die Automatiksteuerung dort zu integrieren [um es programmiertechnisch sauber zu halten].
Die Automatiksteuerung soll folgendes tun:
Von der Startposition (unten links) verfahren zur Zielposition (unten rechts). Dabei werden alle Endlagen passiert. Evtl. soll es später eine Möglichkeit geben anschließend wieder zur Startposition zu verfahren.
Also dachte ich mir folgendes:
Da ich das arbeiten mit Speicherschaltungen noch sehr gewohnt bin, habe ich 3 LED-Anzeigen erstellt, die jeweils die Bereiche "Hochfahren", "Rechtsfahren" und "Runterfahren" abdecken. Z.B. wird "Hochfahren" aktiv, wenn die Endlage unten links aktiv ist und fällt ab, wenn die Endlage oben links erreicht ist.
Nun dachte ich, das man in der Ereignisstruktur einfach den Taster "Automatik" (Ereignis: Maustaste gedrückt) UND die jeweilige Wertänderung der LED-Anzeige abgreifen könnte. Sprich, die Ereignisstruktur soll folgendes tun:
- Automatik wird gedrückt + Hochfahren aktiv => 1 ausgeben => Kiste fährt hoch BIS Endlage oben erreicht (Hochfahren nicht mehr aktiv).
Und genau diesen Punkt bekomme ich nicht umgesetzt. Eine Kombination der beiden Argumente ist mir bis jetzt nicht gelungen. Des Weiteren ist das zweite Argument variabel, sprich entweder trifft Hochfahren zu, oder Rechtsfahren, oder Runterfahren. Je nachdem soll eine andere Zahl ausgegeben werden (die jeweiligen Cases befinden sich außerhalb der Eventstruktur und könnten angesteuert werden).
Ich habe auch schon einige andere Möglichkeiten probiert, aber nichts hat mich bis jetzt weiter gebracht... Zwischenzeitlich bin ich bei der Suche auf die Möglichkeit der Zustandsautomaten in Labview gestoßen, aber ob sich das für diesen einen Fall rentiert? Und dann wäre wieder die Frage, inwiefern ist das kombinierbar mit der vorhandenen Eventstruktur.
Danke schonmal für eure Hilfe.
Ein schönes Wochenende,
Grüße,
Niko
02.03.2014, 18:58 (Dieser Beitrag wurde zuletzt bearbeitet: 02.03.2014 18:59 von GerdW.)
Zitat:Ist halt erstmal eine kleine Umstellung, wenn man vorher mit Siemens SPS programmiert hat.
Das sieht man!
Bitte (wirklich BITTE):
Lokale Variablen vermeiden, insbesondere wenn in der selben Struktur schon das Terminal des Controls/Indicators liegt (oder das Terminal komplett ungenutzt rumliegt!), und DRÄHTE verwenden! THINK DATAFLOW!
Zitat:da ich die Kistensteuerung nun mit einer Ereignisstruktur umgesetzt habe
Das "Maustaste gedrückt"-Event ist nur ganz selten das wirklich benötigte. Meist nutzt man sinnvollerweise "Wertänderung"!
Zitat:Eine Kombination der beiden Argumente ist mir bis jetzt nicht gelungen.
- Man kann mehrere Events für einen Eventcase definieren, dies ist dann aber eine ODER-Verknüpfung. Eine UND-Verknüpfung musst du im Code selsbt realisieren.
- Events reagieren (primär) auf User-Aktionen und NICHT auf Wertänderungen von Indicatoren! Bitte die Hilfe zur Event-Struktur durchlesen!
Zitat:Zwischenzeitlich bin ich bei der Suche auf die Möglichkeit der Zustandsautomaten in Labview gestoßen, aber ob sich das für diesen einen Fall rentiert?
Erstens ist das eine excellente Idee und zweitens rentiert sich das auf alle Fälle!
Zitat:Und dann wäre wieder die Frage, inwiefern ist das kombinierbar mit der vorhandenen Eventstruktur.
Hast du doch momentan selbst schon realisiert: deine Eventstruktur gibt einen Wert aus und eine Case-Struktur wertet diesen dann aus: O/U/L/R wird mit Zahlenwerten von 1-4 signalisiert und von einer (Art) "Statemachine" abgearbeitet…
Tipp:
Verwende ein (typdefiniertes) Enum statt einfacher Zahlenwerte…
Danke erstmal Gerd für die Antwort Ich habe mich nochmal ein bisschen mit Zustandsautomaten auseinander gesetzt und das ganze noch einmal umgebastelt. Ich setze nun ein typdefiniertes Enum ein um eine Case-Struktur anzusteuern. Diese enthält einen Init-, Exit-, Wait for Event-, sowie Hoch-/Runter.... Case. Meine Hoffnung war, das ich mit einem Zustandsautomaten das Problem mit der Automatiksteuerung lösen kann.
Nun hat sich aber erstmal ein anderes Problem eingeschlichen:
Der Zustandsautomat läuft soweit, ich kann aber nur einen Tippbetrieb realisieren. Ich möchte aber das die Kiste verfährt, solange ich die zugehörige Taste gedrückt halte. Der Case "Wait for event" gibt momentan beim Tastendruck auf Hoch/Runter/Rechts/Links den Befehl zum jeweiligen Case zu wechseln (das ganze verpackt in eine Eventstruktur). Der jeweilige Case wird dann einmal ausgeführt und springt wieder in den Wait for event - Case. Wie kann ich hier eine Schleife realisieren, die stoppt, wenn die jeweilige Taste nicht mehr gedrückt wird? Ich habe schon probiert mit einem True/False-Vergleich zu arbeiten [sprich Schleife im jeweiligem Case], aber dann verfährt die Kiste um mehrere Einheiten pro Schritt, was nicht sein sollte...
Warum sind da immer noch lokale Variablen im Haupt-VI - und die auch noch direkt neben ihren Terminals? Warum verwendest du keine Drähte? THINK DATAFLOW!
- Es ist ungünstig, eine Event-Struktur in einer Case-Struktur zu verstecken. Eine Eventstruktur sollte immer auf Events reagieren können!
- Es ist ungünstig, Wartezeiten in subVIs (wie LinksFahren/RechtsFahren) zu verstecken. Erstelle doch lieber einen weiteren State "Warten"…
- Für die ganzen Vergleiche mit Null gibt es extra Vergleichsfunktionen…
- Die vier Richtungen unterscheiden sich nur im Bewegungsvektor. Warum also 4 verschiedene Funktionen zum Verfahren der einzelnen Richtungen?
- Deine Positionsprüfung kann auch einfacher aussehen:
Die CoercionDots darfst du selbst entfernen!
Danke für deine Antwort Du bist ja ganz schön fleißig hier
Deinen Hinweis mit den lokalen Variablen werde ich definitiv noch umsetzen, ich wollte aber erstmal ein funktionierendes Programm haben
Bezüglich der Eventstruktur wäre es also programmiertechnisch sauberer gewesen so wie vorher zu arbeiten? Sprich eine Eventstruktur mit nachfolgender Casestruktur?
Ich habe den jetzigen Aufbau einem Beispiel entnommen.
Das mit der Wartezeit muss eh noch überarbeitet werden, das soll die Geschwindigkeit in den Endlagen drosseln. Danke erstmal für die Hinweise, ich werde mich heute abend wieder ran machen
Ich habe wieder ein bisschen gebastelt an meinem Projekt... Also der Stand der Dinge:
- Event- und Casestruktur wieder getrennt, Ansteuerung durch Enum Typdef.
- Vergleiche mit Null ersetzt durch fertige Funktion
- "Warten" aus dem SubVI entfernt [da muss ich nochmal gucken, ob ich für die Endlagenanfahrt eine bessere Lösung finde]
-Bewegungssteuerung in einem SubVI zusammengefasst
- Positionsprüfung angepasst
- Automatiksteuerung umgesetzt [im Moment fährt die Kiste vom Startpunkt bis zum Endpunkt, wird evtl. noch um Rückfahrt erweitert]
- und natürlich habe ich bestens probiert nach dem "THINK DATAFLOW"-Prinzip zu arbeiten, ich hoffe es ist mir einigermaßen gelungen
So, jetzt haben sich (wie sollte es auch anders sein) wieder neue Probleme ergeben....
Ist es sinnvoll anstelle von Referenzen den vorhandenen Ring-Terminal an das SubVI zu übergeben? Im Moment habe ich zur Endlagenbestimmung die Referenz der Kiste an meine SubVIs übergeben und lese daraus die Position aus. Wenn ja, wie würde ich im SubVI die Position abgreifen?
Ist das Prüfen der Endlagen im "Timeout"-Zustand der Eventstruktur programmiertechnisch richtig? Ich habe das Problem, das wenn ich die Endlagen bzw. meine Hilfszustände für die Automatiksteuerung in der While-Schleife abfrage, das diese auch nach beenden des Programms noch gesetzt sind [das kommt daher, dass der Zustand "Exit" durchläuft und danach in der While-Schleife die Endlagen überprüft werden, somit können diese nicht rückgesetzt werden....]
Nachdem die Automatiksteuerung nun endlich funktioniert, bereitet sie mir natürlich auch gleich tolle Probleme zu... Mein momentaner Lösungsansatz für die Automatiksteuerung lautet:
Automatiktaster gedrückt? => Abfrage des jeweiligen Hilfzustandes (S_Hoch/S_Runter/S_Rechts) => Sprungbefehl für die Eventstruktur in den jeweiligen Zustand
Das ganze läuft bis zum rechten unteren Ende. Das Problem ist aber, drückt man den Automatiktaster öfters während dem Ablauf, bleibt dieser im "TRUE"-Zustand hängen. Das liegt daran, das ich im "Timeout"-Zustand der Eventstruktur einen zusätzlichen Sprungbefehl zum Automatik-zustand gesetzt habe (solange Taster Automatik gedrückt). Leider kann ich ohne diesen Sprung die Automatiksteuerung nicht realisieren. Ansonsten würde die Kiste hochfahren und stehen bleiben (nachdem S_Hoch angesteuert wurde, springt die Eventstruktur wieder in Timeout), erst nach nochmaligem Drücken des Automatiktasters fährt die Kiste weiter. Gibt es eine sauberere Lösung?
Danke schonmal und einen angenehmen Abend gewünscht
LG Niko
13.03.2014, 08:39 (Dieser Beitrag wurde zuletzt bearbeitet: 13.03.2014 08:40 von GerdW.)
soweit schon ganz gut. Nur das AutoCleanup hast du vergessen…
Zitat:Ist es sinnvoll anstelle von Referenzen den vorhandenen Ring-Terminal an das SubVI zu übergeben? Im Moment habe ich zur Endlagenbestimmung die Referenz der Kiste an meine SubVIs übergeben und lese daraus die Position aus. Wenn ja, wie würde ich im SubVI die Position abgreifen?
Ich würde sagen: nein.
Im "echten Leben" willst du ja kein FP-Element bewegen, sondern irgendein echtes Stück Material. Und da hat man keine Referenz auf die Hardware, sondern muss sich intern dessen Position merken. Und "Daten merken" läuft sehr schnell auf die Nutzung von Schieberegistern hinaus!
Also: Merke dir die aktuelle Position in einem Schieberegister und gebe diese Information als Parameter an subVIs weiter…
(Tipp: typdefinierten Cluster für diese Information anlegen, dann kann man später sehr leicht weitere Informationen in diesem Cluster ablegen. Und der Schritt zu (LV)OOP ist dann auch nicht mehr weit…)
Zitat:Ist das Prüfen der Endlagen im "Timeout"-Zustand der Eventstruktur programmiertechnisch richtig?
Nein, ich würde das im Timeout-Case der Case-Struktur erledigen.
Grund: klare Trennung von Consumer und Producer. Der Producer (hier: Eventstruktur) kümmert sich nur um die Verarbeitung Entgegennahme von User-Aktionen, der Consumer arbeitet dessen Befehle ab…
Zitat:Leider kann ich ohne diesen Sprung die Automatiksteuerung nicht realisieren. Ansonsten würde die Kiste hochfahren und stehen bleiben (nachdem S_Hoch angesteuert wurde, springt die Eventstruktur wieder in Timeout), erst nach nochmaligem Drücken des Automatiktasters fährt die Kiste weiter. Gibt es eine sauberere Lösung?
Ja klar gibt es eine!
Den Automatikmodus sollte man nicht durch andauerndes Feuern eines Events erzwingen, sondern indem man sich diesen Modus einfach merkt (siehe oben: in einem Schieberegister)!
Die letzten "Problemchen" habe ich leider noch nicht behoben, ich arbeite aber dran.
Nun würde ich gerne eine neue Idee implementieren und wollte diesbezüglich mal eure Meinung hören, was da evtl. einfacher wäre
Stand der Dinge:
Ich habe die Steuerung um ein "Seil" erweitert, soll ja einen Kran darstellen. Nun möchte ich gerne die Möglichkeit einbauen, die Kiste abzukoppeln.
Dazu habe ich schon mal zwei Taster und zwei Kontrollleuchten eingebaut: Ankoppeln und Abkoppeln.
Soweit kein Problem. Jetzt kommt aber das größere Problem(chen)...
In der aktuellen Version der Steuerung ist es leider nicht möglich, die Position des "Seils" auf eine Stelle der X- bzw. Y-Koordinate zu verfahren. Das Problem ist jetzt folgendes:
Man koppelt die Kiste ab, verfährt mit dem Seil und möchte anschließend wieder ankoppeln. Dazu sollte das Seil genau die gleich Position über der Kiste haben, wie davor. Ansonsten gibt es Probleme mit den anderen Randbedingungen im ganzen Programm...
Mein Ansatz wäre jetzt einen Automatikmodus einzubauen, der, nachdem man die Kiste grob angefahren hat, die genaue Position setzt zum ankuppeln des "Seils" an die Kiste. Ist das aufwendig? Stehe gerade vor dem Problem, das ich nächste Woche fertig sein muss und mir daher genau überlegen muss, was in der Zeit noch umsetzbar ist Oder ob ich lieber nur Programmpflege betreibe und alles schick mache.
Ich hoffe ihr habt einen Ansatz für mich oder ein paar Ideen