LabVIEWForum.de - GetSnapshot-Funktion funktioniert in While-Schleife nicht richtig

LabVIEWForum.de

Normale Version: GetSnapshot-Funktion funktioniert in While-Schleife nicht richtig
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Hallo,

ich habe ein Programm, mit dem ich über diverse Funktionen aus einer DLL-Datei von einer Kamera (Sumix SMX150) Bilder hole, wobei wir die Kamera extern triggern. In der DLL ist eine Funktion "CxGetSnapshot" enthalten, die bei einer Triggerflanke ein einzelnes Kamerabild erzeugt. Im Prinzip funktioniert die Funktion einwandfrei. Ruft man die Funktion 1mal auf, bekommt man auch 1 Snapshot. Würde man beispielsweise die Funktion 100mal hintereinander mit 100 verschiedenen DLL-Knoten aufrufen, würde man auch 100 Frames bekommen. Soweit so gut!

Nun ist diese Vorgehensweise etwas umständlich, aber dafür gibt es ja Schleifen. Genau hier liegt aber das Problem.
Angenommen, das Triggersignal kommt mit 0,5Hz, dann erwartet man, dass alle 2 Sekunden ein Bild aufgenommen wird. Tatsächlich aber werden Bilder mit der höchstmöglichen Framerate (ca. 30fps) erzeugt.

Ich kann definitiv sagen, dass die Kamera auf den Triggerpuls reagiert, da wir sonst nicht unsere extrem kurzen Laserpulse (einige Nanosekunden) detektieren könnten. Außerdem kann man beid er Bilddarstellung alle 2 Sekunden ein Flackern im Bild erkennen. Es scheint jedoch fast so, als ob zwischen den getriggerten Bildern einfach beliebige weitere Bilder erzeugt werden.

Ich bin ein wenig am Verzweifeln, denn dies scheint so ein Problem zu sein vom Typ: Sollte eigentlich funktionieren, tut es aber nicht. Vielleicht habe ich aber einfach nur etwas übersehen. Für eure Hilfe bin ich jedenfalls sehr dankbar.

schöne Grüße
labrat
Hallo,

wenn ich dein Programm richtig verstehe, wird die GetSnapshot DLL ständig aufgerufen. Setzte doch eine "Wait" Funktion mit dem Wert 2000 in die While-Schleife.
Die GetSnapshot-Funktion sollte eigentlich auf ein externes Triggersignal waren, d.h. die Schleife (inkl. Snapshotfunktion) sollte sowieso nur alle 2 Sekunden aufgerufen werden. So wie es aussieht, reagiert die Funktion auch auf das Triggersignal. Aber sie wird eben auch permanent innerhalb der 2 Sekunden ausgeführt, wenn auch gerade kein Trigger anliegt.

Aber du hast natürlich recht. Füge ich eine Wartefunktion ein, kann die Schleife natürlich nur alle 2 Sekunden durchlaufen werden. Problem gelöst! Aber: Der 2 Sekunden Takt, war nur zur Verdeutlichung gedacht. Bei einer so langsamen Frequenz kann man eben gut erkennen, wie die Funktion auf einen Trigger reagiert - oder eben nicht. In Wirklichkeit benötigen wir deutlich höhere Frameraten (25 - 100 fps). Da wird es dann extrem schwierig das exakte Timeing hinzubekommen.

Kann es vielleicht sein, dass etwas mit der GetSnapshotfunktion ansich nicht stimmt? Das dürfte aber doch eigentlich nicht vorkommen.
Laut Hersteller soll die Funktion tatsächlich nämlich nur 1 Frame pro 1 Triggerflanke einholen.

schöne Grüße
labrat
Wenn die GetSnapshot-Funktion auf das externes Triggersignal warten soll, dann würde ich das Trigersignal mit Hilfe einer While-Schleife abfragen und wenn der Wert "True" ist die Dll-Funktion einmal aufrufen lassen.
In deinem Programm wird die DLL-Funktion ständig aufgerufen.

Das wäre zumindest mein Ansatz Wink
Im Prinzip hast du recht, so würde es gehen. Aber an müsste man anstelle der Snapshot-Funktion natürlich ständig den Trigger abfragen. Das hieße dann aber, dass eine DAQ-Karte benötigt wird um das Triggersignal einzulesen.

Das Seltsame ist ja, dass die Funktion nach aufruf auch tatsächlich auf eine Triggerflanke wartet. Kaum packt man sie in eine Schleife scheint das Warte-Feature jedoch nicht mehr zu funktionieren. Das dürfte doch eigentlich nicht so sein, oder?
(07.02.2012 22:30 )labrat schrieb: [ -> ]Im Prinzip hast du recht, so würde es gehen. Aber an müsste man anstelle der Snapshot-Funktion natürlich ständig den Trigger abfragen. Das hieße dann aber, dass eine DAQ-Karte benötigt wird um das Triggersignal einzulesen.

Das Seltsame ist ja, dass die Funktion nach aufruf auch tatsächlich auf eine Triggerflanke wartet. Kaum packt man sie in eine Schleife scheint das Warte-Feature jedoch nicht mehr zu funktionieren. Das dürfte doch eigentlich nicht so sein, oder?

Dürfte? Es wäre natürlich sinnvoll wenn das nicht so wäre, aber da Du nicht weisst was der Programmierer getan hat, ist es schwierig zu beurteilen ob das jetzt ein Bug ist oder einfach ein unwillkommenes Feature. Wahrscheinlich verhedert sich die DLL an den inherenten Multithreadingmöglichkeiten von LabVIEW, indem sie beispielsweise per aufrufendem Thread beihält ob der Trigger schon abgefragt wurde. Funktioniert perfekt wenn man das aus einer C Routine in einer Schleife aufruft, aber in LabVIEW ist die Chance recht gross, dass bei einem folgenden Aufruf ein anderer Thread aus dem vorhandenen Pool verwendet wird, dann zuvor.

Abhilfen wären:

- Sicherstellen dass Du die Parallelisierung der Loop nicht eingeschaltet hast.
- Dem VI explizit ein bestimmtes Execution System zuweisen und mit dem vi.lib\utility\sysinfo.llb\threadconfig.vi diesem Execution System nur einen einzigen Thread zuweisen. LabVIEW muss neu gestartet werden, da die Threadkonfiguration nur beim Starten gemacht wird.
- Die DLL Funktion im UI Thread laufen lassen (nicht empfehlenswert da Dein Image Capture dann mit dem LabVIEW UI konkuriert und das kann unschöne Ergebnisse haben (schlechte Performance) bis hin zu totalen Lockouts der LabVIEW Applikation, wenn die DLL sich selber auch noch irgendwie in die Windows Message Queue einhängt).
Hallo labrat,

zunächst einmal ein kleiner Programmierhinweis. In deinem VI aus Beitrag #1 verwendest du eine flache Sequenzstruktur. Diese brauchst du doch garnicht. Denke an das Datenflussprinzip. Dann wirst du feststellen, dass diese Dinge so oder so nacheinander ablaufen müssen.

Darüber hinaus wäre das "Producer-Consumer" Design Pattern für deine Anwendung sehr hilfreich. Dann einfach eine Eventstruktur nutzen und bei einem Triggersignal in die Queue schreiben. Das lässt dann auch deine CPU-Auslastung sinken, da nicht ständig in der Schleife rotiert wird. Dann wird die Funktion auch nur genau dann aufgerufen, wenn es sein muss. Dies ist dann ähnlich zu dem Vorschlag von cnongs.

MfG Carsten
Referenz-URLs