# Schnelle Datenübertragung mit DotNetSiemensPLCToolBoxLibrary (LibNoDave) Nummer 2



## Burkhard (24 September 2015)

Ich habe folgende vb.net Applikation erstellt um beliebige, frei konfigurierbare Datenpakete (INT, DWORD, STRING[255], FLOAT) von konfigurierbaren SPSen (IP-Adresse, Rack 0, Slot 2) zu lesen.

Die Log-Ergebnisse werden in Dateien im Ordner D:\MyDocuments geschrieben. Mir geht es dabei auch um Zeitmessungen.

Ich habe festgestellt, dass die Lese-Zeit stark von der Anzahl der zu lesenden Daten abhaengt. Hier mal eine Gegenueberstellung von zwei Faellen.

Station 1: Datenpaket GROSS

8x INT, 4x STRING, 4x DWORD, 4x REAL

Lesezeit von zu Hause: 170 ms
Lesezeit in der Firma: 100 ms





Station 2: Datenpaket KLEIN

8x INT, 4x DWORD, 4x REAL

Lesezeit von zu Hause aus: 30 ms
Lesezeit in der Firma: 15 ms





Es scheint, dass nicht die Netzwerkperformance oder die Netzwerkkarte des PC der Flaschenhals ist, sondern die SPS, da diese zur Zusammenstellung des Datenpaketes einfach mehr Zeit benoetigt.

Wie kann ich die Lesegeschwindigkeit bei Datenmengen um die 1000  Byte noch vergroessern?


----------



## Burkhard (24 September 2015)

Hier nochmal eine Gegenueberstellung der Zeitmessung von Station1 und Station2.


----------



## Hans54216 (25 September 2015)

Burkhard schrieb:


> Wie kann ich die Lesegeschwindigkeit bei Datenmengen um die 1000  Byte noch vergroessern?



Hallo Burkhard, 

wie du meinem Thema entnehmen kannst, liegt der Schlüssel in der Parallelen Anfrage bei der SPS. http://www.sps-forum.de/newreply.php?do=newreply&p=596888


```
Parallel.Invoke(Task1, Task2, Task3, Task4);
```

Wird die Datenmenge zu groß, werden mehrere PDUs nacheinander versendet. Um dies zu vermeiden, musst du die zu lesenden Pakete aufteilen auf die Größe eines PDU.

Anschließend erstellst du mehrere Verbindungen zur selben SPS und sendest die PDUs parallel los.

Damit solltest du auf die Lesezeit von 15/30 ms auch für die 1000 Byte kommen.


----------



## Burkhard (25 September 2015)

Ah, ok. Ich habe ja in meinem Programm bereits parallele Threads. Fuer jede SPS habe ich einen eigenen Thread. Pro Thread/SPS habe ich aber nur eine Verbindung. Eine PDU hat bei mir die Groesse 240 Byte. Das ist ziemlich wenig. Ein einziger String, was ja ein Byte-Array ist, passt da ja nicht mal komplett rein, wobei ich aber eigentlich gar nicht so grosse Strings brauche, wenn ich Seriennummern oder gescannte Barcodes einlese. 

Allerdings ein Array of Real oder Int ueberschreitet schnell die Groesse einer PDU. Ich denke es ist schwierig, aber es sollte irgendwie machbar sein, auch ein Array aufzuteilen und einzeln einzulesen. 

Ich werde den Ansatz gleich mal ueberpruefen! Danke erstmal, Hansi!


----------



## Burkhard (25 September 2015)

SPS1 (Thread/Verbindung1): 8 x INT, 4x DINT, 4x REAL

34 Millisekunden




SPS1 (Thread/Verbindung 2): 1x STRING[127]

34 Millisekunden




SPS1 (Thread/Verbindung 3) 1x STRING[127]

39 Millisekunden




SPS1 (Thread/Verbindung 4): 1x STRING[127]

27 Millisekunden




SPS1 (Thread/Verbindung 5): 1x STRING[127]

34 Millisekunden


----------



## Burkhard (25 September 2015)

SPS2 (Thread/Verbindung 6): 8x INT, 4x DINT, 4x REAL

15 Millisekunden




SPS 3 (Thread/Verbindung 7): 8x INT, 4x STRING[255], 4x DWORD, 4x REAL

90 Millisekunden




Hier nochmal die Logaufzeichnung aller Verbindungen:




Was auffaellig ist, dass die SPS 1 insgesamt 5 Threads/Verbindungen laufen hat und dadurch die Gesamtlesezeit von 30ms nicht die 15 Millisekunden von SPS2 erreicht, die nur eine Verbindung offen hat.


----------



## Hans54216 (25 September 2015)

Burkhard schrieb:


> Was auffaellig ist, dass die SPS 1 insgesamt 5 Threads/Verbindungen laufen hat und dadurch die Gesamtlesezeit von 30ms nicht die 15 Millisekunden von SPS2 erreicht, die nur eine Verbindung offen hat.



Welche Zeit erreichst du, wenn du an SPS1 nur ein PDU z.B. ein DWORD anforderst?

Selbst wenn du nicht die 15 ms erreichst, mit 30 ms hast du die Zeit mehr als gedrittelt (alt 100 ms).


----------



## Burkhard (26 September 2015)

Das stimmt, Hans. Ich habe nochmal eine andere Frage. Wen ich die Datenuebertragung mit der Toolbox-Library mit einem OPC-Server vergleiche, hinsichtlich des Funktionsprinzipes (PDU Size) und der Uebertragungs-Geschwindigkeit. Wie sieht das da aus, wenn ich mit einem OPC Server 1000 Byte von 14 SPSen lesen will?

Arbeitet der OPC-Server auch mit PDUs? 

Findet da auch Multi-Threading statt beim lesen der OPC-Tags? 

Und wie sieht es mit der Aktualisierungs-Zeit bei OPC-Tags aus (bei 14 SPSen a 1000 Byte)?

Liege ich da auch im Bereich von 30ms oder ist das eher 300ms?


----------



## Jochen Kühner (26 September 2015)

Der Opc arbeitet genau gleich, wobei er wahrscheinlich nicht mehrere Connections benutzt, Solltest du aber auch können, indem du mehrere Verbindungen einrichtest!


----------



## Burkhard (26 September 2015)

Hallo lieber Jochen,

nochmal vielen Dank fuer deine tolle Toolbox-Library. Sie funktioniert echt gut. Ich habe an meiner Anwendung weiter programmiert. Hast du schonmal Gelegenheit gehabt sie runterzuladen und auszuprobieren? 

Das tolle ist, dass man verschiedene SPSen mit ihren IP-Addressen parametrieren kann und dann pro SPS beliebige Variablenlisten mit copy/paste importieren kann. Es werden dann im Hintergrund so viele Verbindungen geoeffnet damit die Zykluszeit so niedrig wie moeglich ist.


----------



## Burkhard (26 September 2015)

*Schnelle Datenuebertragung von SPS zu IPC*

Anhang anzeigen S7Manager.zip


Hier ist die neuste Version meines S7 Managers. Ich habe die Anzeige-Liste mit einem double-buffer flicker-frei gemacht. Man braucht die Device-Liste nun nicht mehr missbrauchen um verschiedene Verbindungen zur gleichen SPS aufzubauen. Es reicht jede SPS einmal in die Device-Liste einzutragen. Pro SPS kann nun eine beliebig lange Signal-Liste mit INT, DWORD, REAL und STRING[127] konfiguriert werden. Die Anzahl von notwendigen Verbindungen zur gleichen SPS wird im Hintergrund gemanaged. Dabei werden Z*ykluszeiten von 15-20ms *erreicht, weil pro Verbindung immer nur eine PDU genutzt wird und jede Verbindung in einem separaten Thread bearbeitet wird.

Da jede SPS einen eigenen Thread hat und jeder dieser Threads wieder Sub-Threads war es gar nicht so einfach so ein ausgekluegeltes System zu programmieren, es hat mich den ganzen Tag gekostet, aber es hat sich gelohnt. Das Programm ist noch ein bisschen schneller geworden und vor allem die Usability ist nun echt top. Sehr gut gefaellt mir auch, dass man die Signal-Liste mit copy/paste bearbeiten kann. An dieser Funktion werde ich morgen noch arbeiten.

Weiterhin werde ich morgen, das speichern der Log-Dateie/en wieder einbauen, das fehlt in der aktuellen Version. Unter Optionen kann man dann den Ort waehlen, wo die Logdateien gespeichert werden sollen.


----------



## Thomas_v2.1 (26 September 2015)

Was macht denn das Programm? Irgendwie erschließt sich mir das nicht. Ich kann eine SPS anlegen und dann?

