Grundsätzliche Vorgehensweise

Dies ist das deutsche Forum für alle Themen um den IO-Warrior. Beiträge bitte nur in Deutsch.

Moderator: Guido Körber

Post Reply
MeisterM
Posts: 9
Joined: Sat Nov 11, 2006 1:09 pm

Grundsätzliche Vorgehensweise

Post by MeisterM »

Hallo Leute,

ich steuer derzeit einen IOW 40 mit VB 6 an. Dazu sind an allen IOWs die ersten beiden Ports als Eingänge und die beiden anderen Ports als Ausgänge konfiguriert. (Optokopplereingänge und Relaisausgänge)
Dabei nutze ich die ReadNonBlocking Funktion und lese alle Daten. Schaue dann nach ob etwas geschrieben muss, schreibe und beginne die Schleife dann von vorn.

Nun schreibe ich das Programm neu in VB.net. Da dort nun Threads unterstützt werden, habe ich mir gedacht, dass ich Lesen und Schreiben trenne. Das wäre meiner Meinung nach effektiver. Vorgestellt habe ich mir das ganze so:

Hauptthread:
IowKitOpenDevice()
Lesethread starten
IowKitCloseDevice()

Lesethread:
Do
IowKitRead
Loop

Schreibfunktion:
IowKitWrite

Somit hätte ich das Lesen vom Schreiben getrennt und könnte immer direkt schreiben, wenn ich es für notwendig halte.
Die Lesefunktion würde die ganze Zeit laufen und die Eingänge überwachen.

Jetzt habe ich ein paar Fragen.

1. Macht das Sinn so?
2. Wie lange steht der Thread in der Read Methode wenn keine Daten kommen?
3. Bricht die Read Methode ab, wenn ich das Programm beenden möchte und die Devices schließe, oder blockiert die Read Methode weiterhin?
4. Habt ihr sonst noch Ideen?

Edit:
5. Wie kann ich mitbekommen, ob der IOW vom PC abgezogen wurde, oder ein neuer IOW eingesteckt?

Gruß
Holger

Gute Nacht.
User avatar
Christoph Jung
Posts: 673
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Grundsätzliche Vorgehensweise

Post by Christoph Jung »

Bei Threads muss man höllisch aufpassen und wissen WAS man tut und WANN man es tut (!) .
Der Lesethread fungiert in dem Fall hier als Timer, der alle X milisekunden schaut ob daten da sind. Allerdings emphele ich dorte ReadNonBlocking, da Read auch mit Timeout 1 Sekunde steht wenn nichts an Daten ankommt.

zu 1: Macht Sinn aber trotzdem würde ich schaun ob nicht ein normaler Timer oder ein Multimediatimer ausreicht. Damit man den Overead der Threads nicht hat.
zu 2: Der Thread steht ohne IowKitSetTimeout, bis Daten ankommen, mit Timeout minimal 1 Sekunde
zu 3: Jein die Read-Funktion bricht nicht ab, da sie in einem extra Thread läuft. Daher muss der Thread zerstört werden damit Read abbricht. Sicher bin ich da aber nicht 100%ig
zu 4: Ja, Multimedia-Timer oder normaler OnTimer versuchen.
zu 5: WM_DEVICECHANGE ist da ein Ansatz. Allerdings gibt es da einige Probleme, da die DLL nicht korrekt aus der Funktion aufgerufen wird. Woran das liegt kann ich leider nicht sagen, denn wenn man das ganze in einem Timer alle Sekunde, pollt klappt es probelmlos. Also einen Timer verwenden, der jede Sekunde schaut ob sich an den IO-Warriorn was geändert hat (Seriennummern oder anderes). Oder mal nach WM_DEVICECHANGE googlen.
Software developer
MeisterM
Posts: 9
Joined: Sat Nov 11, 2006 1:09 pm

Re: Grundsätzliche Vorgehensweise

Post by MeisterM »

OK zum Thema Timer. Wie oft könnte man dann pollen? Es sollen auch Veränderungen gemessen werden, die in einem niedrigen zeitlichen Rahmen liegen.

Deshalb ja meine Idee, nen Thread mit Read laufen zu lassen, da der ja dann blockiert wird, bis der IOW Daten für mich hat.
Mit dem pollen müsste ich ja ständig abfragen.

zu 3) Das wäre ja auch kein Problem. War halt nur meine Frage.

Nachtrag:

Das Ändern von Devices könnte ich dann z.B. auch mit IowKitGetNumDevs ständig abfragen? Wenn sich die Anzahl geändert hat, dann wurde ja entweder was abgezogen oder drangesteckt. Kann man das auch wirklich 1 sekündlich machen oder schmiert dann irgendwann die DLL ab? :p
Muss ich dann vorher wieder ein Open machen oder kann man das direkt nutzen?

