Beckhoff-ADS und Threads

drfunfrock

Level-1
Beiträge
934
Reaktionspunkte
72
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe für .NET2.0 eine Klassenbibliothek in VB geschrieben, damit ich TwinCat bequem die Variablenwerte entlocke. Nur habe ich massiv mit Thread gearbeitet, damit die Sache robust wird und ich bei einem Verbindungsabbruch, die Verbindung neu aufbauen kann. Mein Prob:

Ich sende aus diesen Threads Events, die jedoch im Thread und nicht im Thread des Unser-Interfaces abgearbeitet werden, so das Zuweisungen wie

textbox.text = PLCVar.value

nicht mehr möglich sind und ich mit Invoke arbeiten muss. Mein Wunsch ist es eine Komponente zu bauen, die das umgeht damit auch meine Kollegen damit zurechtkommen und intern trotzdem mit Threads arbeitet. Im Prinzip müsste ich also einen Mechannismus bauen, der die Erzeugung der Events in den Thread des User-Interfaces verlagert. Nur fällt mir dazu keine Lösung ein.

Hat jemand eine Idee?
 
Hmm, so ganz hab ich's jetzt noch nicht verstanden, aber deine Klassenbibliothek könnte ich gebrauchen. ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Na ja, den Code kann ich dir nicht geben, aber Tips sollst du bekommen:

Ich habe eine Klasse PLC (englisch für SPS), die in einem Thread einen Automaten zum Verbindungsaufbau hat, damit ich die Verbindung jederzeit automatisch neu aufbauen kann. 3 weitere Threads mit verschiedenen Zykluszeiten sind für das Auslesen der Variablen. Beim Verbindungsaufbau versucht man zuerst das Objekt tcADSClient aus der TwinCat Bibliothek zu initialisieren. Dann hat man eine Verbindung zu SPS. Als nächstes checke ich mit ReadState() ob die SPS überhaupt im RUN-State ist, um dann zu checken, ob das richtige Programm geladen wurde, indem ich eine Variable versuche auszulesen.

Dann baue ich anhand einer Liste ein Dictionary mit allen PLC-Variablen-Objekten auf, die dann auch schon direkt auf die SPS-Variablen zugreifen können.

Nun brauch ich in einem der 3 Lese-Threads nur noch zu schauen, ob PLC-Variablen-Objekt in die entsprechende Zeit-Klasse gehört und wenn lese ich sie aus. Hat sich der Inhalt geändert lege ich Namen und Inhalt in einer Liste ab. Sind alle Variablen ausgelesen, sende ich die Liste per Event an das User-Programm.

Nun zu den PLC-Variablen-Objekten:

- Alle basieren auf einer Basisklasse, die das IDispose-Interface implementiert:
Code:
    Public Overloads Sub Dispose() Implements IDisposable.Dispose
        Me.adsStream.Close()
        Me.adsStream.Dispose()
        Me.adsStream = Nothing
        adsClient.DeleteVariableHandle(Me.hVar)
        GC.SuppressFinalize(Me)
    End Sub

Der Sinn ist, dass ich die Handles explizit freigeben kann, sonst gehen dir irgendwann die Dinger in TwinCat aus. Ich habe folgende Methoden und Propertys implementiert:

connect()
read()
write()
changed() /* Variable hat sich geändert */
path /* Access-Pfad z.B. ".machine1.output" */
siz
handle
adsstream

Das sollte als erste Idee reichen. Wichtig ist nur, dass die Verbindung zu jeder Zeit neu aufbauen kannst, dh. das Programm die Variablenhandles auch wieder freigibt, weil TwinCat versucht alle jemals angeforderten Variablen aktuell zu halten! Hat man das nicht getan und baut nach einem Lesefehler die Verbindung ein 2. mal auf, steigt die CPU-Beanspruchung von TwinCat erheblich und bleibt irgendwann stehen. Dh. sollte dein Automat nach einem Lese-Fehler (Exception) alle Variablen freigeben und dann alles neu aufbauen.
 
Zurück
Oben