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

Seite 1 von 4 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 36

Thema: libnodave: Verbindung PC mit CPU 300/400

  1. #1
    Registriert seit
    02.04.2012
    Beiträge
    23
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo erstmal,
    ich bin neu hier und kenne mich noch nicht so gut aus in diesem Forum

    Ich sitze gerade an meiner Bachelorarbeit und habe folgendes Problem:

    Also meine Aufgabenstellung:
    1. Mein Aufgabe ist es einen Kommunikation zwischen einem PG bzw. PC und einer CPU 300/400 über TCP/IP aufzubauen.
    2. Ziel soll es dann sein den DB1 auszulesen und die Werte in eine Datei abzuspeichern abzuspeichern.
    3. Das Programm soll weiterhin dynamisch bleiben. (Variable Größe des zulesenden DB1 und es soll möglich sein CPU 300 oder 400 zu benutzen)
    4. Programm wird mit C/C++ geschrieben (Eclipse 3.5.1)

    Ich bin bisher nur soweit gekommen, dass ich mir die Header-Dateien von libnodave nodave.h und openSocket.h angeguckt habe.
    Ich habe festgestellt, dass das (für mich zumindest ) ein ziemliches Durcheinander ist.
    Welche Funktionen davon brauche ich überhaupt für mein Programm? (arbeite mit XP)
    Wenn ich das richtig verstanden habe muss ich mir eine eigene main() schreiben oder?
    Habe mir auch schon die test_iso_tcp.c angeschaut.Aber aus der werde ich nicht so richtig schlau

    Ich würde gerne folgendermaßen vorgehen:
    1. Verbindung mit CPU herstellen (über IP- oder MAC-Adresse)
    2. DB1 auslesen (REAL, INT, BOOL)
    3. Ergebnis in Datei speichern (z.B. einfache .txt )

    Welche Dateien muss ich von libnodave in mein Projekt einbinden?
    Reichen die beiden Header (nodave.h und openSocket.h)?
    Welche Funktionen brauche ich davon?

    Ich hoffe ich habe mein Problem gut beschrieben und ich würde mich über eure Hilfe sehr freuen. Danke schonmal im vorraus

    Gruß Derick
    Geändert von Derick87 (05.04.2012 um 11:07 Uhr)
    Zitieren Zitieren Experten gefragt: unbekannten DB auslesen  

  2. #2
    Derick87 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    02.04.2012
    Beiträge
    23
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Bin jetzt schon ein Stückchen weiter
    Habe mir jetzt ein Projekt mit Eclipse erstellt.
    Habe die drei Header-Dateien log2.h, opensocket.h und nodave.h eingebunden und mir eine main.c mit Funktionen aus der testISO_TCP.c erstellt.
    Wenn ich jetzt auf Build All klicke erscheinen sehr viele Fehlermeldungen.
    Zum Beispiel:
    C:\Bachelorarbeit\cpp_Programme\TCP_IP_libnodave\Debug/../main.c:27: undefined reference to `daveListBlocksOfType@12'

    Das heißt ja das er die Funktion nicht finden kann oder??
    Was habe ich falsch gemacht

    Gruß Derick

  3. #3
    Registriert seit
    24.03.2011
    Beiträge
    7
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hallo Derick!

    Ich arbeite selbst für meine Diplomarbeit mit der Bibliothek Libnodave, allerdings unter C#!
    Ich hoffe aber trotzdem , dass ich dir in einer gewissen Art und Weise helfen kann!

    Ich binde bei meinem Projekt die libnodave.dll ein und programmiere den Verbindungsaufbau und die durchzuführenden Aktionen in einer eigenen Klasse!

    Dabei gehe ich nach folgendem Prinzip vor:

    Verbindungsaufbau zur CPU -> Lesen bzw Schreiben von Daten -> Trennen der Verbindung

    Für den Anfang würd ich dir raten, dass du das gettingstarted.html File genauer anguckst.

    Um überhaupt richtig damit Arbeiten zu können benötigst du mal folgende Klassen:
    • _daveOSSerialType
    • _daveConnection
    • _daveInterface
    Die findest du alle in der "libnodave.dll", die du normalerweise doch einbinden kannst ? (Hab nie wirklich C++ programmiert, deshalb frag ich)

    daveInterface
    Benötigst du unbedingt, die Übergabeparameter sind
    • Name des Interfaces
    • daveOSSerialType
    • MPI-Adresse (Null, da du ja über TCP verbindest)
    • die Protokollart (ISOTCP)
    • die Übertragungsgeschwindigkeit (die aber eigentlich keine wirkliche Rolle spielt)
    daveConnection
    • MPI-Adresse (wieder Null)
    • daveInterface
    • Rack-Nummer (normalerweise null)
    • Slot-Nummer (Achtung hier aufpassen, gewöhnlich bekommen 300er CPUs RACK-Nummer 2!, bei 1200ern ist es allerdings Null!)
    um eine Verbindung aufzubauen gehst du wie folgt vor:
    • öffnen eines Sockets mit openSocket (Parameter sind PORT und IP-Adresse des CPs)
    • danach musst du ein Interface erstellen mit daveInterface
    • danach musst du eine Connection erstellen mit daveConnection
    • danach öffnest du deine Verbindung mit connectPLC
    Verwende immer eine Result Variable, die die Rückgabewerte der Funktionen auswertet
    Rückgabewert 0 einer libnodave Funktion bedeutet erfolgreich!
    Alles andere ungleich Null ist eine Fehlermeldung (diese kannst du aus nodave.h entnehmen + Bedeutung)

    Und dann gehts eben ums Lesen bzw Schreiben

    Variablen lesen kannst du mit readBytes, einzelne Bits mit readBits
    Und schreiben eben mit writeBytes und writeBits

    als Übergabeparameter benötigen diese Lese/Schreibefunktionen in der Regel
    • die Area-Art (handelt es sich um einen DB, ein MW, ein In/Output?) in deinem Fall libnodave.daveDB
    • die Nummer des DBs
    • Die Startadresse
    • die Länge in Byte
    • einen Buffer
    Anfangs hatte ich ziemlich viele Probleme mit dem Buffer! Beim Lesen kannst du selber einen byte buffer erstellen, indem die gelesenen Daten gespeichert werden
    Beim Schreiben musste ich auf vieles aufpassen!
    Da die Byte-Order der SPS anders ist, musste ich zuerst den zu schreibenden Wert in der Byte-Order umdrehen und dann mit BitConverter.GetBytes verwenden (weiß ehrlich gesagt nicht ob es sowas ähnliches in C++ gibt!


    Der Einstieg mit Libnodave ist sehr sehr schwierig, ich hatte selber arg große Probleme, vor allem durch viele Fehlermeldungen!
    Aber lass es nicht hängen, wenn einmal alles funktioniert, dann ist es großartig und die Kommunikation funktioniert perfekt!

    Ich arbeite mit einer 1214CPU, hab Libnodave aber auch bei 300ern angewendet und das ohne Probleme!

    Wie gesagt, ich kann dir bei C++ nicht wirklich so auf die Sprünge helfen, bei C schon eher aber ich hoffe ich konnte dir jetzt ein bisschen weiterhelfen mit Libnodave

    Wenn du möchtest kann ich dir einen Ausschnitt schicken aus meiner File, aber ich weiß nicht wie gut du mit C# umgehen kannst!

    Grüße

    steggo.

  4. #4
    Derick87 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    02.04.2012
    Beiträge
    23
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Danke steggo für die Antwort.

    Bin jetzt auch mittlerweile etwas weiter gekommen.
    Ein paar Fragen hab ich allerdings noch und hoffe du kannst mir helfen?!

    1. Die Länge des DB1 (den ich auslesen will) ist unbekannt. Brauche also ne Methode die mir die Länge des DB1 zurückgibt. Hab hierzu die Methode daveGetBlockInfo() gefunden. Was muss ich ihm beim zweiten Parameter (daveBlockInfo *dbi) übergeben?

    2. Nachdem ich den DB1 ausgelesen habe möchte ich diese Daten abspeichern. Das heißt einen neuen DB erzeugen mit den gleichen Daten wie DB1

    3. Ein Verständnisproblem noch: Mein DB1 besitzt unterschiedliche Datentypen (BOOL, WORD, DWORD etc.). Wenn ich jetzt die Methode daveReadManyBytes() benutze habe ich doch nur die einzelnen bytes oder??

    4. Wie muss ich denn den buffer bei daveReadBytes initialisieren?

    Gruß Eric
    Geändert von Derick87 (04.04.2012 um 15:41 Uhr)

  5. #5
    Registriert seit
    24.03.2011
    Beiträge
    7
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    zu 1)
    soweit ich bis jetzt herausgefunden habe ist daveBlockInfo eine Struktur in Libnodave, guck mal ob du irgendwo eine Struktur findest, die so heißt
    hier ein kleiner Ausschnitt aus der noDave.h

    typedef struct {
    uc type[2];
    uc x1[2]; /* 00 4A */
    uc w1[2]; /* some word var? */
    char pp[2]; /* allways 'pp' */
    uc x2[4]; /* 00 4A */
    unsigned short number; /* the block's number */
    uc x3[26]; /* ? */
    unsigned short length; /* the block's length */
    uc x4[16];
    uc name[8];
    uc x5[12];
    } daveBlockInfo;

    Die Methode wird einen Pointer auf diese Struktur erwarten, nehme ich mal an
    Ansonsten kannst du noch nachschauen ob du eine Funktion namens "getProgrammBlock" findest!

    zu 2)
    Ich bin mir nicht sicher ob du mit Libnodave einen DB erzeugen kannst?!
    Eigentlich dient es zur Kommunikation und zum Datenaustausch, ich denke den DB müsstest du in STEP7 erzeugen?
    Musst du die Daten in einem DB speichern?
    Oder könntest du auch eine File nehmen?

    zu 3)
    du könntest in diesem Fall auch readMultipleItems verwenden

    PDU p;
    daveResultSet rs;
    davePrepareReadRequest(dc, &p);
    daveAddVarToReadRequest(&p,daveInputs,0,0,1);
    daveAddVarToReadRequest(&p,daveFlags,0,0,4);
    daveAddVarToReadRequest(&p,daveDB,6,20,2);
    daveAddVarToReadRequest(&p,daveFlags,0,12,2);
    res=daveExecReadRequest(dc, &p, &rs);

    hier kannst du mit 1 Anfrage auf mehrere Bereiche zugreifen
    Auch auf mehrere Datenbereiche des DBs

    neben daveAddVar gibt es auch noch daveAddBit etc

    Musst du mal versuchen, ich selber habe nie einen ganzen DB ausgelesen, sondern nur gewisse Bereiche, die für meine Anlage wichtig sind

    Aber mal angenommen du hast in deinem DB zwei INT-Werte und einen BOOL-Wert
    daveAddVarToReadRequest(&p,daveDB,1,0,2);
    daveAddVarToReadRequest(&p,daveDB,1,2,2);

    Bitadressierung ist wie folgt --> Bsp: 43.1 -> 43*8 + 1 = Bitadresse

    Nachdem du die Variablen hinzugefügt hast, musst du execReadRequest(dc, PDU, resultSet) ausführen
    Mit useResult kannst du dann die Resultate ausgeben

    Beispiel:

    Result = useResult(dc, resultSet, 0) // 1. Ergebnis

    if (Result == 0)
    {
    Output = getU16(dc) // oder getU32, oder getS32, je nachdem
    }
    useResult(dc, resultSet, 1) // 2. Ergebnis


    Bei DWORD mußt du dann als Länge eben 4 Byte angeben und getU32 verwenden!


    zu 4)
    Ich habe einfach einen Byte-Buffer erstellt mit einer Größe von zB 4Byte
    und diesen Buffer übergeb ich dann bei der Funktion readBytes

    und Ausgeben tu ich das ganze dann wieder mit getU16 oder getU32 auf eine dementsprechende Variable

    Grüße
    steggo.

  6. #6
    Registriert seit
    17.06.2004
    Ort
    Offenau
    Beiträge
    3.759
    Danke
    209
    Erhielt 421 Danke für 338 Beiträge

    Standard

    Zitat Zitat von steggo. Beitrag anzeigen
    Der Einstieg mit Libnodave ist sehr sehr schwierig, ich hatte selber arg große Probleme, vor allem durch viele Fehlermeldungen!
    Aber lass es nicht hängen, wenn einmal alles funktioniert, dann ist es großartig und die Kommunikation funktioniert perfekt!

    Ich arbeite mit einer 1214CPU, hab Libnodave aber auch bei 300ern angewendet und das ohne Probleme!

    Wie gesagt, ich kann dir bei C++ nicht wirklich so auf die Sprünge helfen, bei C schon eher aber ich hoffe ich konnte dir jetzt ein bisschen weiterhelfen mit Libnodave

    Wenn du möchtest kann ich dir einen Ausschnitt schicken aus meiner File, aber ich weiß nicht wie gut du mit C# umgehen kannst!

    Grüße

    steggo.
    @steggo:

    Wenn du C# nutzt und libnodave als zu kompliziert findest, kann Ich dir noch meine Wrapper Library (http://siemensplctoolboxlib.codeplex.com/) (kapselt libnodave) oder S7Net (http://s7net.codeplex.com/) empfehlen
    ---------------------------------------------
    Jochen Kühner
    https://github.com/jogibear9988/DotN...ToolBoxLibrary - Bibliothek zur Kommunikation mit PLCs und zum öffnen von Step 5/7 Projekten

  7. #7
    Derick87 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    02.04.2012
    Beiträge
    23
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    danke schonmal für die schnelle Antwort

    ja ich habe auch schon einen Pointer erzeugt, der auf die Struktur von daveBlockInfo zeigt. Aber wie initialisiere ich den??
    Die Methode daveGetProgrammBlock verlangt als Parameter doch die Länge des DB's oder? Die weiß ich ja nicht.

    Die Funktionen, die du mir geschickt hast:
    Aber mal angenommen du hast in deinem DB zwei INT-Werte und einen BOOL-Wert
    daveAddVarToReadRequest(&p,daveDB,1,0,2);
    daveAddVarToReadRequest(&p,daveDB,1,2,2);
    Die sagen doch schon aus, dass ich weiß wo die INT- und BOOL-Werte adressmäßig beginnen oder? Das weiß ich ja gar nicht. Oder hab ich dich falsch verstanden?

    Meine main() muss im Grunde genommen folgendes können:

    1. Verbindung über CPx43 aufbauen
    2. Länge des DB1 bestimmen
    3. DB1 auslesen und bei 0 beginnen. Bei der ersten Adresse müsste ich dann ja abfragen ob die Adresse 0:
    DB1.DBX0.0 oder
    DB1.DBB0 oder
    DB1.DBW0 oder
    DB1.DBD0 ist.
    Und mit den weiteren Adressen dann auch. Oder gibt es hierzu schon eine fertige Methode von libnodave, die das feststellt um was für ein Datentyp es sich im DB1 handelt?!

  8. #8
    Registriert seit
    11.12.2009
    Beiträge
    2.120
    Danke
    389
    Erhielt 390 Danke für 271 Beiträge

    Standard

    Frage: Warum weist du nicht wie dein DB aufgebaut ist?

    Denn wenn du weist was du für Daten erwartest, dann kannst du eigentlich auch wissen wo diese stehen!
    Wenn du nicht weist was du erwartest, dann weist du ja auch nix mit den Daten anzufangen, also brauchst du sie
    gar nicht.

    In 99,99% der Fälle sind die DBs in der SPS einmal angelegt, und sind dann ein starres Konstrukt. Man KANN sie aus der SPS heraus verändern, löschen, neue anlege. Aber bis jetzt kenne ich noch keinen sinnvollen Anwendungsfall dafür.

    Was ist der Grund warum du den DB nicht kennst?

    Grüße

    Marcel

  9. #9
    Derick87 ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    02.04.2012
    Beiträge
    23
    Danke
    0
    Erhielt 0 Danke für 0 Beiträge

    Standard

    @Matze001

    Ich möchte ein Programm schreiben mit denen ich Daten aus einer Steuerung auslesen möchte.
    Es gibt mehrere verschiedene Anlagen die immer den DB1 als Sammlung von Messwerten, Zuständen usw. Da jede Anlage anders aufgebaut ist, ist die Anordnung von REAL, INT, BOOL immer anders. Beispiel:
    Ich habe mehrere Anlagen aus denen ich den DB1 auslesen möchte:

    Anlage 1: die ersten drei Werte sind REAL Werte: DB1.DBD0, .DBD4, .DBD8
    Anlage 2: die ersten drei Werte: DB1.DBW0, DB1.DBX2.0, DB1.DBX2.1
    Anlage 3: die ersten drei Werte: DB1.DBW0, DB1.DBD2, DB1.DBX6.0
    usw.

    Außerdem haben die verschiedenen DB1 unterschiedliche Länge.

    Das ist meine Aufgabenstellung:

    Aus jeder SPS die einen DB1 besitzt, dieses auszulesen. Egal wie groß er ist und welche Datentypen er besitzt.
    Geändert von Derick87 (05.04.2012 um 10:20 Uhr)

  10. #10
    Registriert seit
    11.12.2009
    Beiträge
    2.120
    Danke
    389
    Erhielt 390 Danke für 271 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ok das verstehe ich nun!

    Aber trotzdem muss man doch der Benutzer eingreifen, und dir sagen was welcher Wert ist... außer du hast 3 bekannte Anlagen, aber dann wäre es wieder ein fixer DB.

    Mein Ansatz wäre:

    Der Benutzer muss eine Tabelle ausfüllen in der steht:

    VariableXYZ ist in DB1.DBW0 zu finden
    VariabeABC ist in DB1 DBB42 zu finden
    ...

    Oder du schreibst dir ein Programm mit dem man DBs importieren kann (AWL Quellen z.B.) oder den DB als CSV exportiert (geht das, ich kopier die immer in Excel)... und die CSV-Datei für die Anlage parst.

    Das wären meine Ansätze für das Problem. Weil du wissen was für Datentypen du im DB hast, hilft dir nicht bei der Zuordnung! Denn die Symbolik wird nicht auf der SPS gespeichert, sprich du bekommst nicht BDE_COUNTER_ROHTEILE aus deinem DB ausgelesen, wenn dein Wert so benannt sein sollte.

    Grüße

    Marcel
    Geändert von Matze001 (05.04.2012 um 12:02 Uhr)

Ähnliche Themen

  1. S7-300/400 Projekt aus CPU
    Von Cell im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 24.10.2011, 11:00
  2. Libnodave + Verbindung CPU
    Von Proxy im Forum Hochsprachen - OPC
    Antworten: 1
    Letzter Beitrag: 19.03.2011, 18:04
  3. S7-300 od 400 mit DataHighway
    Von Parz im Forum Simatic
    Antworten: 1
    Letzter Beitrag: 26.07.2007, 22:25
  4. Proble mit S7 TCP Verbindung zwischen S7 300 und 400
    Von Jochen Kühner im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 02.11.2006, 12:15
  5. Datenempfang auf CPU-400 von CP-300
    Von Wastel im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 05.12.2005, 11:06

Lesezeichen

Berechtigungen

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