WinCC Verbindungsprobleme Libnodave

Jennsy

Level-1
Beiträge
81
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Ich habe ein .Net Control in WinCC (V7.0 und V7.2) eingebunden, der Verbindungsaufbau, Schreiben, Lesen aus SPS funktioniert prima, jedoch kommt es von Zeit zu Zeit zu Verbindungsaufällen (Verbindung zur SPS funktioniert jedoch, ping geht). Auch wenn ich einen Button, in meinem Control einfüge, zum erneuten Verbindungsaufbau, funktioniert es nicht, erst nachdem ich die Runtime neu starte, ist die Verbindung wieder da. Wenn ich die Runtime etwas laufen lasse, dann geht die Verbindung auch wieder.

Arbeitet vll auch jemand mit Libnodave und hatte ein ähnliches Problem?
Und hat vll. eine Idee, wo der Fehler liegen könnte?

Vielen Dank im Voraus!

mfG
 
Kannst Du mir erklären, warum Du in WinCC libnodave zur Kommunikation mit der SPS verwendest? Eigentlich sollte ja WinCC in der Lage sein, eigenständig mit der SPS zu kommunizieren ? :confused:

Gruß.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Natürlich, aber für einige Einstellungen, welche sonst sehr viele Variablen verbrauchen würden, arbeiten wir mit diesem .Net Control, welches ich mit VB programmiert habe, und so auch viele Funktionen dort nutzen konnte, die in WinCC etwas eingeschränkter sind. Denn so greife ich mit dem .Net Control über libnodave direkt auf die SPS zu...

mfG
 
:confused:
Ich schließe die Libnodave-Verbindung ja eigentlich nicht (nicht wissentlich zumindest), es wird nur immer mal wieder zwischendurch (oft nach schnellen Bildwechseln) unterbrochen.
Aber prinzipiell öffne ich ihn hiermit den Socket (...=libnodave.openSocket(102, IP) ) beim Aufbauen der Verbindung, und schließe ihn aber nirgends wieder...Sollte dieser wieder geschlossen werden?

mfG Jenny
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hmm, irgendwann gehen Dir dann Ressourcen aus.
Beobachte mal die Anzahl der offenen Ports, z.B. mit netstat.

Code:
Private Sub cleanUp(ByRef ph As Long, ByRef di As Long, ByRef dc As Long)
Dim res
If dc <> 0 Then
    res = daveDisconnectPLC(dc)
    Call daveFree(dc)
    dc = 0
End If
If di <> 0 Then
    res = daveDisconnectAdapter(di)
    Call daveFree(di)
    di = 0
End If
[COLOR="#A52A2A"]If ph <> 0 Then
    res = closePort(ph)
    res = closeSocket(ph) 'bei ISO over TCP, sonst wird bei jedem opensocket() ein weiterer Port belegt
    ph = 0
End If[/COLOR]
End Sub
 
Hallo PN/DP,
Vielen Dank für deine Antwort! Habe das anscheinend komplett überlesen in den Erklärungen.
Nur ich hätte noch eine Bitte, könntest du mir das vielleich noch erklären, wo ich das einbauen muss? Weil beim Laden der Form stelle ich ja wie gesagt, die Verbindung her, und öffne den Socket, aber ich darf ihn hier ja auch nicht schon wieder schließen, oder doch? Bitte entschuldige meine vielleicht blöde Frage, aber ich arbeite noch nicht wirklich lange in dieser Branche und für mich ist das alles noch so gut wie Neuland...
Code:
Private Sub UserControl1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' *******************Verbindung aufbauen**************************************************
        fds.rfd = libnodave.openSocket(102, IP)
        fds.wfd = fds.rfd
        If fds.rfd > 0 Then       ' if step 1 is ok
            di = New libnodave.daveInterface(fds, "IF1", 0, libnodave.daveProtoISOTCP, libnodave.daveSpeed187k)
            di.setTimeout(1000000)  ' Make this longer if you have a very long response time
            res = di.initAdapter
            '
            If res = 0 Then       ' init Adapter is ok
                dc = New libnodave.daveConnection(di, 0, rack, slot)  ' rack and slot don't matter in case of MPI
                res = dc.connectPLC()
                If res = 0 Then
                    Connection = True
                    ToolStripStatusLabel1.Text = "Connected " + IP
                Else
                    ToolStripStatusLabel1.Text = "Connection lost"

                End If
            End If
        End If
        '*****************Sichtbarkeiten beim Start festlegen

        '***und dann werden noch die Texte für Buttons etc. aus einem Textfile geladen, bzw. die Sprachauswahl getroffen
