Libnodave lernen

Zuviel Werbung?
-> Hier kostenlos registrieren
Ich meine, das schafft noch nichtmal Step7, zyklusgenau alle 10ms auszulesen.
Puffere Deine Messdaten in einen DB, da bist Du auf der sicheren Seite, egal wie schnell Deine SPS ist.
Am Ende des Meßzyklus setze ein Triggerbit, dann kannst Du in aller Ruhe den Datenblock auslesen.

Zur Kommunikationsgeschwindigkeit gibt es Erfahrungen von Forumsmitgliedern, die werden sich sicher noch melden. Irgendwo gibt es hier im Forum auch schon Beiträge mit Zeitangaben.

Harald
 
Wenn ich nur eine Fliesskommazahl aus der SPS lese mit ReadBytes und GetFloat dann ist die Zykluszeit in der VB6 Loop-Until-Schleife (gelesen mit timeGetTime aus der (winmm.dll ) durchschnittlich 20ms. Lese ich aber drei Fliesskommazahlen aus der SPS schwillt die Zykluszeit in meiner Schleife auf 70-80ms an.

Ich moechte so wie das alle Programme machen, die Daten aus der SPS lesen, keine Veraenderungen am SPS Programm machen. Ich moechte eine Daten-Rate von 20-30ms erreichen, und dabei ungefaehr 8 Worte lesen.

Leider bekomme ich beim Execute-Befehl die Fehlermeldung 5, means the data address is beyond the CPUs address range.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Liest du ein- oder 3 mal mit ReadBytes? wenn du readmes und faqs gelesen hast, wirst du auch gelesen haben, daß ich dazu rate, möglichst viele Variablen en bloc zu lesen. Die Ausführungszeit von getFloat ist vernachlässigbar.
 
Ich selber habe keine Zeitmessungen gemacht doch ich meine, es macht fast keinen Unterschied in der Geschwindigkeit, ob man 1 REAL oder 50 REAL aus einem Array mit ReadBytes liest. Wenn man jeden REAL in einer extra Anfrage liest, dann multipliziert sich natürlich die Auslesezeit. Wenn Deine Daten quer durch die ganze SPS verstreut liegen, dann solltest Du das Auslesen in einem Multiple Item Read zusammenfassen. Das beste ist aber, die Daten schon in der SPS "kommunikationsfreundlich" in einem DB zusammenzufassen.

Harald
 
Danke dass ihr euch die Zeit genommen habt zu antworten. Ja, ich lese dreimal mit ReadBytes. Jedes mal lese ich vier Byte und wandle mit GetFloat in eine REAL-Zahl. Das Ziel ist es, wie mit einem handelsueblichen Data-Logging-Programm, die Verbindung zur SPS herzustellen, eine Anzahl an Daten aus zu waehlen und diese dann mit einer akzeptablen durchschnittlichen Zykluszeit zwischen 40ms und 50 ms auszulesen. Es sollen, wenn moeglich, keine Aenderungen an der SPS durchgefuehrt werden muessen!

Ja, ich habe die FAQ und Doku gelesen und weiss, dass meine Anfangsvariante mit einzelnen ReadBytes-Befehlen, die zu Testzwecken ganz gut war, verbesserungswuerdig ist. Darum habe ich gestern auch mit dem Multiple Item Read begonnen. Ich habe mich an das VBA Beispielprogramm gehalten: die PDU erzeugt, das Resultset erzeugt, den Request vorbereitet, Variablen zum Request hinzu gefuegt (die gleich Werte wie bei meinen Readbyte-Befehlen, die funktionieren), aber beim ExecuteRequest-Befehl bekomme ich den Fehler 5. Wenn ich die Meldung umwandle, erhalte ich "the data address is beyond the CPUs address range." Irgendwo habe ich was falsch gemacht. Ich probiere es heute noch mal aus und poste meine Code.

Gruss aus Shanghai. Burkhard.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
Sub MyReadMultipleItemsFromPLC()
    Dim FloatResult1 As Single
    Dim FloatResult2 As Single
    Dim FloatResult3 As Single
    Dim ResultSet As Long
    Dim PDU As Long
    Dim Err As String
    
    'Establish Connection to PLC
    
    PortHandle = openSocket(102, "10.196.47.224")
    
    If PortHandle > 0 Then
        DeviceInterface = daveNewInterface(PortHandle, PortHandle, "IF1", 0, daveProtoISOTCP, daveSpeed187k)
        Result = daveInitAdapter(DeviceInterface)
       
        If Result = 0 Then
            DeviceConnection = daveNewConnection(DeviceInterface, 0, 0, 2)
            Result = daveConnectPLC(DeviceConnection)
            If Result = 0 Then
                MsgBox ("connectPLC successful")
            Else
                MsgBox ("connectPLC failed")
                End
            End If
        Else
            Call MsgBox("InitAdapter failed")
            End
        End If
    Else
        Call MsgBox("OpenSocket failed")
        End
    End If
    'Read Data as single requests from PLC

    Result = daveReadBytes(DeviceConnection, daveDB, 195, 80, 4, Empty)
    FloatResult1 = daveGetFloat(DeviceConnection)
        
    Result = daveReadBytes(DeviceConnection, daveDB, 199, 0, 4, Empty)
    FloatResult2 = daveGetFloat(DeviceConnection)
        
    Result = daveReadBytes(DeviceConnection, daveDB, 199, 4, 4, Empty)
    FloatResult3 = daveGetFloat(DeviceConnection)

    'Read Data as multiple item request from PLC
     PDU = daveNewPDU
     Call davePrepareReadRequest(DeviceConnection, PDU)
     Call daveAddVarToReadRequest(PDU, daveDB, 199, 0, 4)
     Call daveAddVarToReadRequest(PDU, daveDB, 199, 4, 4)
     Call daveAddVarToReadRequest(PDU, daveDB, 195, 80, 4)
       
    ResultSet = daveNewResultSet
    
    Result = daveExecReadRequest(DeviceConnection, PDU, ResultSet)
    
    If Result = 0 Then
        
        Result = daveUseResult(DeviceConnection, ResultSet, 0)
        FloatResult1 = daveGetFloat(DeviceConnection)
        
        Result = daveUseResult(DeviceConnection, ResultSet, 0)
        FloatResult2 = daveGetFloat(DeviceConnection)
        
        Result = daveUseResult(DeviceConnection, ResultSet, 0)
        FloatResult2 = daveGetFloat(DeviceConnection)
            
        daveFreeResults (ResultSet)
    Else
        Err = daveStrError(Result)
    End If
    
    daveFree (ResultSet)
    daveFree (PDU)
    Call CloseConnection
End Sub

Hier ist der mein Testcode. Ich bekomme bei ExecuteRequest, wie gesagt, den Fehler Nummer 5. Und weiss nicht was ich falsch mache... Bitte helft mir!!

Wenn ich statt daveDB, daveFlags verwende und die Merker MW0, MW2 und MW4 lese, dann bekomme ich keinen Fehler. Ich will aber keine Merker lesen, ich will Datenbausteine lesen.
 
Zuletzt bearbeitet:
Ja, natürlich, Wie du in meinem Test Code siehst, stelle ich ja die Verbindung zur SPS her, lese dann mit readbytes dreimal aus den DB 195 und 199. Ohne Fehler!
Dann will ich aus den gleichen DB lesen, aber mit dem multiple Read request. Beim execute gibt's die Fehlermeldung. Da ist offenbar ein derber Bug in libnodave!
 
Zuletzt bearbeitet:
Hab gerade noch einmal getestet, bei mir läufts einwandfrei.

Oben im Programm siehst du das normale Lesen mit ReadBytes, aus genau den gleichen DBs wo ich dann auch unten mit dem Multiple Read lese. Siehst du denn einen Fehler in meinem Code?

Nutzt du auch VBA in Excel? Liest du auch aus DBs? Kannst du mal deinen Code posten? Danke!
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
gibt es eine Anleitung im libnodave besser kennenzulernen?
ich wurde gerne über Autoit eine Libnodave Verbindung zu meiner SPS 315 PN aufbauen. Hierzu gibt es schon ein Projekt. Allerdings verstehe ich noch nicht den Aufbau?

Wenn jemand Lust hat könnte er mir mal diesen Code erklären?

Code:
#include "LibNoDave.au3"

Global $IP_SPS1 = "10.1.3.105", $Socket_SPS1, $di_SPS1, $dc_SPS1, $Name_SPS1 = "SPS1"

_DaveInit()

_daveTCPConnect($IP_SPS1, $Socket_SPS1, $di_SPS1, $dc_SPS1, 0, 2, $Name_SPS1)
If @error Then
    MsgBox(16, "Error " & @error, "TCP connection parameter incorrect for SPS1!")
    DllClose($DLL)
    Exit
EndIf

Local $Anzahl_Bytes = 7
Local $StartByte = 220
; Schreibe 7 Bytes ausgehend vom MB 230

$Buffer = DllStructCreate("CHAR buf[" & $Anzahl_Bytes & "]")
$pBuffer = DllStructGetPtr($Buffer)

_davePut8($pBuffer, 127)
_davePut16($pBuffer, 3)
_davePutFloat($pBuffer, 644321.55)

_daveWriteBytes($dc_SPS1, $daveFlags, 0, $StartByte, $Anzahl_Bytes, $Buffer)

_daveTCPDisconnect($Socket_SPS1, $di_SPS1, $dc_SPS1)
_DaveDeInit()
 
Wo liet genau das Problem?
Die LibNoDave-UDF wird initialisiert.
Es wird eine Netzwerk-Verbindung zur SPS mit der IP 10.1.3.105 auf Rack 0 und Slot 2 aufgebaut.
Es wird ein Speicherbereich von 7 Bytes vorbereitet.
Es wird die Zahl 127 in den Speicherbereich geschrieben (MB220).
Es wird die Integer-Zahl 3 in den Speicherbereich geschrieben (MW221).
Es wird die Float-Zahl 644321.55 in den Speicherbereich geschrieben (MD223).
Die sieben Bytes aus dem Speicherbereich werden auf die SPS geschrieben.
Die Netzwerkverbindung wird abgebaut.
Die LibNoDave-UDF wird deinitialisiert (nicht nötig, das geschieht automatisch).
 
Hallo danke erst mal für die antwort.

folgendes ist mir noch unklar ? für was sind die anderen Variablen ?

Golobale Variable , IP der SPS , ??? , ?? , ??? , ?????
Global $IP_SPS1 = "10.1.3.105", $Socket_SPS1, $di_SPS1, $dc_SPS1, $Name_SPS1 = "SPS1"



ISt dies die Verbinfungsart ? , IP der SPS, Slocket , di ??, , dc???? , 0 , 2, ??
daveTCPConnect ($IP_SPS1, $Socket_SPS1, $di_SPS1, $dc_SPS1, 0, 2, $Name_SPS1)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, funkey

wenn ich das oben genante Script auf meinen Rechner mit der IP meiner SPS 315 PN Starte wird kein Bit in den bereichen 220 - 223 gesetzt.
Was müsste doch funktionieren oder ?

Ich wurde mal in der einfachsten ausführung ohne Variablen den Befehl benötigen um eine Verbindung zu einer 315 PN über ISO over TCP zu erhalten ?

Code:
_daveTCPConnect(192.168.178, ????,????,?????, 0, 2, $Name_SPS1)
oder
_openS7online

mir wäre sehr geholfen wenn du mir mal den Verbindungsaufbau mit Zeiten und den Verbindungsaabau beschreiben könntest
 
Zuletzt bearbeitet:
Die ganzen Variablen werden von LibNoDave gebraucht. Das ist der einfachste Weg!

Code:
#include "LibNoDave.au3"Global $IP_SPS = "192.168.178"
Global $Socket_SPS ; Der Socket wird von _daveTCPConnect() beschrieben
Global $di_SPS ; Das Device Interface wird von _daveTCPConnect() beschrieben
Global $dc_SPS ; Die Device Connection wird von _daveTCPConnect() beschrieben
Global $Name_SPS = "SPS-Name" ; Name wird bei Logging und Debugging ausgegeben
Global $CPU_Rack = 0
Global $CPU_Slot = 2
_DaveInit()

_daveTCPConnect($IP_SPS, $Socket_SPS, $di_SPS, $dc_SPS, $CPU_Rack, $CPU_Slot, $Name_SPS)
If @error Then
 MsgBox(16, "Error " & @error, "TCP connection parameter incorrect for " & $Name_SPS & "!")
 Exit
Else
 MsgBox(64, "OK", "TCP connection established for " & $Name_SPS & "!")
EndIf
_daveTCPDisconnect($Socket_SPS, $di_SPS, $dc_SPS)
 
Hallo funkey
super TCP verbindung geht. Es kommt der Text "OK TCP connection established for ..."

Wenn ich jetzt das Schreiben der Variablen anhänge wird keine Variable gesetzt ? An was kann das leigen ?
Das Lesen von Variablen funktioniert. Nur das Senden noch nicht.
Mir ist noch unklar wie das Schreiben von Byts funktioniert ? für was ist
$Buffer = DllStructCreate("CHAR buf[" & $hLine & "]")
$pBuffer = DllStructGetPtr($Buffer)


Code:
      #include "LibNoDave.au3"
    Global $IP_SPS = "192.168.178.30"
    Global $Socket_SPS ; Der Socket wird von _daveTCPConnect() beschrieben
    Global $di_SPS ; Das Device Interface wird von _daveTCPConnect() beschrieben
    Global $dc_SPS ; Die Device Connection wird von _daveTCPConnect() beschrieben
    Global $Name_SPS = "SPS-Name" ; Name wird bei Logging und Debugging ausgegeben
    Global $CPU_Rack = 0
    Global $CPU_Slot = 2
    _DaveInit()

    _daveTCPConnect($IP_SPS, $Socket_SPS, $di_SPS, $dc_SPS, $CPU_Rack, $CPU_Slot, $Name_SPS)
    
    $hDB = 5
    $hOffset=4
    $hLine=4
    
    _daveReadManyBytes($dc_SPS, $daveDB, $hDB, $hOffset, $hLine)
    $Ausgabe=_daveGetFloat($dc_SPS)
    
    
    
    
     ; Schreibe 

    $Buffer = DllStructCreate("CHAR buf[" & $hLine & "]")
    $pBuffer = DllStructGetPtr($Buffer)


     _davePutFloat($pBuffer, 25.0)

      _daveWriteBytes($dc_SPS, $daveDB, $hDB, $hOffset, $hLine, $Buffer)
    
    
    If @error Then
     MsgBox(16, "Error " & @error, "TCP connection parameter incorrect for " & $Name_SPS & "!")
     Exit
    Else
     MsgBox(64, "OK", "TCP connection established for " & $Ausgabe & $Name_SPS & "!")
  EndIf
  
  
  Sleep(5000)
  
    _daveTCPDisconnect($Socket_SPS, $di_SPS, $dc_SPS)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
#include "LibNoDave.au3"
Global $Socket_SPS ; Der Socket wird von _daveTCPConnect() beschrieben
Global $di_SPS ; Das Device Interface wird von _daveTCPConnect() beschrieben
Global $dc_SPS ; Die Device Connection wird von _daveTCPConnect() beschrieben
Global $Name_SPS = "SPS-Name" ; Name wird bei Logging und Debugging ausgegeben
Global $IP_SPS = "192.168.178.30"
Global $CPU_Rack = 0
Global $CPU_Slot = 2
_DaveInit()
_daveTCPConnect($IP_SPS, $Socket_SPS, $di_SPS, $dc_SPS, $CPU_Rack, $CPU_Slot, $Name_SPS)
If @error Then
 MsgBox(16, "Error " & @error, "TCP connection parameter incorrect for " & $Name_SPS & "!")
 Exit
Else
 MsgBox(64, "OK", "TCP connection established for " & $Name_SPS & "!")
EndIf
Global $iDB = 5 ; Nummer des Datenbausteines
Global $iOffset = 4 ; Adress-Offset im Datenbaustein
Global $iBytes = 4 ; Anzahl der im Speicher vorzubereitenden Bytes
Global $Ausgabe
Global $iRet = _daveReadManyBytes($dc_SPS, $daveDB, $iDB, $iOffset, $iBytes)
If $iRet <> 0 Then
 MsgBox(16, "Error " & $iRet, "Cannot read " & $iBytes & " Bytes from DB " & $iDB & " at offset " & $iOffset & "!")
Else
 $Ausgabe = _daveGetFloat($dc_SPS)
 MsgBox(64, "Success", "You got value " & $Ausgabe & " from " & $Name_SPS)
EndIf
; Schreibe
Global $Buffer = DllStructCreate("CHAR buf[" & $iBytes & "]") ; Speicher vorbereiten auf den die bytes geschrieben werden
Global $fValue = 25.0
_davePutFloat($Buffer, $fValue)
$iRet = _daveWriteBytes($dc_SPS, $daveDB, $iDB, $iOffset, $iBytes, $Buffer)
If @error Or $iRet <> 0 Then
 MsgBox(16, "Error " & $iRet, "Cannot write " & $iBytes & " Bytes to DB " & $iDB & " at offset " & $iOffset & "!")
Else
 MsgBox(64, "Success", "You wrote " & $fValue & " to " & $Name_SPS)
EndIf
_daveTCPDisconnect($Socket_SPS, $di_SPS, $dc_SPS)
 
Hallo
super vielen Dank funktioniert.
Jetzt kann ich erst mal ein bisschen spielen damit.

Eine Frage noch
Wenn ich ein Programm habe da ständig Variablen sendet und empfängt muss ich dann die Verbindung jedes Mal öffnen und schließen? Oder mach ich eine schleife innerhalb der Verbindung?
 
Eine Frage noch
Wenn ich ein Programm habe da ständig Variablen sendet und empfängt muss ich dann die Verbindung jedes Mal öffnen und schließen? Oder mach ich eine schleife innerhalb der Verbindung?

Ich würde sagen das ist Geschmackssache, aber der Auf- und Abbau einer Verbindung dauert auch seine Zeit. Also wenn ich Daten z.B. alle 2 Sekunden aus der SPS hole, dann öffne ich nur am Anfang die Verbindung und schließe sie erst wenn ich das Programm beende. wenn ich aber nur alle 60 Sekunden Werte brauche, dann öffne und schließe ich die Verbindung jedes Mal.
 
Zuletzt bearbeitet:
Zurück
Oben