LibNoDave-UDF zur Kommunikation mit Simatic SPS

  • Hallo.

    Mittels dieser UDF ist es möglich die LibNoDave.DLL zu verwenden, um damit eine Kommunikation zu einer SIMATIC SPS herzustellen, um Werte auszulesen oder zu schreiben.
    Mit dem beigefügten Demo-Skript können einfach die Kommunikationsparameter eingestellt werden, um die Verbindung zur SPS zu testen.

    http://libnodave.sourceforge.net/

    Viel Spaß beim Basteln eurer eigenen Visualisierung.

    Tip: Die RM-Chart-UDF von prog@ndy kann gut für eine Trendanzeige verwendet werden.


    Info: Die jeweils aktuellste UDF bekommt ihr auf Anfrage, da ich ständig versuche neue nützliche Funktionen hinzuzufügen.

  • Hi funkey !

    also bei mir kommuniziert da nix.

    Liegt aber wahrscheinlich daran, dass mein USB
    MPI Modul nicht in deiner Demo hinterlegt ist.
    Und / oder ich was falsch einstell.

    Es handelt sich um dem PC/ Adapter (MPI ) von Siemens ( 6ES7 972-0CB20-0XA0 )

    Adresse : 0
    Übertragungsgeschwindigkeit : 187,5kbit/s
    Timeout : 30s
    Anschluss : USB

    Laut deinem Connection Editor habe ich folgendes eingestellt :
    Name : Test
    Protokol : MPI-Protokol
    Description : AutoItSPS
    CPU-Rack : 1
    Slot : leer
    IP-Adresse : leer
    Timeout : 30s
    Intervall : 100
    Com-Port : ? ohne USB ?
    MPI-Speed 187.5 kBit/s
    MPI-Local: 0
    Remote : 1

    .
    .
    .

    so jetzt steh ich an der Wand. . . ;)

  • Du musst den COM-Port des USB-Adapters herausfinden, wenn dieser aber keinen virtuellen COM-Port hat, dann die s7onlinx.dll verwenden.

    Das Intervall würde ich zum testen nicht unter 1000 stellen. Remote-MPI-Adresse ist meistens 2. Rack sollte im Normalfall 0 sein, Slot bei einer S7-300 auf 2 stellen.
    Ich stelle gleich die neue UDF und Demo online.

    thx for testing

  • :thumbup: !! :thumbup:

    also Kommunikation ist da.

    Cycle Time wird mir angezeigt und der grüne Statusbar bewegt sich ...

    was das msec drunter soll, bin ich noch nicht dahinter gestiegen. :S

    Settings habe ich jetzt wie folgt angepasst :

    Protocol : S7onlinex.dll
    Com-Port : Com7 ( obwohl dieser nicht in meinem System angelegt ist ?!?! )
    Übertragungsrate Com : leer
    MPI-Speed 187 kBit/s
    Mpi-Local : 3
    Remote : 2
    Cpu-Rack 0
    Slot : 2

    ...
    ...

    jetzt geh ich mal dran irgend welche werte aus der SPS zu lesen .. und wenn das funktioniert, dass gehe ich an das hineinschreiben in die SPS. . .

    Hast du dir irgend ein Test *.k7p File gemacht ?

    nochmals danke für das geniale UDF !! Du hast's halt schon drauf :thumbup:

  • Hallo!
    Hab nun das Demo-Skript fertig gestellt. Außerdem sind nun weitere Funktionen in der LibNoDave-UDF von mir übersetzt worden.

    Viel Spaß beim Testen, für Fragen bin ich jederzeit hier erreichbar.


    vivus: Wenn du die S7onlinx.dll verwendest, dann hat der eingestellte COM-Port keinen Einfluss, das wird dann alles von den Siemens-Einstellungen geregelt. ;)

  • Hallo funkey,

    Vielen Dank für Deine Hilfe, das Auslesen funktioniert nun einwandfrei, allerdings ging es mit der Funktion _daveReadBits nicht, und ich musste die Schleife für die Bit-Auflösung auf "For $i=1 to 8" ändern... Noch kurz für alle (ich hatte meine Frage per PN gestellt):

    Meine Frage:

    Zitat

    Hallo funkey,

    ich möchte meine SPS (S7-1200) visualisieren und bin bei der Recherche auf deine UDF gestossen. Gute Arbeit!
    Ich kann bereits Verbindung aufnehmen und auch z.B. Ausgänge auslesen. Leider bekomme ich bei der Abfrage mit _daveReadBytes der Ausgänge z.B. von Byte 0 eigenartige Werte:
    Ausgang A0.0 an --> Wert 1, Ausgang A0.0 und A0.1 an --> Wert 3 ... soweit so gut. Aber:
    Ausgang A0.0 bis A0.7 an --> Wert -1 oder Ausgang A0.2 bis A0.7 an --> Wert -4, d.h. ich bekomme z.T. einen negativen Wert.
    Wie kann ich diese Werte nutzbar machen (eigentlich möchte ich ja jedes Bit - also jeden Ausgang - einzeln haben)?
    Kannst Du mir weiterhelfen?

    Antwort von funkey:


    So, und jetzt würde ich gern ein Byte schreiben (ein Merker-Byte), d.h. also M0.1 bis M0.7. Z.B. möchte ich den Merker M0.3 auf 1 setzen. Also muss ich doch das Byte M0 mit dem Wert "8" beschreiben?

    Ich habe schon einiges mit der Funktion _daveWriteBytes herumprobiert, aber irgendwie bekomme ich nichts in die CPU. Ich weiss nicht, wie ich der Funktion meinen Wert mitteile. Geht das über den Puffer und mittels DllStructSetData? Und in welchen Format muss ich der Funktion meinen Wert übergeben?

    Wäre super, wenn Du mir nochmals auf die Sprünge helfen könntest.

    Gruss, thommy75

  • Hallo thommy75!
    Ich habe die Funktionen zum schreiben auf die SPS noch nicht übersetzt, da ich sie bis jetzt noch nicht gebraucht habe. Das werde ich aber sobald als möglich nachholen und hier posten.

    Es fehlen noch die Funktionen:
    daveWriteBits
    daveWriteBytes
    davePut8
    davePut16
    davePut32
    davePutFloat
    davePutKG
    davePut8At
    davePut16At
    davePut32At
    davePutFloatAt
    davePutKGAt
    daveSetBit
    daveClrBit

    Einzelne Bits mit daveWriteBytes zu schreiben ist gefährlich, da auch die restlichen Bits des Bytes überschrieben werden!

  • Zu daveWriteBytes: Dann muss man eben erst ein daveReadBytes machen, darauf dir Bitmanipulationen anwenden und wieder schreiben richtig?

  • Hab mal ein Beispiel zum Schreiben von Bytes gemacht und hänge die neue LibNoDave-UDF an.
    Es hat sich einiges geändert seit der letzten Version im Post#1, daher funktioniert die dortige Demo nicht mehr mit der neuen UDF. Das wird bei Gelegenheit überarbeitet.

    Spoiler anzeigen
    [autoit]


    #include "LibNoDave.au3"

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    _DaveInit()

    [/autoit] [autoit][/autoit] [autoit]

    _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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

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

    [/autoit] [autoit][/autoit] [autoit]

    _daveTCPDisconnect($Socket_SPS1, $di_SPS1, $dc_SPS1)
    _DaveDeInit()

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • also mit deinem neuen Spoiler ( demo ) bekomme ich immer einen error von deiner UDF.

    [autoit]

    Func _daveReadBit(ByRef $dc, $iArea, $iDB, $iByte, $iBit)
    Local $Buffer = DLLStructCreate("BYTE buffer[1]")
    $aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart, "int", $iByte * 8 + 1, "ptr", DllStructGetPtr($Buffer, 'buffer'))
    Return DllStructGetData($Buffer, 1, 1)
    EndFunc

    [/autoit]
  • Bei mir komt es zu einer ganz änlichen Fehlermeldung:

    Code
    C:\Users\Admin\Desktop\LibNoDave.au3(547,112) : WARNING: $iStart: possibly used before declaration.
    	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart,
    	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
    C:\Users\Admin\Desktop\demo.au3(10,18) : WARNING: $DLL: possibly used before declaration.
        DllClose($DLL)
    ~~~~~~~~~~~~~~~~~^
    C:\Users\Admin\Desktop\LibNoDave.au3(547,112) : ERROR: $iStart: undeclared global variable.
    	$aRet = DllCall($hDLL_LibNoDave, "int", "daveReadBits", "ptr", $dc, "int", $iArea, "int", $iDB, "int", $iStart,
    	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
    C:\Users\Admin\Desktop\demo.au3 - 1 error(s), 2 warning(s)
  • ja das hast du ja geschrieben , dass deine alte demo nicht mehr funktioniert....

    aber ich habe deinen "neuen" spoiler genommen .. nicht die alte demo ..

    die variable ist nicht initialisiert ..

    kann es sein, dass du eine *.au3 vergessen hast bei zu legen ? in der alle nicht definierten variablen einen wert zugweisen bekommen ?

    ... mir fehlen folgende :

    $Socket_SPS1, $di_SPS1, $dc_SPS1

  • Hallo funkey.

    Erst mal vielen Dank für deine UDF und die Demo.
    Dadurch hatte ich sehr schnell einen Erfolg mit dem Auslesen von Maschinenparametern gehabt.
    Hat mir eine menge Zeit mit Testen und Ausprobieren erspart. :thumbup:

    Bei Testen ist mir dann noch folgendes aufgefallen:
    Wenn man mit libnodave versucht einen DB auszulesen den es auf der SPS nicht gibt, wird kein Array sondern nur ein Int? zurückgegeben.
    Jedenfalls steigt das Programm mit der Fehlermeldung aus, das die angegebene Variable kein Array ist.
    Ich habe in deiner UDF die Funktion "_daveReadBytes" (Ich nutze nur diese) um folgende Zeilen ergänzt:

    [autoit]

    If IsArray($aRet) Then
    Return $aRet[0]
    Else
    Return SetError(0)
    EndIf

    [/autoit]

    mfg Jörn

  • Hallo Jarmado!
    Es freut mich, dass du die UDF nutzen könntest. :thumbup:
    Ich habe leider nicht wirklich viel Error-Handling bei den Funktionen betrieben. Ich weiß aber auch immer welche DBs es auf der SPS gibt. Außerdem gibt es dazu die Funktion _daveListBlocksOfType().
    Die angehängte UDF ist auch bei weitem nicht mehr die aktuellste, aber wenn alles funktioniert, dann reicht das ja.

    Viel Spaß auch weiterhin damit!

  • Nein, aber ich muss mal suchen, wo ich die aktuellste Version im Einsatz habe. Ich hab da einen ziemlichen Wirrwarr, denn mit jedem neuen Projekt habe ich die UDF ein wenig angepasst.
    Und mittlerweile arbeite ich mit 4 verschiedenen Bibliotheken (DLLs) für die Kommunikation mit einer S7-SPS. (Und ich habe auch schon die Kommunikation direkt in AutoIt nachgebaut, zumindest TCP)