End Sub
 
für einige Einstellungen, welche sonst sehr viele Variablen verbrauchen würden, arbeiten wir mit diesem .Net Control, welches ich mit VB programmiert habe
Solche Powertag_sparen-Verbindungen würde ich nur für eher selten benötigte Sachen benutzen. Für alles was zyklisch benötigt wird würde ich auf jeden Fall die WinCC-eigene Kommunikation benutzen. Außerdem muß man sicher aufpassen, daß man keine Tags in beiden Verbindungen verwendet.


könntest du mir das vielleich noch erklären, wo ich das einbauen muss?
Mit "richtigem" VB, .Net, Forms ... habe ich keine Erfahrung - kann also keine fundierten Tips geben. Mein Code ist VBA (Excel). Ein komplett-Projekt findest Du hier.

Ich lese immer nur einmalig "auf Knopfdruck" die Daten aus der SPS.
Dafür baue ich die LibNoDave-Verbindung zur SPS auf, lese meine Variablen und schließe die Verbindung sofort wieder. Etwa so:
Code:
Dim ph As Long, di As Long, dc As Long
Dim res, resmb, peer$, MpiPpi, Rack, slot

ph = 0: di = 0: dc = 0
' Verbindungsparameter TCP: peer$, Rack, Slot (MpiPpi wird nicht genutzt)
peer$ = "192.168.123.123"
MpiPpi = 2: Rack = 0: slot = 2

ph = openSocket(102, peer$) ' for ISO over TCP
If (ph > 0) Then
    di = daveNewInterface(ph, ph, "IF1", 0, daveProtoISOTCP, daveSpeed187k)
    res = daveInitAdapter(di)
    If res = 0 Then
        dc = daveNewConnection(di, MpiPpi, Rack, slot)
        res = daveConnectPLC(dc)
        If res = 0 Then ' Verbindung zu PLC erfolgreich aufgebaut
...
            'Werte lesen aus DB123.DBB0...DBB13 14 Bytes
            res2 = daveReadBytes(dc, daveDB, 123, 0, 14, 0)
...
End If

Call cleanUp(ph, di, dc)

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit "richtigem" VB, .Net, Forms ... habe ich keine Erfahrung - kann also keine fundierten Tips geben. Mein Code ist VBA (Excel). Ein komplett-Projekt findest Du hier.
Vielen, vielen Dank trotzdem.
Nur verstehe ich nicht ganz, wann dieser CleanUp aufgerufen wird? Kann ich diesen CleanUp jedes Mal beim Laden der Form machen, bevor ich die Verbindung erneut überprüfe/herstelle und die Sockets öffne? Denn irgendwie scheint das bei mir nicht so ganz zu funktionieren :-(

Und wenn ich mit einem Button die Verbindung unterbreche:
Code:
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click    
    dc.disconnectPLC()
        libnodave.closePort(fds.rfd)
        libnodave.closePort(fds.wfd)
       di.disconnectAdapter()
             If res = 0 Then       ' init Adapter is ok
            dc = New libnodave.daveConnection(di, 0, rack, slot)  ' rack and slot don't matter in case of MPI
            res = dc.connectPLC()
            If res = 0 Then       ' init Adapter is ok
                Connection = True
                ToolStripStatusLabel1.Text = "Connected " + IP
            Else
                ToolStripStatusLabel1.Text = "Connection lost"
            End If

        End If
End Sub

und mit einem zweiten wieder aktiviere:
Code:
 Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        If res = -1025 Or res = -1 Or res = 0 Then
            MsgBox("trifft zu", MsgBoxStyle.DefaultButton1, "Test")
            fds.rfd = libnodave.openSocket(102, IP)
            MsgBox("open socket", MsgBoxStyle.DefaultButton1, "Test")
            fds.wfd = fds.rfd
            If fds.rfd > 0 Then       ' if step 1 is ok
                di = New libnodave.daveInterface(fds, "IF1", 0, libnodave.daveProtoISOTCP, libnodave.daveSpeed187k)
                di.setTimeout(1000000)  ' Make this longer if you have a very long response time
                res = di.initAdapter
                '
                MsgBox(res, MsgBoxStyle.DefaultButton1, "Test")
                If res = 0 Then       ' init Adapter is ok
                    dc = New libnodave.daveConnection(di, 0, rack, slot)  ' rack and slot don't matter in case of MPI
                    res = dc.connectPLC()
                    If res = 0 Then
                        Connection = True
                        ToolStripStatusLabel1.Text = "Connected " + IP
                    Else
                        ToolStripStatusLabel1.Text = "Connection lost"

                    End If
                End If
                End If
            End If
       
    End Sub
geht das ganze, nur sobald, die Verbindung 'automatisch' unterbrochen wird, funktioniert es nicht mehr, sie mit diesem 'Verbindung herstellen'-Button zu reaktivieren...:confused:

mfg Jenny
 
Zuletzt bearbeitet:
Bitte entschuldige meine vielleicht blöde Frage, aber ich arbeite noch nicht wirklich lange in dieser Branche und für mich ist das alles noch so gut wie Neuland...

Solche Powertag_sparen-Verbindungen würde ich nur für eher selten benötigte Sachen benutzen. Für alles was zyklisch benötigt wird würde ich auf jeden Fall die WinCC-eigene Kommunikation benutzen. Außerdem muß man sicher aufpassen, daß man keine Tags in beiden Verbindungen verwendet.

Jo, solch ein Kommentar lag mir schon lange auf der Zunge :)

Nebenbei, man hat mit den selbstgebastelten Controls für WinCC auch meist mehr Ärger als Freude. Spätestens beim nächsten WinCC Update. Und was ist eigentlich bei WinCC Client-Server Lösungen? Da funktioniert das Ganze sowieso nicht.

Ich kenn jetzt Deine Anwendung zwar nicht, aber die Frage, ob das Ganze Sinn macht, würd ich mir schon stellen.

Gruß.
 
irgendwie scheint das bei mir nicht so ganz zu funktionieren :-(
Beim Aufbauen und Abbauen der LibNoDave-Verbindung muß die Reihenfolge der Aktionen genau eingehalten werden! Dein Code Button3../Button4.. sieht für mich ziemlich unplanmäßig aus ... Außerdem vermisse ich das closeSocket(...) - ich bin nicht sicher, doch ich meine, erst dann wird die Verbindungsressource auf der CPU wieder freigegeben. Ohne das closeSocket gehen Dir aber auf jeden Fall irgendwann die Verbindungsressourcen auf dem PC aus.

Wenn Du feststellst, daß die Verbindung zur CPU nicht mehr funktioniert, dann baue die Verbindungsressourcen komplett ab (inklusive closeSocket(...)!) und verbinde komplett neu.
Besser: halte die Verbindung nur kurzzeitig, nur solange Du sie tatsächlich brauchst.

Hier nochmal schematisch die korrekte Reihenfolge. Siehe auch die Beiträge #8 und #6
Code:
ph = 0: di = 0: dc = 0

//Reihenfolge Verbindungsaufbau
ph = openSocket(...)
If ph > 0 Then
    di = daveNewInterface(ph, ...)
    res = daveInitAdapter(di)
    If res = 0 Then
        dc = daveNewConnection(di, ...)
        res = daveConnectPLC(dc)
        If res = 0 Then ' Verbindung zu PLC erfolgreich aufgebaut
            ' tu was produktives ...
        End If
    End If
End If

//Reihenfolge Verbindungsabbau
If dc <> 0 Then
    res = daveDisconnectPLC(dc)
    Call daveFree(dc)
    dc = 0
End If
If di <> 0 Then
    res = daveDisconnectAdapter(di)
    Call daveFree(di)
    di = 0
End If
If ph <> 0 Then
    res = closePort(ph)
    res = closeSocket(ph)
    ph = 0
End If

PS:
Ich meine, das di.setTimeout(1000000) kann man weglassen, das hat bei ISO-on-TCP keinen Effekt.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast du denn schonmal geprüft wie sich dein .Net Control überhaupt verhält wenn z.B. das Bild gewechselt wird?
Wird dann der Destruktor aufgerufen, oder bleibt das Objekt bestehen und wenn das Bild neu aufgerufen wird, dann wird ein neues erzeugt?

Das alles musst du in deinem Control behandeln. Also im Destruktor auf jeden Fall die Verbindung trennen und alle Ressourcen freigeben (kann ja sein dass der Bediener das Bild wechselt obwohl noch eine Abfrage läuft), anonsten kann der Garbage Collector den Speicher nicht wieder freigeben.

Mir ist das Erstellen von eigenen Controls bei WinCC zu spärlich beschrieben. Du kannst die Kommunikation mit libnodave auch direkt in WinCC C-Skript schreiben, siehe hier:
http://www.sps-forum.de/hochsprachen-opc/47286-libnodave-mit-wincc-7-0-a.html#post346563
 
Hallo,
@ducati
Bin natürlich für jederlei Anmerkungen (auch Kritik) dankbar. Jedoch ist es so, dass wir vorher schon mit einem ActiveX (Delphi) gearbeitet haben, und meine Aufgabe war es, dieses Control zu erneuern, und ich habe dafür diese Möglichkeit gewählt, da sie am ehesten zu den alten Erfordernissen herankommt, bzw. auch neue Möglichkeiten bietet.

@PN/DP und Thomas_v2.1
Dankeschön für eure Hilfe!!
Ich habe es jetzt mal so gelöst, dass ich die Verbindungen beim Unload der Form schließe. (was, wenn ich es mit netstat verfolge, so auch zu funktionieren scheint...)

Code:
Private Sub UserControl1_Unload(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.HandleDestroyed
        dc.disconnectPLC()
        libnodave.closePort(fds.rfd)
        libnodave.closePort(fds.wfd)
        libnodave.closeSocket(102)
        di.disconnectAdapter()
        End Sub

mfG Jenny
 
Zuletzt bearbeitet:
Hallo
Bin durch Zufall auf den alten Thread gestossen.
@Jennsy
Bedenke bitte, dass es das Ereigniss "HandleDestroyed" erst ab .Net 3,5 SP1 vollständig unterstützt wird.

Plattform
", , Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core-Rolle wird nicht unterstützt), Windows Server 2008 R2 (Server Core-Rolle wird mit SP1 oder höher unterstützt; Itanium wird nicht unterstützt)"

Ich habe bei .Net schon öfter bei einer Inbetriebnahme Updates machen müssen, weil bestimmte Eigenschaften nicht funktionierten.
Grüsse Holger
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@holgermaik

Vielen Dank für die Info! Ich verwende .Net 3.5 , denn neuere Versionen sind (zumindest mal unter WinCC V7.0 ) nicht unterstützt worden.
Habs jetzt auch auf Win7 /Windows Server 2008 R2 mit WinCC 7.2 ausprobiert und es wird ebenfalls noch alles unterstützt, aber für zukünftige Anwendungsfälle ist das sicherlich zu klären, was womit noch kompatibel ist, damit auch alle Funktionen weiterhin zur Verfügung stehen.

mfG Jenny
 
Zurück
Oben