LibNoDave kompilieren auf raspberry pi?

Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zottel,

für mich sind das 2 Grundlegende Änderungen beim Programmablauf.
Die eigentliche Änderung besteht in meinen Augen aus diesen beiden Zeilen:
Code:
dc->communicationType = 2; // OP 
    dc->maxPDUlength = 240; // hack for LOGO
Ich habe gefragt, ob es 2 oder 3 Änderungen sind, weil dein voriges Posting DREI Zeilen Code enthielt. (Ja, ich hätte auch in den Quelltext gucken können...)
Das ich die Änderungen brauche ist für mich ein funktionierender Workaround.
Und es wundert mich. Möglicherweise kann die LOGO die PDU-Länge nicht aushandeln, wie es die anderen Steuerungen machen?
Dann verstehe ich, warum
Code:
    dc->maxPDUlength = 240; // hack for LOGO
nötig sein soll. Libnodave macht es erst seit 0.8.5.0.
Aber bei
Code:
dc->communicationType = 2; // OP
glaube ich, dass da etwas nicht richtig sein kann: Alle Versionen von Libnodave vor 0.8.5 setzen immer dort standardmäßig eine 1 ("PG") ein und Leute haben damit mit LOGOs kommuniziert !!!???

Dann beantworte bitte noch mal klip und klar, dass die beiden Programmaufrufe KEIN verschiedenes Ergebnis liefern. Ich sitz da nämlich vor und denke: "Warum postet er nun 2 Ausgaben?. Ich sehe keinen Unterschied!" (abgesehen von der Debug-Ausgabe, die ich zum Vergleich im Geiste ausblenden muß.
Wie wäre es denn wenn man in die Lib ein Precompiler-Flag(#ifdef SIEMENS_LOGO_0BA7) abfägt und beim Aufruf von daveNewConnection(..,..,..,..) die entsprechenden Einstellungen für die PDU-Länge,(..) hinterlegt?
Ziemlicher Mist. 1.Die beiden Ergänzungen
Code:
    dc->maxPDUlength = 240; // hack for LOGO
    dc->communicationType = 2; // OP
können im Anwenderprogramm nach Aufruf von daveNewConnection() und vor daveConnectPLC() vorgenommen werden.
2.Für die Anbindung an solche Programmiersprachen, die nicht direkt über Zeiger auf Felder eines structs zugreifen können, wären Methoden wie setMaxPDUlength erforderlich.
3. Die Optionen von testISO_TCP wären um Optionen für maxPDUlength und Kommunikationsart zu ergänzen.
4. Eventuell wäre ein Programm testLOGO_TCP sinnvoll, weil die Leute sich mit Kommandozeilenoptionen so schwer tun...
 
Hallo Zottel,

Aber bei
Code:
dc->communicationType = 2; // OP
glaube ich, dass da etwas nicht richtig sein kann: Alle Versionen von Libnodave vor 0.8.5 setzen immer dort standardmäßig eine 1 ("PG") ein und Leute haben damit mit LOGOs kommuniziert !!!???
war ja vorher
Code:
-        dc->msgOut[17]=dc->rack+1;
-        dc->msgOut[18]=dc->slot;
+        dc->msgOut[17]=dc->communicationType;  // (1=PG Communication,2=OP Communication,3=Step7Basic Communication)
+        dc->msgOut[18]=dc->slot | dc->rack<<5; // hope I got it right this time...
so das es mit der Übergabe Racknummer 1 mit der LOGO (1+1 = OP) funkte.

Und es wundert mich. Möglicherweise kann die LOGO die PDU-Länge nicht aushandeln, wie es die anderen Steuerungen machen?
so sieht es wohl aus:
die vorherige (V <=0.8.4.6) fixe Initiallänge 960 (0x 03 C0) klappt wohl noch, die neue von 1920 Byte (0x 07 80) führt zu dem Error (0x 81 04).

edit: Typo
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Passen die verschiedenen PDU-Großen des Protokollstapels denn überhaupt zusammen?
Wenn auf ISO-Ebene eine TPDU von 9 Oktetts = 512 Bytes ausgehandelt wird, kann ich darin kein S7-Protokoll-Paket einpacken welches größer ist.

Dann wäre das Verhalten der Logo sogar richtig. Logo stellt fest: da will mir jemand 1920 Bytes S7-Pakete schicken, hat vorher aber nur eine 512 große TDPU ausgehandelt -> passt nicht.

Wenn ich ein S7-Paket mit 960 Bytes verschicken will, muss vorher auch eine entsprechend große TPDU-Größe ausgehandelt werden, z.B. 1024 oder 2048.
 
Das die vorgeschlagene Änderung nur ein Workaround fuer mich ist, will ich nochmal klarstellen.

Ich helfe euch gerne bei der Ursachensuche.
Aber ich brauche konkrete Anforderungen von euch.
Falls Zottel oder ein anderer Entwickler der Libnodave lust auf eine Remote-Sitzung hat, waere ich auch dazu bereit.

Edit:
Testprogramme mit speziellen modifikationen koennte ich auch laufen lassen. Aber dann bitze nur als Source. Kompilieren moechte ich selbst.
 
Zuletzt bearbeitet:
Hi,

diese 960Byte scheint ein MaxWert für die LOGO zu sein, alle Werte kleiner funken.

Wie wäre z.B. es mit einer Halbierung der PDU-Längenvalidierung bei Fehlerversuchen:
Code:
--- nodave.c.org    2013-10-19 18:46:26.000000000 +0200
+++ nodave.c    2014-06-29 12:01:43.869214698 +0200
@@ -3916,6 +3916,7 @@
     if (res==0) {
         return res;
     } else {
+            dc->maxPDUlength /= 2; // retry with half PDUlength
         if (daveDebug & daveDebugPrintErrors){
         LOG2("%s error in daveConnectPLC() step 1. retrying...\n", dc->iface->name);    
         }

Sieht dann mit der LOGO so aus:
Code:
openSocket: enter OpenSocketopenSocket: OpenSocket: socket is 3
openSocket: Connected to host: 10.11.12.235 
openSocket: setsockopt Success 0
send packet: :                             
                            0:0x03,0x00,0x00,0x16,0x11,0xE0,0x00,0x00,0x00,0x01,0x00,0xC1,0x02,0x01,0x00,0xC2,
                            10:0x02,0x02,0x00,0xC0,0x01,0x09,
readISOpacket: 22 bytes read, 22 needed
readISOpacket: packet:                             
                            0:0x03,0x00,0x00,0x16,0x11,0xD0,0x00,0x01,0x8F,0x67,0x00,0xC0,0x01,0x09,0xC1,0x02,
                            10:0x01,0x00,0xC2,0x02,0x02,0x00,
IF1 daveConnectPLC() step 1. got packet: :                             
                            0:0x03,0x00,0x00,0x16,0x11,0xD0,0x00,0x01,0x8F,0x67,0x00,0xC0,0x01,0x09,0xC1,0x02,
                            10:0x01,0x00,0xC2,0x02,0x02,0x00,
TPDU len 9 = 512
PDU header:                             
                            0:0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,
plen: 8 dlen: 0
Parameter:                             
                            0:0xF0,0x00,0x00,0x01,0x00,0x01,0x07,0x80,
_daveExchange PDU number: 65535
IF1 enter _daveExchangeTCP
send packet: :                             
                            0:0x03,0x00,0x00,0x19,0x02,0xF0,0x80,0x32,0x01,0x00,0x00,0xFF,0xFF,0x00,0x08,0x00,
                            10:0x00,0xF0,0x00,0x00,0x01,0x00,0x01,0x07,0x80,
readISOpacket: 27 bytes read, 27 needed
readISOpacket: packet:                             
                            0:0x03,0x00,0x00,0x1B,0x02,0xF0,0x80,0x32,0x03,0x00,0x00,0xFF,0xFF,0x00,0x08,0x00,
                            10:0x00,0x81,0x04,0xF0,0x00,0x00,0x01,0x00,0x01,0x00,0xF0,
IF1 _daveExchangeTCP res from read 27
result of exchange: 0
PDU header:                             
                            0:0x32,0x03,0x00,0x00,0xFF,0xFF,0x00,0x08,0x00,0x00,0x81,0x04,
plen: 8 dlen: 0
Parameter:                             
                            0:0xF0,0x00,0x00,0x01,0x00,0x01,0x00,0xF0,
error: context is not supported. Step7 says:Function not implemented or error in telgram.
IF1 error in daveConnectPLC() step 1. retrying...
PDU header:                             
                            0:0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,
plen: 8 dlen: 0
Parameter:                             
                            0:0xF0,0x00,0x00,0x01,0x00,0x01,0x03,0xC0,
_daveExchange PDU number: 65536
IF1 enter _daveExchangeTCP
send packet: :                             
                            0:0x03,0x00,0x00,0x19,0x02,0xF0,0x80,0x32,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
                            10:0x00,0xF0,0x00,0x00,0x01,0x00,0x01,0x03,0xC0,
readISOpacket: 27 bytes read, 27 needed
readISOpacket: packet:                             
                            0:0x03,0x00,0x00,0x1B,0x02,0xF0,0x80,0x32,0x03,0x00,0x00,0x00,0x00,0x00,0x08,0x00,
                            10:0x00,0x00,0x00,0xF0,0x00,0x00,0x01,0x00,0x01,0x00,0xF0,
IF1 _daveExchangeTCP res from read 27
result of exchange: 0
PDU header:                             
                            0:0x32,0x03,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,
plen: 8 dlen: 0
Parameter:                             
                            0:0xF0,0x00,0x00,0x01,0x00,0x01,0x00,0xF0,
error: ok

*** Partner offered PDU length: 240 used limit 240

Connected.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Passen die verschiedenen PDU-Großen des Protokollstapels denn überhaupt zusammen?
Wenn auf ISO-Ebene eine TPDU von 9 Oktetts = 512 Bytes ausgehandelt wird, kann ich darin kein S7-Protokoll-Paket einpacken welches größer ist.
Nein, die S7-PDU wird dann auf mehrere ISO-Pakete aufgeteilt, die nachher wieder zusammengesetzt werden müssen. Dies passiert auch bei MPI- oder Profibus-Kommunikation, wenn die S7-PDU >240 Byte ist. Dieses Zerlegen und Zusammensetzen ist neu ab Libnodave 0.8.5. Eine PDU mit 1920 Byte habe ich noch nicht gesehn. Maximum war 960. Aber die CPUs, die ich getestet habe, akzeptierten es...
 
Nein, die S7-PDU wird dann auf mehrere ISO-Pakete aufgeteilt, die nachher wieder zusammengesetzt werden müssen. Dies passiert auch bei MPI- oder Profibus-Kommunikation, wenn die S7-PDU >240 Byte ist. Dieses Zerlegen und Zusammensetzen ist neu ab Libnodave 0.8.5. Eine PDU mit 1920 Byte habe ich noch nicht gesehn. Maximum war 960. Aber die CPUs, die ich getestet habe, akzeptierten es...

Stimmt, hatte ich ganz vergessen. Es gibt dafür extra dieses Flag-Bit im Iso-Kopf.
In den meisten Aufzeichnungen die ich habe bei denen ein Siemens-Produkt Client ist, wird eine TPDU von 1024 Bytes und eine PDU von 480 Bytes angefragt.

Ist meiner Meinung nach sinnvoller wenn TPDU >= PDU. Ist TPDU < PDU wird es über die Fragmentierung zwar funktionieren, aber bringt dann doch keinen Vorteil mehr. Oder hat das einen anderen Grund dass bei der neuen libnodave TPDU=512 und PDU=1920 ist?
 
..Ist meiner Meinung nach sinnvoller wenn TPDU >= PDU. Ist TPDU < PDU wird es über die Fragmentierung zwar funktionieren, aber bringt dann doch keinen Vorteil mehr. Oder hat das einen anderen Grund dass bei der neuen libnodave TPDU=512 und PDU=1920 ist?
Bei TPDU=512 bin ich unsicher. Es ist möglich, dass es einfach der Wert ist, der am Ende mehrerer Versuche da stand...das hätte ich mir wohl aufschreiben sollen. Bei der PDU ist es so, dass die Länge bei der Verhandlung in allen Versuchen und Gerätekombinationen immer nur reduziert oder bestätigt wird, man also hoch anfangen muß. Der Wert von 1920 kam zustande, weil:
- 960 habe ich gesehen
- mit der "traditionellen" Pufferlänge daveMaxRawLen=2048 geht noch das Doppelte
- noch größere ansonsten nutzlose Puffer wollte ich nicht anlegen (vor allem wegen embedded-Systemen). Wenn wirklich PDUs von 2*1920 vorkommen würde ich die Puffergröße konfigurierbar machen und den Speicher erst nach der "Verhandlung" allokieren wollen.

Den Nutzen von PDU>TPDU kann ich nicht nachweisen; ich vermute aber dass es ihn dann geben kann, wenn ein Gerät oder ein Teilprozeß innerhalb der Firmware die große PDU empfängt und dann in TPDUs zerlegt. Beispiel: CP443 kriegt die ganze PDU über den Rückwandbus und zerlegt sie selbstständig in TPDUs. Oder ein Prozeß(Thread oder main()) der Firmware beantwortet S7-Anfragen und legt die Antwort-PDU in einem gemeinsam genutzten Speicherbereich ab. Ein anderer Prozeß (Thread oder z.B. Timer-IRQ-Routine) stellt bei Bedarf daraus die nächste TPDU zur Verfügung.
Oder ein Prozeß (Thread oder main()) der Firmware beantwortet S7-Anfragen und legt alle Teil-TPDUs im gemeinsam genutzten Speicherbereich ab. Dort holt sich der TCP-IP-Stack die Pakete nacheinander.
Diese Vorstellungen von der internen Arbeitsweise einer S7 sind nur Spekulation.
Das mit 0.8.5 eingeführte Routing erlaubt noch eine Menge mehr Szenarien, in denen es meiner Vermutung nach so fuktionieren sollte, dass die PDU-Länge mit dem Zielgerät ausgehandelt wird, aber zwischen routenden Geräten andere Paketlängen verwendet werden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen
Ich habe ein kleines Verstaendnisproblem! Wie lese ich aus einer S7-300 ein- bzw. Ausgaenge, oder gar Merker aus? Datenbausteininhalte funktioniert, aber irgendwie erschliesst sich mir die Syntax fuer den Rest nicht! Oder muss ich dann einfach nur "0" angeben? Wenn dem so ist, wie weiss ich dann ob ich Ein- oder Ausgaenge lese? Sorry fuer meine Blindheit!
Gruss Christoph
 
Hallo,
ich und mein Freund habe hier bei mir die Libnodave mal so angepasst das ich auf meine PI die Temperaturwerte aus meiner S7 300 auslesen kann und an das Prog cacti übergeben funktioniert sehr gut.
Hier jetzt nur mit einem Wert dargestellt.
Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "nodave.h"
#include "openSocket.h"

#ifdef LINUX
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#define UNIX_STYLE
#endif

#ifdef BCCWIN
#include <time.h>
    void usage(void);
    void wait(void);
#define WIN_STYLE
#endif

#include <errno.h>

int main(int argc, char **argv) {
    int res;
    daveInterface * di;
    daveConnection * dc;
    _daveOSserialType fds;

    daveSetDebug(daveDebugPrintErrors);

        char *PLC_IP="192.168.0.200";

    fds.rfd=openSocket(102, PLC_IP);
    fds.wfd=fds.rfd;

    if (fds.rfd>0)
        {
                di =daveNewInterface(fds,"IF1",0, daveProtoISOTCP, daveSpeed187k);
                daveSetTimeout(di,5000000);
                dc =daveNewConnection(di,2,0,2);  // insert your rack and slot here
                if (0==daveConnectPLC(dc))
                {

                        res=daveReadBytes(dc,daveDB,400,2,4,NULL);
                        if(0==res)
                        {
                                float TEST=daveGetFloat(dc);

                                printf("TEST %f\n",TEST);
                        }
                        else
                                printf("failed! (%d)\n",res);

                        closeSocket(fds.rfd);

                        return 0;
                }
                else
                {
                        printf("Couldn't connect to PLC with IP \"%s\".\n",PLC_IP);
                        closeSocket(fds.rfd);
                        return -2;
                }
    }
        else
        {
                 printf("Couldn't open TCP port. \nPlease make sure a CP is connected  and the IP \"%s\" address is ok. \n",PLC_IP);
        return -1;
    }
}

Jetzt wollte ich das ganze aus einer Logo 8 auslesen.
Habe den code mal so abgeändert aber bin mir jetzt auch nicht sicher wie ich in meiner Logo Temperaturwerte auslesen kann habe zwei Analogverstärker in de Variablenspeicher.
Habe auch mal einen Analogen Netzwerkausgang gesezt. Oder eine Serververbindung aufgemacht auf der Logo bekomme aber immer nur 0 angezeigt. Kann mir jemand hier mal ein Beispiel geben.
Benutze auch die lib 0.8.5 mit den zwei änderungen wie oben beschrieben.

Code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "nodave.h"
#include "openSocket.h"

#ifdef LINUX
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
#define UNIX_STYLE
#endif

#ifdef BCCWIN
#include <time.h>
    void usage(void);
    void wait(void);
#define WIN_STYLE
#endif

#include <errno.h>

int main(int argc, char **argv) {
    int res;
    daveInterface * di;
    daveConnection * dc;
    _daveOSserialType fds;

    daveSetDebug(daveDebugPrintErrors);

        char *PLC_IP="192.168.1.201";

    fds.rfd=openSocket(102, PLC_IP);
    fds.wfd=fds.rfd;

    if (fds.rfd>0)
        {
                di =daveNewInterface(fds,"IF1",0, daveProtoISOTCP, daveSpeed187k);
                daveSetTimeout(di,5000000);
                dc =daveNewConnection(di,2,0,0);  // insert your rack and slot here
                dc->communicationType = 2; // OP
                dc->maxPDUlength = 240;
                if (0==daveConnectPLC(dc))
                {

                        res=daveReadBytes(dc,daveDB,1,350,2,NULL);
                        if(0==res)
                        {
                                float TEST=daveGetFloat(dc);

                                printf("TEST %f\n",TEST);
                        }
                        else
                                printf("failed! (%d)\n",res);

                        closeSocket(fds.rfd);

                        return 0;
                }
                else
                {
                        printf("Couldn't connect to PLC with IP \"%s\".\n",PLC_IP);
                        closeSocket(fds.rfd);
                        return -2;
                }
    }
        else
        {
                 printf("Couldn't open TCP port. \nPlease make sure a CP is connected  and the IP \"%s\" address is ok. \n",PLC_IP);
        return -1;
    }
}

Danke schonmal für eure Hilfe!
Gruß Frank
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo ich benötige mal eure hilfe.
Ich habe auf einem Raspberry Pi 2 Model B Libnodave Installiert mit
Code:
git clone git://github.com/netdata/libnodave.git
cd libnodave
make
sudo make install

anschließend habe ich in Makefile geändert und "sudo make install"

Ergebniss
Code:
pi@raspberrypi ~/libnodave $ sudo make install
cc -m64 -Wall -Winline -DLINUX -DDAVE_LITTLE_ENDIAN -fPIC -DARM_FIX  -m64 -Wall -Winline -DLINUX -DDAVE_LITTLE_ENDIAN -fPIC  -c -o nodave.o nodave.c
cc1: error: unrecognized command line option â-m64â
cc1: error: unrecognized command line option â-m64â
<builtin>: recipe for target 'nodave.o' failed
make: *** [nodave.o] Error 1

Wenn ich jetzt folgende Eingebe erhalte ich diesen Fehler.
Code:
pi@raspberrypi ~/libnodave $ ./testISO_TCP 192.168.178.23
-bash: ./testISO_TCP: cannot execute binary file

Was mache ich falsch ?
 
Habe die test verbindung hin bekommen.

wie kann ich jetzt einen bit lesen oder schreiben ?
Wenn jemand ein Beispielt hat wie ich z.b einen GIPO Pin zur SPS schreiben kann wäre das super

Ich habe eine S7 315 PN
 
Zuletzt bearbeitet:
Zurück
Oben