Du musst auch bedenken, dass eine S7 nur eine begrenzte Anzahl an Verbindungsressourcen hat, die nicht gerade hoch ist. Wenn du da so mit rumaast, sind die schnell aufgebraucht.


----------



## Burkhard (26 September 2015)

Thomas_v2.1 schrieb:


> Was macht denn das Programm? Irgendwie erschließt sich mir das nicht. Ich kann eine SPS anlegen und dann?
> 
> Du musst auch bedenken, dass eine S7 nur eine begrenzte Anzahl an Verbindungsressourcen hat, die nicht gerade hoch ist. Wenn du da so mit rumaast, sind die schnell aufgebraucht.




Hallo lieber Thomas,

hast du denn das Programm schon runtergeladen?

1. Du kannst mehrere SPSen anlegen
2. Pro SPS kannst du eine Variablentabelle anlegen, mit Adresse, Datentyp und Signal-Name.
3. Dann baust du die Verbindung auf und kannst die Werte beobachten.
4. Die Zykluszeit der Datenerfassung wird angezeigt und liegt dank der Verbindungsoptimierung bei 15-20ms. Das ist sehr schnell.
5. Die Werte werden in Log-Dateien geschrieben.


Hast du das Programm schon runtergeladen? Falls nicht, dann aber schnell jetzt... 

Wieviele Verbindungen darf denn eine Siemens S300 haben?? Kannst du mir das bitte mal sagen???


----------



## Thomas_v2.1 (26 September 2015)

Ja, hab die exe aus dem Release Verzeichnis gestartet, das war wohl eine andere Anwendung. Die aus dem Debug sieht anders aus.

Die Anzahl der Verbindungen sind je nach CPU unterschiedlich, steht im Datenblatt.


----------



## Burkhard (27 September 2015)

Hallo lieber Hansi, hallo bester Thomasius ! 

ich habe nun eine neue und traumhafte Version meines "S7 Manager Data Collector" erstellt. Durch das ausgekluegelte "Connection-Splitting" und "Multi-Threading" kann ich fuer das Lesen eines Datenblockes nur rund 20 Millisekunden zu Buche schlagen. Jeder Datenblock wird dabei in vier Verbindungen aufgesplittet, die in 4 Einzel-Threads laufen. Das Aufsplitten der Verbindungen geht automatisch, weil geschaut wird wieviele Variablen in eine PDU passen, die PDU Groesse ist mit 222 angesetzt. 

Dabei geltent die Grundsaetze:

1. JEDE SPS EIN THREAD

2. PACK SOVIELE VARS IN PDU WIE MOEGLICH

3. JEDE PDU EINE VERBINDUNG = EIN THREAD

Bei insgesamt 3 Test-SPSen habe ich also 3 Threads fue die SPSen zusammen und dann vier Threads fuer jede SPS macht zusammen 3x4 + 3 = 15 Threads. Ein Wahnsinn! Hahaha. 

*ROFL*










Hier nochmal die genauen Zykluszeit-Logging-Daten, wie man sieht schwankt die Zykluszeit zwischen 15 und 35 Millisekunden mit einem Mittelwert von etwa 25 Millisekunden.


----------



## Burkhard (28 September 2015)

Thomas_v2.1 schrieb:


> Du musst auch bedenken, dass eine S7 nur eine begrenzte Anzahl an Verbindungsressourcen hat, die nicht gerade hoch ist. Wenn du da so mit rumaast, sind die schnell aufgebraucht.



Ich kommuniziere in meinem Fall ueber die interne Profinet-Schnittstelle und nicht ueber ein CP343. Ich habe folgende Informationen gefunden, betreffend der maximalen Anzahl von parallelen Verbindungen. 

_*Communication via CP343-1
*One connection is occupied for each connected Modbus/TCP device.
 The maximum number of connections - and therefore the maximum number of Modbus/TCP devices that can be connected - is given in the technical data of the CP under "Performance data / Open communication". The number of possible connections for open communication or via SEND/RECEIVE blocks specifies how the maximum number of Modbus/TCP devices that can be connected to the CP343-1. 
There are no restrictions regarding the SEND/RECEIVE jobs that can be processed simultaneously. 
*Communication via CP443-1
*One connection is occupied for each connected Modbus/TCP device.
 The maximum number of connections - and therefore the maximum number of Modbus/TCP devices that can be connected - is given in the technical data of the CP under "Performance data / Open communication". The number of possible connections for open communication or via SEND/RECEIVE blocks specifies how the maximum number of Modbus/TCP devices that can be connected to the CP443-1. 
