S7TCP.DLL - Einfachstes Auslesen von Daten aus der SPS

funkey

Level-2
Beiträge
355
Reaktionspunkte
105
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute.
Hab mir eine eigene Bibliothek zum Auslesen von Daten aus einer S7-300/S7-400 über das Netzwerk geschrieben.

Nun will ich sie euch mal kurz vorstellen. Es ist allerding noch eine Beta-Version, da ich noch einige Dinge verbessern will, und auch das Schreiben von Werten will ich noch implementieren.

Die DLL hat nur 3 exportierte Funktionen, diese sollten selbserklärend sein.
Code:
int S7Connect(LPCSTR IP, int SlotNo, S7Conn *conn);
void S7Disconnect(S7Conn *conn);
int S7Read(S7Conn *conn, LPCSTR syms[], int iCount, float result[]);

Der Funktion S7Read wird ein String-Array übergeben, das z.B. so aussehen kann:
Code:
LPCSTR sym[] = {"M0.1", "DB65.DBD0", "T21", "db65.dbx2.0", "z100", "MW20"};
Man kann die Werte also genauso eintragen wie sie z.B. in die Variabeltabelle eingetragen werden.
Alle Werte, egal ob Bit, Real, Timer oder Zähler, werden als 'float' zurückgegeben, da dies der einfachste Weg ist, und in 99% der Anwendungen reichen wird.

Angehängt ist ein kleines Code:Blocks-Projekt in C, das die Verwendung der DLL verdeutlicht.
Anhang anzeigen S7TCP Beispiel.rar

Schöne Grüße,
funkey
 
Ich habe die DLL mal ausprobiert,
bekomme als Anwort Error -4 oder Error -5


Hier ein Mitschnitt mit Wireshark:

Die Verbindung wird aufgebaut und die Daten werden angefordert.

Anhang anzeigen S7TCP_wireshark.zip

S7TCP.png


Das ist wohl, das Problem mit den sieben Bytes.
Hier ein Ausschnitt von libnodave:

Code:
#define ISOTCPminPacketLength 16
int DECL2 _daveGetResponseISO_TCP(daveConnection * dc) {
    int res;
    res=_daveReadISOPacket(dc->iface,dc->msgIn);
    if(res==7) {
    if (daveDebug & daveDebugByte) 
        LOG1("CPU sends funny 7 byte packets.\n");
    res=_daveReadISOPacket(dc->iface,dc->msgIn);
    }
    if (res==0) return daveResTimeout; 
    if (res<ISOTCPminPacketLength) return  daveResShortPacket; 
    return 0;
}
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist wohl, das Problem mit den sieben Bytes.

Wobei das eigentlich nicht "funny" ist, sondern ein gültiges Telegramm eines ISO Paketes. Die Länge im TPKT Header abzufragen ist im Grunde genommen der falsche Weg (funktioniert aber trotzdem). Richtig wäre es das Bit im Byte für "Last data unit" der TPDU Nummer abzufragen. Wireshark macht das auch, und darum werden diese Pakete auch als "reassembled" angezeigt.
Details siehe hier:
http://www.synapse.de/ban/HTML/P_ISO/Ger/P_iso87.html

Ich kenne dieses Verhalten nur von WinAC Soft-SPSen. Fragt sich nur warum Siemens das so reinprogrammiert hat, vielleicht sollen dadurch bestimmte Steuerungen erkannt werden, wer weiß. Ist zwar nicht falsch, aber überflüssig.

Aber ich will hier nicht zu viel unterstützen, denn wenn die erste fehlerhafte Version schon als eine beschränkte Demo-Version daher kommt...naja, da soll er mal lieber selbst seine Fehler suchen.
 
Danke für die Kommentare.
Das mit den 7 Bytes konnte ich auf meinen Test-SPSen nicht nachvollziehen, das könnte den Error -4 verursachen. Hab jetzt aber versucht, das so ähnlich wie in LibNoDave einzubauen. Ich kann es aber jetzt nicht online testen.
Error -5 kommt eigentlich wenn das Symbol nicht erkannt wird, welche Symbole hast du der Funktion übergeben?