Gruß
Holger
User avatar
Christoph Jung
Posts: 673
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Grundsätzliche Vorgehensweise

Post by Christoph Jung »

Also zum Timer muss man beachten, dass der IO-Warrior auch eine Maximale Frequenz hat. Also beim IOW40 sind das 125Hz, sprich 7-8 milisekunden die man pollen darf / kann. Mit einem normalen Timer (WM_TIMER) schafft man maximal 18ms bei niedriger Systemlast. Mit einem Multimedia-Timer kann man bis auf 1 milisekunde runter.

Das mit dem blockiertem Thread müsste man halt mal testen. Ich habe so was noch nie benutzen müssen darum habe ich da keine Erfahrungswerte. Auch nicht was passiert wenn das Programm abstürzt oder etwas nicht geplantes passiert. Das müsste mal alles UNBEDINGT abfagen, nicht das das Programm den Rechner lahmlegt.

Das pollen nach neuen Geräten ist nicht so intensiv. Man muss ja nicht alle Sekunde pollen, ist aber auch nicht Sytemkritisch.
IowKitGetNumDevs() liefert die aktuelle anzahl aller IO-Warior nach einem IowKitOpenDevice() zurück (Wichtig: vorer MUSS open gemacht werden, sonst kommt immer das selber ergebnis zurück, auch wenn sich was geändert hat). Man kann noch etwas machen. Wenn man vor dem Lesen ein Write auf einen nicht belegten Pin macht und er schief geht kann man von ausgehen, dass der IO-Warrior nicht mehr da ist. Das ist sozusagen eine Abfrage ob jemand gültiges da ist oder nicht.

Wieviele IO-Warrior sollten denn gleichzeitig angesteuert werden? Bei einem einzigen ist dieser Aufwand etwas zu viel des Guten. Das macht nur sinn, wenn man mehrere gleichzeitig verwenden will.
Software developer
MeisterM
Posts: 9
Joined: Sat Nov 11, 2006 1:09 pm

Re: Grundsätzliche Vorgehensweise

Post by MeisterM »

Ja zwischen eins und vielen. Haben mittlerweile hier vor Ort schon 3 Stück dran. Allerdings will ich das für jeden IOWarrior in einer separaten Klasse machen. (Das Program ist das Bindeglied zwischen PC und Außenwelt und soll mit mehreren Geräten konfiguriert werden. Also nicht nur IO Warriors. Wenn dann aber jemand zwei IO Warriors angeschlossen hat, werden halt zwei Instanzen geöffnet, die dann jeweils einen IO Warrior ansteuern) Jeweils dann auch mit eigenem Thread.)

Also empfohlen wird mittels MediaTimer und ReadNonBlocking zu pollen anstatt mittels Read einen Thread blocken und auf Antwort vom IOW zu warten? Kann ich mittels ReadNonBlocking dann auch ermitteln ob sich etwas verändert hat, oder nicht?
User avatar
Christoph Jung
Posts: 673
Joined: Sun Oct 08, 2006 3:43 pm
Location: Germany / Berlin
Contact:

Re: Grundsätzliche Vorgehensweise

Post by Christoph Jung »

Das wird jetzt ein Problem. Mit der aktuellen DLL kann man keine mehreren Instanzen (also mehrere Programme) Managen. Wenn ein Programm sich die DLL holt / greift, dann ist sie Gesperrt und kein anderes Programm kann die IO-Warrior über die DLL ansprechen. Man bekommt dann immer NULL zurück. Das lässt sich leider auch nicht ändern.

Also ein Programm kann einen oder alle IO-Warrior benutzen, aber ein weiteres geht dann leer aus.
Mit der alten 1.4 API ist das noch möglich allerdings geben wir keinen Support auf die alte Version.

Es kommt auf einen Versuch an ob es mit einem Thread funktioniert oder nicht. Ein Workthread hat halt so seine Tücken und Eigenheiten.
Ein Timer aber auch. Wenn man mit ReadNonBlocking arbeitet muss man sich halt drum kümmern ob das was da ankommt auch neu ist oder nicht.


Was soll denn genau mit dem Programm gemacht werden? Vllt. wäre das ein besserer Ansatzpunkt für eine Lösung des Problems.
Software developer
MeisterM
Posts: 9
Joined: Sat Nov 11, 2006 1:09 pm

Re: Grundsätzliche Vorgehensweise

Post by MeisterM »

Naja ist ja kein Problem. Ich kann das Open ja im Mainprogramm öffnen und dann auf Read un Write in den Klassen zugreifen. Warum sollte das ein Problem geben?
Post Reply