There are restrictions for the CPU regarding the SEND/RECEIVE jobs that can run simultaneously. A data transfer of a length of up to 240 bytes occupies 1 connection resource in the CPU. A data transfer longer than 240 bytes occupies 2 connection resources in the CPU. Taking into consideration the Modbus/TCP header this means that as of 115 registers or 1825 coils/inputs 2 connection resources are occupied in the CPU.
 The maximum number of function calls is given in the technical data of the CPU under "S5-compatible communication > Max. number of simultaneous AG-SEND/AG-RECV jobs per CPU".
 By cascading the triggered jobs you can connect as many devices as the CP can operate. They might be addressed consecutively if necessary. 
_
_*Communication via the PROFINET interface of the CPU* *SIMATIC S7 is Modbus/TCP client
*If the SIMATIC S7 is working as a Modbus/TCP client, then theoretically there is no limit to the number of Modbus/TCP devices that can be connected. A connection can be disconnected via the "DISCONNECT" input of the Modbus/TCP function block and then connected with a different device.
 The number of devices that can be operated at the same time is limited by the maximum number of connections. The maximum number of connections is given in the technical data of the CPU under "Open IE communication > Max. number of connections".
_
*In the Siemens Document "Open IE Communication: Data Exchange 
S7-300/400 <-> S7-1200" I found the following information:
*
_The maximum number of connections for open IE communication depends on the used CPU. For the used CPU 315-2 PN/DP, max. 8  imultaneous connections can be established using “ISO-on-TCP”. By changing the IP address in the connection data block, data can be successively exchanged with more than 8 different communication partners via the same connection resource. “ISO-on-TCP” allows to  tansfer up to 8,192 bytes per job._


----------



## Burkhard (28 September 2015)

Ich benutze allerdings folgende Kommunikationsbaugruppe:

IM 151-8 PN/DP CPU interface module 

Technical specifications 

Open IE communication supported:  Yes 
ISO on TCP (RFC1006)                 :  Yes (via integrated PROFINET interface and 
loadable FBs) 

Maximum number of connections  :  8 
 Data length, max.                        :  32768 bytes


----------



## Burkhard (28 September 2015)

Wenn ich mich mit dem Programmiergeraet auch ueber ISO on TCP verbinde, dann ist schonmal eine Verbindung weg, nehme ich an.

Wenn dann zum Datensammeln gerade 7 Verbindungen offen sind, dann sind nunmehr alle Verbindungen aufgebraucht. Ich denke damit kann ich leben.


----------



## PN/DP (28 September 2015)

Burkhard schrieb:


> Ich benutze allerdings folgende Kommunikationsbaugruppe:
> 
> IM 151-8 PN/DP CPU interface module


LibNoDave kommuniziert mit der CPU per PG-Kommunikation oder OP-Kommunikation.
Bei der IM 151-8 PN/DP CPU können maximal 12 solche Verbindungen genutzt werden. Falls die CPU weitere Kommunikation betreibt, dann sind weniger Verbindungen übrig.

Harald


----------



## Burkhard (28 September 2015)

Was denn nun? 12 oder 8 Verbindungen? In der Doku steht was von 8 Verbindungen, aber du sagst es sind 12.


----------



## Thomas_v2.1 (28 September 2015)

8 Offene IE-Verbindungen. 12 Verbindungen insgesamt, steht in der Tabelle weiter unten. Davon 11 für PG-Kommunikation verwendbar.


----------



## Jochen Kühner (28 September 2015)

Du musst auch noch aufpassen, das du nicht einfach 222 Bytes an nutzdaten in die PDU bekommst, jede Variablenanfrage braucht wieder zusätzliche 6 Bytes für den Request Header! Aber wie gesagt, diese ganze optimierung, sortierung und zusammenfassung ist in meiner Connection Klasse schon drin!


----------



## Burkhard (29 September 2015)

Jochen Kühner schrieb:


> Du musst auch noch aufpassen, das du nicht einfach 222 Bytes an nutzdaten in die PDU bekommst, jede Variablenanfrage braucht wieder zusätzliche 6 Bytes für den Request Header!



Danke für den Tipp, dann sind es ja pro PDU nur noch 216 Byte an Nutzdaten. 



Jochen Kühner schrieb:


> Aber wie gesagt, diese ganze optimierung, sortierung und zusammenfassung ist in meiner Connection Klasse schon drin!



Aber die nützt mir ja nur zum Teil etwas.

Ich habe ja pro SPS eine Variablenliste. Deine Lib optimiert diese nun, aber diese die ganze Liste wird ja über eine Verbindung gelesen, indem sie sie auf mehrere PDUs aufteilt wird, welche dann nacheinander gelesen werden. 

Das kostet Zeit!

Um Zeit zu sparen, will ich daher meine Liste aufteilen in Unterlisten von der Größe einer PDU. Dann will ich pro PDU eine Verbindung in einem separaten Thread nutzen will.

Deshalb muss ich diese Optimierung nun zum Teil nochmal selber durchmachen... Das ist ja die Crux an der Sache! 

Wenn du das parallele Lesen über mehrere Verbindungen und die Vor-optimierung noch in deine Lib einbauen würdest, wäre das natürlich eine Supersache. Die Lib müsste dann aber berücksichtigen, dass die Anzahl an Verbindungen begrenzt ist. Kann man die Anzahl an verfügbaren Verbindungen irgendwie abfragen, so dass man beim öffnen einer Verbindungen keinen Fehler bekommt, falls alle Verbindungen aufgebraucht sind?


----------



## Jochen Kühner (29 September 2015)

Wenn dann würde ich einbauen, das man sagt, ich will z.b. max 4 verbindungen nutzen! eine abfrage geht bestimmt über irgendeine szl, aber ich weis ja nicht ob vlt auch danach noch welche frei sein sollen z.b. für pg zugriff oder panels welche danach noch eingeschaltet werden!


----------



## Jochen Kühner (29 September 2015)

nein, es sind 222, da ist der erste header soweit ich weis schon abgezogen! aber jeder weitere bereich heist 6byte weniger! deshalb liest meine leseroutine beim abstand <6 auch den bereich dazwischen mit ein! und bei 400er cpus kannst du auch noch den short req nehmen, da sparst glaub ich nochmal 1 byte


----------



## Hans54216 (29 September 2015)

Jochen Kühner schrieb:


> Wenn dann würde ich einbauen, das man sagt, ich will z.b. max 4 verbindungen nutzen! eine abfrage geht bestimmt über irgendeine szl, aber ich weis ja nicht ob vlt auch danach noch welche frei sein sollen z.b. für pg zugriff oder panels welche danach noch eingeschaltet werden!



Es währe am schönsten, wenn dies direkt in deine Bibliothek eingebaut würde. Die Optimierung ist schon schön, und bringt auch einiges an Übertragungszeit. Will man jedoch größere Datenmengen lesen oder schreiben und noch eine akzeptable Übertragungszeit erreichen, kommt man an mehreren Verbindungen nicht vorbei.

Hab ja in dem älteren Thema einen Beitrag erstellt, wo ich mehrer Verbindungen und die Optimierung verglichen habe. In meinem Fall brachte die Optimierung so viel wie parallele Verbindungen, jedoch erst mit der Kombination beider Möglichkeiten, konnte die Übertragungszeit auf eine akzeptable Zeit verringert werden.


----------



## LowLevelMahn (29 September 2015)

Prüfst du deinen parallel Verbesserungen auch mit einer belasteten SPS?

die PUT/GET-Kommunikation wird relativ schnell nach unten gestuft wenn die SPS was zu tun hat und da werden deine Parallelanfragen auch mehr Belastung erzeugen


----------



## Hans54216 (29 September 2015)

Prüfe direkt am Prüfstand, wofür ich die Applikation auch geschrieben hab, sowie an einer arbeitenden CNC Fräsmaschine.


----------



## Rainer Hönle (29 September 2015)

Jochen Kühner schrieb:


> nein, es sind 222, da ist der erste header soweit ich weis schon abgezogen! aber jeder weitere bereich heist 6byte weniger! deshalb liest meine leseroutine beim abstand <6 auch den bereich dazwischen mit ein! und bei 400er cpus kannst du auch noch den short req nehmen, da sparst glaub ich nochmal 1 byte


Was meinst Du denn mit short req?


----------



## Jochen Kühner (29 September 2015)

Rainer Hönle schrieb:


> Was meinst Du denn mit short req?



https://github.com/dotnetprojects/D.../externalDlls/libnodave_patches/nodave.c#L585


----------

