Modularer Aufbau eines größeren LabVIEW Programms - Kommunikation zw. Programmteilen
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!
Modularer Aufbau eines größeren LabVIEW Programms - Kommunikation zw. Programmteilen
Hallo liebe LabVIEW Community!
Zurzeit entwickele ich mittels LabVIEW ein (für mich) größeres Programm zur Steuerung eines Prüfstands.
Im Prinzip kann man mein Programm in 4 Programmteile zerlegen:
1. Steuerung und Auswertung Gerät 1
2. Steuerung und Auswertung Gerät 2
3. Steuerung und Auswertung Gerät 3
4. Kommunikation zwischen den einzelnen Geräten
Momentan habe ich all diese Funktionen in einem LabVIEW Programm untergebracht (das heißt nicht, dass es keine SubVIs gibt :-)). Das Problem ist, dass es mittlerweile recht unübersichtlich wird (auf dem Blockdiagramm sowie auf dem Frontpanel) und mein Wunsch wäre es das ganze wie oben dargestellt zu splitten. Ich stelle mir sozusagen 3 "Standalone" Programme vor mit eigenem Subpanel (zur Steuerung der drei Geräte) die über ein 4. Programm aufgerufen werden. Des weitern soll das 4. Programm den Datenaustausch zwischen den Geräten übernehmen. Ein weiterer Vorteil bei dieser Vorgehensweise wäre aus meiner Sicht der leichtere austausch oder Erweiterung einzelner Komponenten ohne bestehende Programmteile zu beeinflussen.
Ich habe mal ein kleines Beispielprojekt erstellt, das die Problematik veranschaulichen soll. In diesem Beispielprojekt habe ich ein Hauptprogramm (Main.VI im Ordner LV_Source) welches die beiden Unterprogramme "Addieren/Subtrahieren" sowie "Multiplizieren/Dividieren" aufruft. Die Kommunikation zwischen den Programmen wollte ich mit einer Queue realisieren wobei sich hier schon das erste Problem zeigt, ich müsste dann für jedes Unterprogramm eine eigene "Communication Queue" erstellen oder gibt es da eine elegantere Lösung?
Jedes der vier Programme baut auf einer ereignisgesteuerten State Machine auf (wie auch in meinem Beispielprojekt). Nun muss ich auch über das 4. Programm also das Hauptprogramm Ereignisse in den Unterprogrammen 1-3 auslösen (z.B. für automatisierte Steuerungsabläufe, die auf Rückmeldungen bestimmter Programmteile warten). Wie kann ich das am besten realisieren? Ich dachte an Benutzerereignisse die dann im Hauptprogramm erstellt werden und an die 3 Unterprogramme mittels Queue übergeben werden.
Zu den bereits gestellten Fragen wäre ich sehr dankbar wenn die Profis hier im Forum mir Rückmeldung geben könnten, ob dieser Aufbau generell was taugt oder ob es hier wesentlich bessere Vorgehensweisen gibt.
P.S. Ich weiß nicht ob dieser Beitrag an der richtigen Stelle im Forum steht, wenn nicht bitte entsprechend verschieben. Danke!
Gruß
Stefan
18.06.2015, 15:13 (Dieser Beitrag wurde zuletzt bearbeitet: 18.06.2015 17:22 von Trinitatis.)
ich kann deine VIs nicht lesen aber so grundsätzlich würde ich dein Projekt mit einer Master Slave-Struktur angehen. Es gibt also einen Master, der die anderen Kommunikationsteilnehmer aufruft und Grundfunktionen steuert.
Die Kommunikation der Slaves untereinander sollte dann auch über eine Queue des Masters erfolgen, wobei jedes Telegramm einen Absender sowie einen Adressaten haben sollte. Dann hast du im Master EINE Stelle, über die die gesamte Kommunikation läuft. ggf. kannst du deine 1-N Slaves auch mit einem VI erschlagen, das du mehrfach aufrufst und entsprechend parametrierst. Das vermindert den Wartungsaufwand.
Danke schonmal für den Hinweis, ich werde mir mal so eine Master Slave-Struktur ansehen (ich glaube sowas schon mal bei den LabVIEW Beispielen gesehn zu haben).
Also so wie ich das jetzt Verstanden habe gibt es dann im Master n-1 Queues für n-1 Slaves. Mithilfe dieser n-1 Queues kann der Master die n-1 Slaves "steuern". Desweiteren gibt es EINE Queue in die alle n-1 Slaves Nachrichten für den Master schreiben können. Habe ich das soweit richtig verstanden?
Zitat:wobei jedes Telegramm einen Absender sowie einen Adressaten haben sollte
Das verstehe ich nicht so ganz, bzw. weiß nicht wie ich das in Verbindung mit Queues gemeint ist.
Danke
Gruß
Stefan
19.06.2015, 10:18 (Dieser Beitrag wurde zuletzt bearbeitet: 19.06.2015 10:20 von Trinitatis.)
(19.06.2015 07:27 )n4f3ts schrieb: Desweiteren gibt es EINE Queue in die alle n-1 Slaves Nachrichten für den Master schreiben können. Habe ich das soweit richtig verstanden?
...in die alle Slaves Nachrichten für den Master schreiben...
Zitat:wobei jedes Telegramm einen Absender sowie einen Adressaten haben sollte
(19.06.2015 07:27 )n4f3ts schrieb: Das verstehe ich nicht so ganz, bzw. weiß nicht wie ich das in Verbindung mit Queues gemeint ist.
Es soll ja auch möglich sein, dass Slave X mit Slave Y kommuniziert. Wenn diese Kommunikation über den Master läuft, was ratsam wäre, dann muss der ja wissen, wer der Empfänger ist. Deshalb die Adresse. Und wenn der Master sein Telegramm nicht an den Slave weitersenden kann, weil dieser z.B. die Queue zerstört hat, dann muss er eine Antwort an den Absender schicken können, um ihm die Fehlersendung mitteilen zu können, deshalb der Absender.
Ich würde jeden Slave seine eigene Empfangsqueue erstellen lassen mit einem eindeutigen Namen. Danach muss sich dieser Slave beim Master anmelden und ihm seinen Queuenamen oder die Queuereferenz mitteilen. Es soll ja auch möglich sein, dass der Master an einen oder mehrere Slaves Nachrichten verschickt (z.B. beendet euch alle)
Ok, um das mit den Adressen noch einmal zu verdeutlichen. Ich stelle mir das dann in etwa so vor:
Die MasterQueue wo alle Slaves reinschreiben sieht dann in etwa so aus. Sie wird im Blockdiagramm des Masters wie folgt initialisiert:
Und wenn beispielsweise Slave A mit Slave B kommunizieren möchte schreibt Slave A folgendes in die Master Queue (die wiederum im Blockdiagramm von allen Slaves angefordert wird):
Der Master sieht dann von wem die Nachricht kommt und für wen sie ist und leitet entsprechende Befehle über die Queue des Empfängers (in diesem Beispiel Slave B) weiter.
Habe ich das soweit richtig verstanden?
Eine Frage noch hierzu:
Zitat:Danach muss sich dieser Slave beim Master anmelden und ihm seinen Queuenamen oder die Queuereferenz mitteilen.
Das hört sich für mich danach an, dass die Slave Queues dynamisch im Master erstellt werden könnten. Oder liege ich da falsch? Also ich hätte diese jetzt manuell für jeden Slave hinzugefügt.
(19.06.2015 10:51 )n4f3ts schrieb: Die MasterQueue wo alle Slaves reinschreiben sieht dann in etwa so aus. Sie wird im Blockdiagramm des Masters wie folgt initialisiert:
im Prinzip ja. Ich würde allerdings den Queuedatentyp anders wählen. Das schöne bei den LabViewqueues ist ja, dass jede (bestehende) Queue namentlich von jedem VI des Prozesses angefordert werden kann. Dann würde ich Absender und Adressaten auch namentlich (als String) verwenden
(19.06.2015 10:51 )n4f3ts schrieb: Und wenn beispielsweise Slave A mit Slave B kommunizieren möchte schreibt Slave A folgendes in die Master Queue (die wiederum im Blockdiagramm von allen Slaves angefordert wird):
Die Masterqueuereferenz würde ich einfach in eine GV oder in eine FGV schreiben. Das erspart dir die Anforderung derselben Queue in jedem Teilnehmer. Da der Master das zuerst aufzurufende VI sein sollte, muss diese Queue für jeden Teilnehmer bereits bestehen und referenzierbar sein.
(19.06.2015 10:51 )n4f3ts schrieb: Der Master sieht dann von wem die Nachricht kommt und für wen sie ist und leitet entsprechende Befehle über die Queue des Empfängers (in diesem Beispiel Slave B) weiter.
Der Master muss sich im Normalfall nicht um den Absender kümmern. Er kann einfach den Adressaten auslesen und die Nachricht weiterleiten.
Was bei dir komplett fehlt ist eine Nachrichten-ID. Mach verschiedene ID-Klassen auf, die dem Master sagen, was für eine Art Nachricht das ist.
z.B.
Klasse 0-1000 --> Nachrichten der Slaves für den Master bestimmt
ID:1 --> Anmeldung
ID:2 --> Abmeldung
Klasse 1001-2000 --> Nachrichten der Slaves untereinander
ID:1001 --> Nachricht zum weiterleiten
ID:1002 --> Nachricht von einem Slave an alle anderen (z.B. für Zugriffssteuerung, Ausgrauen etc.)
So kannst du die ID an eine Casestruktur koppeln und die entsprechenden Aktionen ausführen.
Und schreib dir von Anfang an eine Doku (Excelsheet) in der du aufschreibst, welche ID wofür ist
(19.06.2015 10:51 )n4f3ts schrieb: Eine Frage noch hierzu:
Zitat:Danach muss sich dieser Slave beim Master anmelden und ihm seinen Queuenamen oder die Queuereferenz mitteilen.
Das hört sich für mich danach an, dass die Slave Queues dynamisch im Master erstellt werden könnten. Oder liege ich da falsch? Also ich hätte diese jetzt manuell für jeden Slave hinzugefügt.
Die Slavequeues sollen nicht dynamisch im Master erstellt werden, er muss nur wissen, welche Teilnehmer es gibt und wie deren Queues heißen. Es kann ja sein, dass der Master von sich aus mit seinen slaves reden will. Dazu braucht er eine Übersicht, welche Slaves überhaupt da sind. Du kannst dr auch eine schlaue Namenshierarchie der slaves ausdenken und deren Queuenamen an ihre VI-Namen koppeln. Dann muss der Master nur die Namen der angemeldeten slaves kennen und kann so auf ihre queuenamen schließen um mit ihnen zu reden.
danke nochmals für deine Hilfe, das hat mich schon ein gutes Stück weitergebracht.
Ob ich das ganze jetzt wirklich mit Klassen mache muss ich mir noch überlegen, da ich hier langsam an die Grenzen meiner LabVIEW Skills gerate. (habe mit Klassen bisher nur erste einfach Übungsaufgaben programmiert...)
Ansonsten versuche ich das ganze mal so in etwa umzusetzen.
(22.06.2015 07:32 )n4f3ts schrieb: Ob ich das ganze jetzt wirklich mit Klassen mache muss ich mir noch überlegen, da ich hier langsam an die Grenzen meiner LabVIEW Skills gerate.
Hallo Steffan,
mit dem Begriff "Klassen" lass dich mal nicht verwirren. Ich meinte damit nur Zahlenbereiche. Das hat den Vorteil, dass du einer ID schon (ohne sie genau zu kennen) ansiehst, zu welcher Art Nachricht sie gehört.
Alles klar, ich hatte jetzt an die Klassen der LVOOP gedacht .
Das einzige was noch unklar ist:
Ich sehe noch nicht den Vorteil wenn ich die Master Queue in eine FGV packe. Diese FGV wäre dann meiner Meinung nach folgendermaßen aufgebaut:
Eine While-Schleife die sich nach einem Durchlauf immer beendet. In dieser eine Case-Struktur mit mindestens "Init" und "GetQueueReferenz". Das "Init" Case wird beim ersten mal durchlaufen um die Queue zu initialisieren und die Queue Referenz in ein Schieberegister zu packen. In allen Slave VI´s muss das "GetQueueReferenz"-Case der FGV ja auch einmal aufgerufen werden um die Queue-Referenz zu bekommen.
Aus diesem Grund könnte ich doch einfach dieses SubVI:
jeweils in allen Programmen einmal aufrufen. Die Queue wird dann ja auch nur einmal erstellt und ansonsten habe ich die Referenz der Queue.
Oder sehe ich das falsch?
im Großen und Ganzen hast du wohl recht.
Im Moment fällt mir auch nicht wirklich ein Grund ein, der bei der Queue-Anforderung gegen ein normales SUB-VI spricht.
Ich verwende aus Gewohnheit in solchen Fällen eine FGV, in der ich dann alle nötigen Queues des Projekts verwalte.