Die Demo-Beschränkung habe ich herausgenommen, das war nur ein Test und ich habe es vergessen zu deaktivieren, es hat ja keinen Sinn einer unvollständigen, fehlerhaften DLL auch noch eine Demo-Funktion zuzumuten. ;) Allerdings habe ich jetzt noch keine Längenbeschränkung nach PDUSize implementiert, also Achtung beim Auslesen von vielen Werten.

Eigentlich wollte ich ja nur fragen, wie ihr mein Konzept findet. Es ist zwar noch nicht fertig, aber ich hoffe es gefällt euch so.
Soll ich als Rückgabe vielleicht double verwenden, damit die Genauigkeit bei hohen DINT Werten besser passt?
Außerdem will ich noch folgendes zum Symbol hinzufügen, z.B.:

MD8S: für signed DINT
DB65.DBD0F für Float (Real)
MW20U für unsigned Integer

Was haltet ihr davon? Wird es schon zu unkomfortabel?

Die nächste eventuelle Erweiterung wäre, folgende:

MD0F,10 für 10 Real-Werte ab MD0

Zu unübersichtlich oder nicht sinnvoll?

Danke für euren Support.

Anhang anzeigen S7TCP_V0.2.1.rar
 
Zuletzt bearbeitet:
Ich teste hier mit einer WinAC Soft-SPS und PLCSim mit NetToPLCSim.

Ich verwende MW100, MW102 und AW2.

Beide SPSen sind gleichzeitig über Netzwerk erreichbar, ich ändere also nur die IP-Adresse.
Bei der WinAC Soft-SPS erhalte ich nur noch Error -5 und mit NetToPLCSim funtioniert es immer.

Mit Libnodave funktioniert es mit beiden SPSen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die Kommentare.
Das mit den 7 Bytes konnte ich auf meinen Test-SPSen nicht nachvollziehen, das könnte den Error -4 verursachen. Hab jetzt aber versucht, das so ähnlich wie in LibNoDave einzubauen. Ich kann es aber jetzt nicht online testen.
Error -5 kommt eigentlich wenn das Symbol nicht erkannt wird, welche Symbole hast du der Funktion übergeben?

Die Demo-Beschränkung habe ich herausgenommen, das war nur ein Test und ich habe es vergessen zu deaktivieren, es hat ja keinen Sinn einer unvollständigen, fehlerhaften DLL auch noch eine Demo-Funktion zuzumuten. ;) Allerdings habe ich jetzt noch keine Längenbeschränkung nach PDUSize implementiert, also Achtung beim Auslesen von vielen Werten.

Eigentlich wollte ich ja nur fragen, wie ihr mein Konzept findet. Es ist zwar noch nicht fertig, aber ich hoffe es gefällt euch so.
Soll ich als Rückgabe vielleicht double verwenden, damit die Genauigkeit bei hohen DINT Werten besser passt?
Außerdem will ich noch folgendes zum Symbol hinzufügen, z.B.:

MD8S: für signed DINT
DB65.DBD0F für Float (Real)
MW20U für unsigned Integer

Was haltet ihr davon? Wird es schon zu unkomfortabel?

Die nächste eventuelle Erweiterung wäre, folgende:

MD0F,10 für 10 Real-Werte ab MD0

Zu unübersichtlich oder nicht sinnvoll?

Danke für euren Support.

Anhang anzeigen 16918


Also Ich hab das bei mir in der toolboxlib (http://siemensplctoolboxlib.codeplex.com/) so drinn:

DB8.DBD4,DWORD
P#DB7.DBX5.0 BYTE 10,STRING
MW4,BCDWORD
P#M0.0 BYTE 8,DATETIME

bei mir kann man als 3ten Parameter noch das Display Format angeben (wie in der Variablentabelle in step7).
Die verwende ich dann wenn man toString vom PLCTag aufruft!
 
Zurück
Oben