DotNetSiemensPLCToolBoxLibrary (LibNoDave) Zugriff auf Dual-Port RAM / FB15

Zuviel Werbung?
-> Hier kostenlos registrieren
Bei der SPS gibt es nämlich auch PI-Dienste. Aus dem SPS-Programm heraus lässt sich aber nur der für Stop und für Start aufrufen, darum fehlt mit da etwas der Vergleich.
Wie aus diesem Thread ersichtlich:
http://www.sps-forum.de/simatic/587...nd-den-pi-dienst-_n_f_pror-oder-nur-pror.html

ich bin mir nicht sicher was du mit PI Dienst meinst Start /Stop ist mir so mal unbekannt


Das sind PI Dienste die man aus der PLC nutzen kann
es gibt da noch weiter die sind aber nicht dokumentiert


PI-Dienst
ASUP (Seite 921) Interrupt zuordnen
CANCEL (Seite 921) Cancel durchführen
CONFIG (Seite 922) Umkonfiguration von gekennzeichneten Maschinendaten
DIGION (Seite 922) Digitalisieren ein
DIGIOF (Seite 922) Digitalisieren aus
FINDBL (Seite 923) Suchlauf aktivieren
LOGIN (Seite 923) Kennwort aktivieren
LOGOUT (Seite 924) Kennwort rücksetzen
NCRES (Seite 924) NC-RESET auslösen
SELECT (Seite 924) Programm zur Abarbeitung für einen Kanal anwählen
SETUDT (Seite 925) Setzt die aktuellen User Daten aktiv
SETUFR (Seite 925) Anwender Frame aktivieren
RETRAC (Seite 926) Freifahren des Werkzeugs in Werkzeugrichtung
CRCEDN (Seite 926) Werkzeugschneide anlegen unter Eingabe der T-Nummer
CREACE (Seite 927) Werkzeugschneide anlegen mit der nächst höheren/freien D-Nummer
CREATO (Seite 927) Anlegen eines Werkzeuges unter Vorgabe einer T-Nummer
DELECE (Seite 92 Löschen einer Werkzeugschneide
DELETO (Seite 92 Werkzeug löschen
MMCSEM (Seite 929) Semaphoren für verschiedene PI-Dienste
TMCRTO (Seite 930) Anlegen eines Werkzeugs unter Angabe eines Namens, einer Duplonummer
TMFDPL (Seite 931) Leerplatzsuche zum Beladen
TMFPBP (Seite 932) Leerplatzsuche
TMGETT (Seite 933) T-Nummer zum vorgegebenen Werkzeugnamen mit Duplonummer
TMMVTL (Seite 934) Magazinplatz zum Beladen bereitstellen, Werkzeug entladen
TMPOSM (Seite 935) Magazinplatz oder Werkzeug positionieren
TMPCIT (Seite 936) Inkrementwert für Stückzahlzähler setzen
TMRASS (Seite 937) Rücksetzen des Aktiv-Status
TRESMO (Seite 937) Rücksetzen der Überwachungswerte
TSEARC (Seite 93 Komplexes Suchen über Suchmasken
TMCRMT (Seite 941) Multitool erzeugen
TMDLMT (Seite 941) Multitool löschen
POSMT (Seite 942) Multitool positionieren
FDPLMT (Seite 943) Leerplatz innerhalb des Multitools suchen/prüfen
 
Vielleicht kannst du noch von anderen PI-Dienstaufrufen mit diversen Parametern Mitschnitte machen, um hoffentlich damit herausfinden zu können wie die Argumente codiert werden. Dann lässt sich hoffentlich eine universelle Funktion schreiben, die einen PI-Dienstaufruf auf dem Netzwerk abschickt.

Hab gerade Urlaub. Ab Montag versuch ich mal so viele als Möglich mitzuschneiden.


Komm aber grad nicht wirklich dazu da was zu machen! Helfen kann iCH DIR NATÜRLICH GERNE (SOFERN ES MIR MÖGLICH IST)

Hast du schon mal nen PI-Dienstaufruf (z.B. Start / Stop) mit der libnodave durchgeführt?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich weiß nicht genau ob das überhaupt einem PI-Dienstaufruf entspricht. Ein Warm- oder Kaltstartbefehl der bei einer SPS ausgeführt wird, ist vom Aufbau zumindest identisch (oder sehr ähnlich) zu den von dir gezeigten NC-Telegrammen. Was wohl PI-Dienstaufrufe sind, wenn ich das richtig verstehe.

Bei einer SPS kann ich aus dem SPS-Programm heraus, z.B. einen Kalt- oder Warmstart an einer anderen CPU ausführen. Der entsprechende Baustein hat dafür Parameter, bei einem Kaltstart wird 'C' als Zeichen übergeben. Das sieht dann so aus wie ein paar der hier gezeigten NC-Aufrufe. Ein Start-Befehl an einer SPS sieht anders aus, der hat überhaupt keine weiteren Parameter. Das erste Byte im Parameter-Teil (was ich Function genannt habe) unterscheidet sich auch bei Start und Stopp.
Bei libnodave werden zum SPS starten und stoppen nur 1:1 die Bytes die reingeschoben, funktioniert auch ohne dass man versteht was da überhaupt passiert.

Ich kenne mich mit dem NC-Zeugs überhaupt nicht aus, außer dass ich da mal in die ein oder andere Betriebsanleitung einen Blick geworfen habe. Wenn du da Logfiles erstellst, solltest du darum schon mitdokumentieren was du da überhaupt gemacht hast. Was auch interessant ist, sind Antworten auf fehlerhafte Anfragen oder so etwas in der Richtung. Dann sieht man evtl. auch mal die Bedeutung von Feldern die vorher z.B. immer Null waren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist schonmal aufschlussreich. Ich habe auch noch eine Beschreibung diverser PI-Dienste in dem Sinumerik-Addon für WinCC flexible gefunden, u.a. sind dort auch die Parameter für PI-Dienste der SPS beschrieben, aber die Beispiele fehlen mir dabei. Oder gibt es noch eine bessere Beschreibung in einem anderen Handbuch?

So wie es aussieht, hat auf dem Netzwerk die Funktion 0x28 (die ich z.Zt in Wireshark als "PLC Control" anzeige) allgemein die Funktion PI_START. Dann kommt als erstes die Länge und der Parameter, und dann Länge und Name des PI-Dienstes der aufgerufen wird. Wie die Parameter zu interpretieren sind, ist dann abhängig von dem verwendeten PI-Dienst.

Wo und wie wird denn überhaupt diese Funktion PI_START(..) aufgerufen? Macht man das in einem Skript, und wenn ja, in welcher Programmiersprache?
Um ein Äquivalent für libnodave zu schreiben, müsste man dazu eine varargs Funktion erstellen, da Anzahl und Datentyp der Argumente ja nicht festgelegt ist. Ich weiß aber nicht ob sich varargs dann auch in .Net verwenden lassen. Die Alternative wäre dann, für jeden PI-Dienst eine eigene Funktion zu erstellen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ist die Frage inwiefern das mit dem was übers Netzwerk geht korreliert.
Beispiel LOGIN:
Code:
    LOGIN : STRUCT
     PIName : STRING [10]  := '_N_LOGIN_';
     p01 : BYTE  := 16#3;    //Bereich / Einheit
     p02 : CHAR  := 0;
     p11 : BYTE  := 16#8;    //Passwort
     p12 : BYTE  := 16#19;    //String Kennung !!!
    END_STRUCT ;
Übers Netzwerk:
Code:
0x28: Funktion PI_START
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd: Unbekannt
0x0e: Länge des Parameterblocks gesamt = 14
{ // Parameterblock
  0x03: Länge Argument 1 
  0x30, 0x30, 0x31: ASCII-String "001" -> (Bereich/Einheit)?
  0x09: Länge Argument 2 (Passwort) = 9 Zeichen
  0x5f, 0x4e, 0x5f, 0x4c, 0x4f, 0x47, 0x49, 0x4e, 0x5f: Passwort als ASCII-String
}

Steht das "001" dort für (Bereich/Einheit)?
 
Dein letzter Anhang funktioniert nicht.

In der WinCC flexible Sinumerik Doku steht zu dem Feld immer:
"3-digit Addressidentification from RangeID and Index"
Dieser Parameter ist bei allen PI-Diensten mit _N_xxxx im Namen immer vorhanden.
Kann ich das von der Bezeichnung her so stehen lassen? Dann muss ich nicht für jeden Dienst eine eigene Bezeichnung verwenden.

Die Struktur der PI-Dienste habe ich denke ich mal soweit.
Der Parameterblock muss immer auf eine gerade Anzahl an Bytes aufgefüllt werden.

Das letzte 0xfd in den bisher unbekannten 7 Bytes zu Beginn könnte auch die maximale Stringlänge bedeuten (253). Dann sind die Strings sozusagen als S7-Strings mit Kopf zu verstehen, aber die Max-Länge wird nur einmalig übermittelt. Ich habe dort aber noch nie einen anderen Wert als 0xfd gesehen.

Bei deinem Logfile von "NC_File_Open" gibt es laut Doku noch einen Parameter "Editor Window Name". Was hast du dort eingetragen, oder ist dieser Parameter optional?
Denn im Logfile ist die Längenangabe 0x00, dann folgt obwohl die Stringlänge Null ist noch ein Null-Byte für den String, und dann noch ein Nullbyte um auf eine gerade Anzahl an Bytes im Parameterblock zu kommen. Das muss eine libnodave Funktion dann später ebenfalls berücksichtigen, wie das handzuhaben ist.

In Wireshark bastel ich mir daraus jetzt einen Pseudo-Funktionsaufruf, z.B.:
Code:
_N_F_OPEN(P01, _N_MPF_DIR/_N_TEILEPROG2_MPF, )
bzw. eigentlich mit Anführungszeichen:
Code:
_N_F_OPEN("P01", "_N_MPF_DIR/_N_TEILEPROG2_MPF", "")

So in der Art könnte man dann auch die Funktionen gestalten.

Ist das für den NC-Bereich sinnvoll?

nc_file_open.jpg
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Der Parameterblock muss immer auf eine gerade Anzahl an Bytes aufgefüllt werden.

Korrektur:
Jeder String muss inklusive des Längenbytes eine gerade Anzahl besitzen, und wird ggf. mit einem Füllbyte aufgefüllt.
Dann passt das auch zusammen, wenn die Längenangabe Null ist.
 
Dein letzter Anhang funktioniert nicht.
PI-LOGIN.pngPI-LOGIN2.png


Bei deinem Logfile von "NC_File_Open" gibt es laut Doku noch einen Parameter "Editor Window Name". Was hast du dort eingetragen, oder ist dieser Parameter optional?
Denn im Logfile ist die Längenangabe 0x00, dann folgt obwohl die Stringlänge Null ist noch ein Null-Byte für den String, und dann noch ein Nullbyte um auf eine gerade Anzahl an Bytes im Parameterblock zu kommen. Das muss eine libnodave Funktion dann später ebenfalls berücksichtigen, wie das handzuhaben ist.

In diesem wireshark ist der Editor Name ein Leerstring.
Wenn du den wireshark aus meinem Paket nimmst (Ordner "File open change close\NC_File_Open.pcapng"), da ist der Editor Name "txt1".
 
Zuletzt bearbeitet:
Ich habe mal eine Testfunktion für die PI-Dienste geschrieben. Zumindest für die PI-Dienste der NC (also die mit _N_ beginnen) sollte das funktionieren. Denn bei den NC PI-Diensten sind alle Parameter identisch kodiert, d.h. immer als String mit Längenangabe vorweg. Zumindest ist das bei allen so, deren Dokumentation ich gefunden habe.

Die Funktion ist nur hingeschrieben und absolut ungetestet!
Code:
int DECL2 davePIstart_nc(daveConnection *dc, const char *piservice, const char *param[], int paramCount) {
    int res;
    int i;
    PDU p, p2;
    int paramlen;
    int len;
    int pos;
    uc pa[1024]; 

#ifdef DEBUG_CALLS
    LOG2("davePIstart_nc(dc:%p)\n", dc);
    FLUSH;
#endif
    /* Header */
    pa[0] = 0x28;   /* Function code for PI-Start*/
    pa[1] = 0x00;   /* unknown */
    pa[2] = 0x00;
    pa[3] = 0x00;
    pa[4] = 0x00;
    pa[5] = 0x00;
    pa[6] = 0x00;
    pa[7] = 0xfd;   /* max. string length */
    pa[8] = 0x00;   /* Parameterblock length */
    pa[9] = 0x00;   /* Parameterblock length */

    /* Parameterblock */
    pos = 10;                               /* start of Parameterblock */
    paramlen = 0;
    for (i = 0; i < paramCount; i++) {
        len = strlen(param[i]);
        pa[pos++] = len;                    /* 1 Byte stringlength */
        memcpy(&pa[pos], param[i], len);    /* the string */
        pos += len;
        if (len % 2 == 0) {                 /* stringlength + length header must be even */
            pa[pos++] = '\0';               /* fillbyte */
            paramlen += 1 + len + 1;
        } else {
            paramlen += 1 + len;
        }
    }
    /* set parameter block length */
    pa[8] = paramlen / 256;
    pa[9] = paramlen % 256;

    /* add servicename */
    len = strlen(piservice);
    pa[pos++] = len;
    memcpy(&pa[pos], piservice, len);
    pos += len;

    /* length of complete parameter part */
    len = 10 + paramlen + 1 + strlen(piservice);

    p.header=dc->msgOut+dc->PDUstartO;
    _daveInitPDUheader(&p, 1);
    _daveAddParam(&p, pa, len);

    ((PDUHeader2*)p.header)->plenHi = p.plen / 256;
    ((PDUHeader2*)p.header)->plenLo = p.plen % 256;

    res =_daveExchange(dc, &p);
    if (res == daveResOK) {
        res =_daveSetupReceivedPDU(dc, &p2);
        if (daveDebug & daveDebugPDU) {
            _daveDumpPDU(&p2);
        }
    }
    return res;
}
libnodave typisch wird nichts überprüft, d.h. wer in die Funktion falsche Parameter eingibt, der muss mit einem Absturz rechnen.
Einzelne Strings dürfen nicht länger als 253 sein. Laut Dokumentation der PI-Dienste dürfen die meisten nur wesentlich kürzer sein.

Aufrufen der Funktion dann mit:
Code:
const char *pistart_parameter[] = {
    "P01",
    "_N_MPF_DIR/_N_TEILEPROG2_MPF",
    ""
};

res = davePIstart_nc(dc, "_N_F_OPEN", pistart_parameter, 3);
Das könnte man ja so als Low-Level Schnittstelle in der Bibliothek stehen lassen. Ein String-Array als Parameter sollte sich auch relativ einfach in .Net verwenden lassen, zumindest einfacher als eine variadische Funktion.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für den Code!!!

Hab gerade die ersten PI-Service per libnodave verschickt.

Hast du eine Beschreibung zu den File Diensten? "_N_F_OPEN", "_N_F_CLOSE" ...

Wie weit bist du mit der Implementierung in WireShark?
 
Die Beschreibungen zu den PI-Diensten habe ich aus der Hilfedatei für das WinCCflexible Sinumerik Addon, das jemand hier https://support.industry.siemens.co...meters-information/106222/?page=0&pageSize=10 angehängt hat.
Dort sind die beiden von dir genannten enthalten, und diverse andere auch. So wie es aussieht gibt es wohl auch Codebeispiele, die aber in der Hilfedatei nicht vorhanden sind. Da müsste man schon jemanden fragen, der dieses Addon wirklich gekauft hat ob der einen da mal einen Blick reinwerfen lässt.
Meiner Meinung nach ist zumindest für einen PI-Dienst ein Fehler in der Beschreibung (_N_DZERO), weil die Dienstnamen immer eine ungerade Länge haben. Ich habe dann mal angenommen, das verlängert sich zu _N_DZERO_.

Ich habe alles soweit in Wireshark drin. Aber ich mache das ja nicht mehr mit einer separaten plugin-dll, sondern das wird dann direkt in Wireshark eingepflegt. Darum sollte das dann auch möglichst zu 100% (oder zumindest 99%) passen. Dann muss der Patch bei Wireshark noch durch den Codereview-Prozess, und das kann dauern. Außerdem muss ich durch die neu gewonnenen Informationen auch ein paar andere Dinge die zur SPS-Programmierung gehören korrigieren/verbessern.
Ich könnte dir höchstens ein komplettes Verzeichnis mit allen Wireshark Dateien zur Verfügung stellen, das ist dann aber schätze ich mal 100 MByte groß.
 
Hab das neue Wireshark ein bisschen ausprobiert. Soweit sieht´s gut aus.

Beim "NC_File_Upload", auch im Paket enthalten wird ja zunächst der PI-Dienst "_N_F_XFER" gestartet. Dieser funktioniert auch soweit.
Anschließend folgen "Start upload", "Upload", "End upload".

Der Funktionskode ist ja wie in libnodave.
Code:
#define daveFuncStartUpload        0x1D
#define daveFuncUpload             0x1E
#define daveFuncEndUpload          0x1F

Jedoch passen die Funktionen nicht zur NC. Wireshark zeigt die Funktionen teilweise falsch an. (liegt wohl an dem Unterschied zur SPS)


Kannst du mir ne angepasste Funktion für "Start upload", "Upload", "End upload" schreiben?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich bin auch eigentlich mit der Namensgebung für Download und Upload nicht ganz glücklich. Wenn ich im Internet eine Datei von einem Webserver herunterlade, ist das ein Download. So wie das in Wireshark angezeigt und auch in libnodave verwendet wird, wäre das Übertragen von Bausteinen vom PG in die SPS ein Download. Ich weiß aber nicht ob ich das nochmal ändere.

Beim jetzigen "Upload" eines Bausteins aus einer SPS, wird der Dateistring bei StartUpload zerlegt, sodass ich direkt sehen kann welcher Baustein (Typ und Nummer) übertragen wird. Leider kann ich das auf dem Netzwerk nicht anhand irgendeiner Kennung unterscheiden, ob das eine Bausteinbezeichnung für die SPS, oder ein NC-Dateiname ist. Bei einer SPS ist der ganze Dateiname aber immer 9 Zeichen lang.
Ist dieser bei der NC fix 17 Zeichen, oder zumindest immer länger als 9? Dann könnte ich pauschal sagen, wenn 9 Zeichen lang, dann als SPS Bausteinadresse zerlegen, und sonst nur den Dateinamen anzeigen.

Die jetzigen Upload Funktionen sollten sich noch relativ einfach anpassen lassen, kann ich bei Gelegenheit mal angehen. Ich weiß aber noch nicht wann ich dazu komme, eher am Wochenende.
 
Und noch eine Bezeichnungsfrage: NC, NCU, NCK
Welches Kürzel ist an welcher Stelle zu verwenden?
NC - Numerical Control
NCU - Numerical Control Unit
NCK - Numerical Control Kernel

Mit welchem von den dreien kommunizierst du, wenn du eine Datei überträgst, einen PI-Service aufrufst, oder eine Variable liest?
 
Ich bin auch eigentlich mit der Namensgebung für Download und Upload nicht ganz glücklich. Wenn ich im Internet eine Datei von einem Webserver herunterlade, ist das ein Download. So wie das in Wireshark angezeigt und auch in libnodave verwendet wird, wäre das Übertragen von Bausteinen vom PG in die SPS ein Download. Ich weiß aber nicht ob ich das nochmal ändere.

Beim jetzigen "Upload" eines Bausteins aus einer SPS, wird der Dateistring bei StartUpload zerlegt, sodass ich direkt sehen kann welcher Baustein (Typ und Nummer) übertragen wird. Leider kann ich das auf dem Netzwerk nicht anhand irgendeiner Kennung unterscheiden, ob das eine Bausteinbezeichnung für die SPS, oder ein NC-Dateiname ist. Bei einer SPS ist der ganze Dateiname aber immer 9 Zeichen lang.
Ist dieser bei der NC fix 17 Zeichen, oder zumindest immer länger als 9? Dann könnte ich pauschal sagen, wenn 9 Zeichen lang, dann als SPS Bausteinadresse zerlegen, und sonst nur den Dateinamen anzeigen.

In der "doUploadNC" und "endUploadNC" ist pa[4]=1, bei den SPS Funktionen war dieser 0. Weiß jedoch nicht was dieser aussagt.
uc pa[]= {0x1f,0,0,0,1,0,0,1};


Die jetzigen Upload Funktionen sollten sich noch relativ einfach anpassen lassen, kann ich bei Gelegenheit mal angehen. Ich weiß aber noch nicht wann ich dazu komme, eher am Wochenende.

Hab die jetzigen Upload Funktionen soweit angepasst, dass ich nen Erfolgreichen Upload durchführen konnte.
 
Zurück
Oben