Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Seite 16 von 31 ErsteErste ... 6141516171826 ... LetzteLetzte
Ergebnis 151 bis 160 von 304

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

  1. #151
    Hans54216 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    06.04.2013
    Beiträge
    208
    Danke
    10
    Erhielt 5 Danke für 5 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Zitat Zitat von Thomas_v2.1 Beitrag anzeigen
    Den Zeitstempel zeigt zumindest auch der Windows Explorer.

    Das kann ich in die Funktion noch mit einbauen. Woher soll der Zeitstempel kommen, als Parameter, oder aktuelle Zeit verwenden?.
    Am schönsten ist es, wenn der Zeitstempel der Funktion als Parameter übergeben wird. Dann hat die Datei in der NC den selben Zeitstempel wie das Original.

  2. #152
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Jetzt kannst du den Pfad und den Zeitstempel als Parameter übergeben. Der Zeitstempel wird als Zeiger auf eine struct tm (aus time.h) übergeben. In C ist das Standard, aber du willst es ja in .Net benutzen. Alternativ könnte man den Zeitstempel auch als String übergeben, dann muss der Anwender aber wissen wie das Format auszusehen hat.
    Code:
    int DECL2 
    davePutNCProgram(daveConnection *dc, char *filename, char *pathname, struct tm *ts, char *buffer, int length)
    {
        PDU p, p2;
        int res = 0;
        int size = 0;
        uc unackcount = 0;
        uc seq_num = 0;
        uc dataunitref = 0;
        int max_data_len = 0;
        int filename_len = 0;
        int prefix_len = 0;
        int buffer_pos = 0;
        int tot_len = 0;
    
        /* Request download */
        uc req_down_pa[]= {
            0x00, 0x01, 0x12, 0x04, 0x11, 0x7f, 0x01, 0x00
        };
        uc req_down_da[]= {
            0xff, 0x09, 0x00, 32,
            /* Dateiname max. 32 Zeichen */
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00
        };
    
        /* Download block */
        uc do_down_pa[]= {
            0x00, 0x01, 0x12, 0x08, 0x12, 0x3f, 0x02,
            0x00,       /* sequence number */
            0x00,       /* data unit reference */
            0x01,       /* Last data unit: 0=yes, 1=no */
            0x00, 0x00  /* errorcode */
        };
        /* 1920 ist die von libnodave vorgeschlagene max. PDU-Größe */
        uc do_down_da[1920 + 6]= {
            0xff, 0x09,
            0x00, 0x00, /* block size in bytes */
            0x00, 0xfb,
        };
    
        /* End download */
        uc end_down_pa[]= {
            0x00, 0x01, 0x12, 0x04, 0x11, 0x7f, 0x04,
            0x00       /* sequence number */
        };
        uc end_down_da[]= { 
            0xff, 0x09, 0x00, 0x02, 0x00, 0x00
        };
    
        filename_len = strlen(filename);    /* max. 32 chars */
        if (filename_len > 32) {
            return -1;
        }
        req_down_da[3] = filename_len;
        memcpy(&req_down_da[4], filename, filename_len);
    
        p.header = dc->msgOut + dc->PDUstartO;
        _daveInitPDUheader(&p, 7);
        _daveAddParam(&p, req_down_pa, sizeof(req_down_pa));
        _daveAddData(&p, req_down_da, 4 + filename_len);
    
        res = _daveExchange(dc, &p);
        if (res == daveResOK) {
            res = _daveSetupReceivedPDU(dc, &p2);
            if (daveGetDebug() & daveDebugPDU) {
                _daveDumpPDU(&p2);
            }
            /* Errorcode im Parameterteil prüfen */
            res = daveGetU16from(&p2.param[10]);
            if (res == 0) {
                seq_num = p2.param[9];      /* Diesen Wert für alle folgenden Downloadtelegramme verwenden */
                unackcount = p2.data[4];    /* Anzahl an Paketen die gesendet werden dürfen, ohne auf ein Ack zu warten */
                do_down_pa[7] = seq_num;
                /* Max. Länge in datablock = PDUsize - hlen - plen - dheader */
                max_data_len = daveGetMaxPDULen(dc) - 10 - 12 - 6;
                do_down_da[6] = '/0';
                sprintf(do_down_da + 6, "%08d%02d%02d%02d%02d%02d%02d    ;$PATH=%s\n", 
                    length + strlen(pathname) + 8, /* ;$PATH= + \n */
                    ts->tm_year % 100, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec,
                    pathname);
                prefix_len = strlen(do_down_da + 6);
                tot_len = prefix_len + length;
                /* Daten senden bis unackcount = 0, dann auf Antwort warten, usw. usf. */
                while (tot_len) {
                    do_down_pa[8] = ++dataunitref;
                    p.header = dc->msgOut + dc->PDUstartO;
                    _daveInitPDUheader(&p, 7);
                    if (tot_len > max_data_len) {
                        size = max_data_len;
                        do_down_pa[9] = 1;  // Last data unit: 1=no
                    } else {
                        size = tot_len;
                        do_down_pa[9] = 0;	// Last data unit: 0=yes
                    }
                    memcpy(do_down_da + 6 + prefix_len, buffer + buffer_pos, size - prefix_len);
                    tot_len -= size;
                    buffer_pos += size - prefix_len;
                    prefix_len = 0;
                    do_down_da[2] = (size+2) / 256;
                    do_down_da[3] = (size+2) % 256;
    
                    _daveAddParam(&p, do_down_pa, sizeof(do_down_pa));
                    _daveAddData(&p, do_down_da, size + 6);
                    if (daveGetDebug() & daveDebugPDU) {
                        _daveDumpPDU(&p);
                    }
                    if (--unackcount > 0) {
                        /* PDU senden ohne auf Antwort zu warten */
                        res = _daveSendTCP(dc, &p);
                        if (res != daveResOK) {
                            break;
                        }
                    } else {
                        /* PDU senden mit Warten auf Antwort von NC */
                        LOG2("davePutNCProgram: unackcount=%d, warte auf Antwort von NC um fortzusetzen...\n", unackcount);
                        res = _daveExchange(dc, &p);
                        if (res == daveResOK) {
                            res = _daveSetupReceivedPDU(dc, &p2);
                            if (daveGetDebug() & daveDebugPDU) {
                                _daveDumpPDU(&p2);
                            }
                            /* Hier weiß ich nicht wie ein Fehler auszuwerten ist, da weder im
                             * Kopf- noch im Parameterteil ein Errorcode vorhanden ist.
                             * Bei Erfolg sollte der Datenteil 6 Bytes groß sein, und unackcount > 0
                             */
    
                            /*              push-nc                   continue */
                            if ((p2.param[5] == 0x3f && p2.param[6] == 0x03) &&
                               ((PDUHeader*)p2.header)->dlen == 6) {
                                unackcount = p2.data[4];    /* Anzahl an Paketen die gesendet werden dürfen, ohne auf ein Ack zu warten */
                                if (unackcount == 0) {
                                    LOG2("davePutNCProgram: in continue response unackcount=%d. Exit!\n", unackcount);
                                    res = daveResUnexpectedFunc;
                                    break;
                                }
                            } else {
                                LOG2("davePutNCProgram: in continue response, falscher Aufbau der Antwort (p2.param[5] = %d). Exit!\n", p2.param[5]);
                                res = daveResUnexpectedFunc;
                                break;
                            }
                        } else {
                            break;
                        }
                    }
                };
    
                if (res == daveResOK) {
                    /* End-download senden */
                    end_down_pa[7] = seq_num;
                    p.header = dc->msgOut + dc->PDUstartO;
                    _daveInitPDUheader(&p, 7);
                    _daveAddParam(&p, end_down_pa, sizeof(end_down_pa));
                    _daveAddData(&p, end_down_da, sizeof(end_down_da));
                    res = _daveExchange(dc, &p);
                    /* Antwort auswerten */
                    if (res == daveResOK) {
                        res = _daveSetupReceivedPDU(dc, &p2);
                        if (daveGetDebug() & daveDebugPDU) {
                            _daveDumpPDU(&p2);
                        }
                        if (p2.param[5] == 0xbf && p2.param[6] == 0x05) {
                            /* Errorcode im Parameterteil prüfen */
                            res = daveGetU16from(&p2.param[10]);
                        } else {
                            res = daveResUnexpectedFunc;
                        }
                    }
                }
            } else {
                LOG2("davePutNCProgram: errorcode erster Antwort: %04X\n", res);
            }
        }
        return res;
    }
    Wahrscheinlich musst du in der nodave.h noch die time.h includieren.
    Die Genialität einer Konstruktion liegt in ihrer Einfachheit – Kompliziert bauen kann jeder.

    (Sergei Pawlowitsch Koroljow, sowjetischer Konstrukteur von Raketen und Weltraumpionier)

  3. #153
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.745
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    Was benutzt denn "daveSetPLCTime" für ein Format? Vlt. sollte man das gleich halten?

    @Thomas
    Ich schau morgen mal nach den von dir angesprochen Punkten
    ---------------------------------------------
    Jochen Kühner
    https://github.com/jogibear9988/DotN...ToolBoxLibrary - Bibliothek zur Kommunikation mit PLCs und zum öffnen von Step 5/7 Projekten

  4. #154
    Hans54216 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    06.04.2013
    Beiträge
    208
    Danke
    10
    Erhielt 5 Danke für 5 Beiträge

    Standard

    Ich hab zum Testen die Funktion so umgebaut, das das Datum als String übergeben wird. (dt.ToString("yyMMddHHmmss"))
    Scheint aber nicht zu funktionieren. (Wireshark im Anhang)
    Kopfzeile wird an den Schluss geschrieben.
    filename und Datum fehlt -> woher weiß sprintf bei ("%s", Pointer) die länge des Strings?


    Code:
    int DECL2 davePutNCProgram(daveConnection *dc, char *filename, char *pathname, uc *ts, char *buffer, int length)
    ...
    //sprintf(do_down_da + 6, "%08d%02d%02d%02d%02d%02d%02d    ;$PATH=%s\n", 
    //    length + strlen(pathname) + 8, /* ;$PATH= + \n */
    //    ts->tm_year % 100, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec,
    //    pathname);
    
    sprintf(do_down_da + 6, "%08d%s    ;$PATH=%s\n", length + strlen(pathname) + 8, ts, pathname);
    ...
    dave_NC_File_Download1.rar

  5. #155
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    In C sind Strings Nullterminiert. D.h. solange ab der Adresse auf die Pointer zeigt ein Zeichen ungleich '\0' vorhanden ist, werden die Zeichen in den String vom ersten Parameter von sprintf kopiert.

    Wenn ich die Funktion so wie von dir beschrieben umbaue, dann funktioniert das wenn ich diese in C mit z.B.
    Code:
    res = davePutNCProgram2(dc, "_N_TEILEPROG3_MPF", "_N_MPF_DIR", "160422175457", buffer, 512);
    aufrufe.

    Ich habe das jetzt einfach mal so getestet, indem ich die Telegramme an eine SPS sende, aber die Abfragen ob der Austausch erfolgreich war "überbrückt" habe. Darum kann ich sehen was zumindest theoretisch rausgeht.

    Bei deiner Aufzeichnung ist auch seltsam, dass bei dir zweimal hintereinander ein Request-Download angefordert wird. Bei mir ist das nicht der Fall. In der Funktion davePutNCProgram() wird das auf jeden Fall nicht so gemacht.

    Kannst du das nicht erstmal direkt aus einem C-Programm testen? Dann ist die zusätzliche Fehlerquelle durch die ganze .Net Schnittstelle schonmal eliminiert. Wahrscheinlich fertigt C# da irgendeinen UTF kodierten String an.


    daveSetPLCTime() nimmt auch ein char array an, die dann auch direkt 1:1 so übertragen werden. Damit man diese Funktion überhaupt verwenden kann, muss man aber wissen wie der Zeitstempel aufgebaut ist der übertragen wird. Also ich weiß das nicht aus dem Kopf und müsste das auch erst nachsehen wie ich das in Wireshark programmiert habe. Im S7-Protokoll gibt es mindestens 2 unterschiedliche Zeitstempel-Formate.
    Die Genialität einer Konstruktion liegt in ihrer Einfachheit – Kompliziert bauen kann jeder.

    (Sergei Pawlowitsch Koroljow, sowjetischer Konstrukteur von Raketen und Weltraumpionier)

  6. #156
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    @Hans54216

    Korrigiere mal diese Zeile bei mir, d.h. von [9] auf [7]
    Code:
    seq_num = p2.param[7];      /* Diesen Wert für alle folgenden Downloadtelegramme verwenden */
    Vielleicht funktioniert dann zumindest der Download einer kleinen Datei. Denn für alle Telegramme wird die Sequenznummer aus der ersten Antwort von der NC verwendet, zumindest war das in den von dir gezeigten Aufzeichnungen so.
    Die Genialität einer Konstruktion liegt in ihrer Einfachheit – Kompliziert bauen kann jeder.

    (Sergei Pawlowitsch Koroljow, sowjetischer Konstrukteur von Raketen und Weltraumpionier)

  7. #157
    Hans54216 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    06.04.2013
    Beiträge
    208
    Danke
    10
    Erhielt 5 Danke für 5 Beiträge

    Standard

    Hab den Fehler von gestern gefunden. Problem war, das ich übersah dass du zusätzlich zum "filename" nun auch nen String für den "pathname" übergibst.

    Mit der Änderung von gestern Abend kommt von der NC kein Fehler zurück.
    Es fehlt jedoch der Befehl sowie die Quittierung "Download ended".

    Wireshark im Anhang:
    Kurzes Programm "Teileprog3" wird von der NC hochgeladen und anschließend als "Teileprog4" mit selbem Inhalt zur NC hinunter geladen.

    dave_NC_File_Download2.pcapng -> vor der Änderung von gestern Abend
    dave_NC_File_Download3.pcapng -> inc. letzter Änderung
    extern_NC_File_Download2.pcapng -> Erfolgreicher up- und download

    dave_NC_File_Download2.rar

  8. #158
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.745
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    Zitat Zitat von Thomas_v2.1 Beitrag anzeigen
    Diese Zeilen finde ich fragwürdig:
    6251:
    Code:
    memcpy(progBlock+4,buffer,maxPBlockLen);
    und 6297:
    Code:
    memcpy(progBlock+4,buffer+(cnt*maxPBlockLen),maxPBlockLen);
    Wenn der Buffer nicht ein Vielfaches von maxPBlockLen, wird aus ganz anderem Speicher gelesen. Der wird zwar nicht verschickt, aber das ist trotzdem nicht statthaft.
    Und length als Zeiger übergeben, obwohl das überhaupt nicht notwendig ist.
    Sollte gefixt sein: https://github.com/dotnetprojects/Do...146a7184f46202
    ---------------------------------------------
    Jochen Kühner
    https://github.com/jogibear9988/DotN...ToolBoxLibrary - Bibliothek zur Kommunikation mit PLCs und zum öffnen von Step 5/7 Projekten

  9. #159
    Registriert seit
    29.03.2004
    Beiträge
    5.735
    Danke
    143
    Erhielt 1.685 Danke für 1.225 Beiträge

    Standard

    Zitat Zitat von Hans54216 Beitrag anzeigen
    Hab den Fehler von gestern gefunden. Problem war, das ich übersah dass du zusätzlich zum "filename" nun auch nen String für den "pathname" übergibst.

    Mit der Änderung von gestern Abend kommt von der NC kein Fehler zurück.
    Es fehlt jedoch der Befehl sowie die Quittierung "Download ended".
    Hm, probiere mal folgende Änderung:
    Code:
    if (--unackcount > 0 || do_down_pa[9] == 0) {
        /* PDU senden ohne auf Antwort zu warten */
        res = _daveSendTCP(dc, &p);
        if (res != daveResOK || do_down_pa[9] == 0) {
            break;
        }
    Dann sollte, wenn die zuletzt gesendete PDU die letzte war, nicht mehr auf eine Antwort gewartet werden, sondern direkt der Download abgeschlossen werden.

    Wenn das funktioniert, könntest du mal schrittweise das Programm vergrößern, damit es über mehrere PDUs übertragen werden muss. Wird sich zeigen ob es dann auch noch funktioniert.
    Die Genialität einer Konstruktion liegt in ihrer Einfachheit – Kompliziert bauen kann jeder.

    (Sergei Pawlowitsch Koroljow, sowjetischer Konstrukteur von Raketen und Weltraumpionier)

  10. #160
    Hans54216 ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    06.04.2013
    Beiträge
    208
    Danke
    10
    Erhielt 5 Danke für 5 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Wenn ich das so anpasse siehts in Wireshark genau so aus.
    Funktion bleibt aber in einer Dauerschleife, anstelle dass sie einen Fehler zurück meldet.


    Wie kann ich den Code im Studio ausführen, damit ich ihn Debuggen kann?
    Brauch ja zunächst die "daveConnection" zur NCU, um deine Funktion aufzurufen.

Ähnliche Themen

  1. Zugriff auf WinAC RTX mit LibnoDave
    Von rm2001 im Forum Hochsprachen - OPC
    Antworten: 2
    Letzter Beitrag: 27.04.2012, 20:31
  2. Libnodave & VB.NET Zugriff auf geschützte Speicherbereiche
    Von KJ1234 im Forum Hochsprachen - OPC
    Antworten: 1
    Letzter Beitrag: 10.11.2007, 16:02
  3. Zugriff mit libnodave (unter Delphi) auf S7-CP443-1
    Von Frank im Forum Hochsprachen - OPC
    Antworten: 19
    Letzter Beitrag: 29.04.2007, 13:59
  4. Zugriff auf Siemens S7 per libnodave (MPI)
    Von Anonymous im Forum Hochsprachen - OPC
    Antworten: 15
    Letzter Beitrag: 02.11.2005, 17:09
  5. Fehler bei Zugriff auf COM- Port
    Von h_matthias im Forum Simatic
    Antworten: 16
    Letzter Beitrag: 08.03.2004, 22:14

Stichworte

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •