Netzwerk-Funktionen laufen 'ewig' auf Eckelmann-SPS

Begonnen von MKr, 27. Oktober 2011, 16:32:48

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 2 Gäste betrachten dieses Thema.

peewit

nächster test - udp server

zu nimmst die bausteine im anhang

das testprogramm nutzt den sntp_server

programm starten und baustein freigeben

rufew dann deine windows-uhr auf und gehe auf einstellungen
internetzeit - einstellungen änder und trägst als sntp-server die ip-adresse deiner sps ein

dann sollte sich windows normalerweise die uhrzeit von der sps holen

ansonsten die schon bekannten sachen machen .... debug meldungen etc...


[gelöscht durch Administrator]

EMV-Fuzzi

Hallo peewit,

wie zu erwarten, will mein "Fensterchen" die Uhrzeit von KEINEM Server uebernehmen!
Fuer solche Faelle sind dann Pinguine SEHR zuverlaessige Partner!
Was soll ich sagen?!?
Es funktioniert:
  ~$ rdate -n -p steuerung.local.net
  Wed Nov  9 12:22:33 CET 2011
  ~$

(Der Pinguin rechnet in localtime um, deswegen 1h Unterschied)

Zwischenzeitlich habe ich die "test4" - Version in IP_CONTROL2
umgebaut und das MODBUS_Client - Demo aus der network.lib
ausprobiert: Auch das funktioniert - ich bekomme richtige Daten!
Das sollte doch den "TCP-Client" - Test abdecken, oder?

Alles weitere nicht mehr heute...

peewit

#32
modbus client = tcp client test
modbus server = tcp server test


ansonsten , probiere mal möglichst vieles der demoprogramme aus....

und gib dann wieder mal bescheid ...

EMV-Fuzzi

Hallo peewit,

inzwischen konnte ich ein wenig weiterbasteln.

Dies habe jeweils ich mit den Versionen test4 und test5 getestet:

  • SNTP-Client: funktioniert!
  • SNTP-Server: funktioniert!
  • Modbus-Client: funktioniert!
  • Web-Seiten mit HTTP_Get holen: funktioniert!
  • SMTP-Client: funktioniert! (vgl. anderer Thread)
Fuer den Modbus-Server musste ich erkennen, dass ich mich da noch
einlesen muss, damit ich den zum Laufen bekomme...

Koennte es noch mehr Leute als mich geben, die z.B. von einer DBox per
netcat Aktionen auf der Steuerung ausloesen moechte?
Wie saehe ein einfacher "Empfangs-Baustein" fuer diesen Zweck aus?

Die "eierlegende Wollmilchsau" muesste das meines Erachtens gar nicht sein:
Im einfachsten Fall koennte auf einem einstellbaren Port gelauscht werden,
nur das erste empfangene Byte wird als Bitfolge interpretiert (alle anderen
Bytes des IP-Pakets verwerfen!) und an binaeren Ausgaengen dargestellt.

Das bedeutet allerdings, dass die IP des Absenders ueberprueft werden muss,
damit z.B. Broadcast-Nachrichten, Portscans, etc. keine Aktionen ausloesen
koennen. (Waere schon bloed, wenn ein Broadcast vom "Fensterchen" die
Rollaeden herunterfahren laesst...)

peewit

#34
hallo

na das hört sich ja schon gut an.
ich würde sagen ziel erreicht !


die anpassungen die wir für dein system in den ip_control gemacht haben, werden wir in den standard übernehmen

somit kannst du die nächste network.lib 1.21 ohne anpassung verwenden.
kommt ca. ende november !

-----------------------------------------

du willst daten empfangen

1. du brauchst eine IP_CONTROL instanz die zyklisch aufgerufen wird.
2. dann musst du die schnittstelle einrichten (nicht zyklisch beschreiben !)

      IP_C.C_PORT := WORD#123; (* Portnummer eintragen *)
      IP_C.C_IP := DWORD#00; (* IP eintragen *)
      IP_C.C_MODE := BYTE#5; (* Mode: UDP+PASSIV+PORT *)
      IP_C.C_ENABLE := TRUE; (* Verbindungsaufbau freigeben *)
      IP_C.TIME_RESET := TRUE; (* Zeitueberwachung rücksetzen *)
      IP_C.R_OBSERVE := FALSE; (* Datenempfang ueberwachen *)
      S_BUF.SIZE := UINT#0; (* Sendelänge eintragen *)
      R_BUF.SIZE := UINT#0; (* Empfangslänge rücksetzen *)

3. dann musst du nur auf R_BUF.SIZE schauen ob daten drinnen sind
   wenn ja, dann daten verarbeiten und gleich wieder R_BUF.SIZE = 0

4. mehr ist es nicht !

inovent

hallo,
ich arbeite auch gerade an dem gleichen problem
modbus-client auf einer elc66 von eckelmann.

somit lässt sich auch alles übersetzten, nur der fehler "variable socket_fd_setsize nicht deklariert" besteht weiterhin.

irgendwie scheint das bei den obenstehenden projekten aber dennoch zu funktioniern, oder habe ich nur die lösung für dieses problem übersehen?

peewit

wenn du die syslibsocket.lib einbindest, so bringt diese bibliothek eigene globale variablen mit
auf manchen systemen ist anscheinend etwas ein wenig anders .... warum auch immer ....

wenn du glück hast reicht es wenn du die angehängten "original" globale variablen dieser lib dort einfügst bzw ergänzt


VAR_GLOBAL CONSTANT
SOCKET_INVALID:DINT:=-1;

(* AddressFamily *)
SOCKET_AF_UNSPEC:INT:= 0; (* unspecified *)
SOCKET_AF_LOCAL:INT:= 1; (* local to host (pipes, portals) *)
SOCKET_AF_UNIX:INT:=SOCKET_AF_LOCAL; (* backward compatibility *)
SOCKET_AF_INET:INT:=2; (* internetwork: UDP, TCP, etc. *)
SOCKET_AF_IMPLINK:INT:=3; (* arpanet imp addresses *)
SOCKET_AF_PUP:INT:=4; (* pup protocols: e.g. BSP *)
SOCKET_AF_CHAOS:INT:=5; (* mit CHAOS protocols *)
SOCKET_AF_NS:INT:=6; (* XEROX NS protocols *)
SOCKET_AF_ISO:INT:=7; (* ISO protocols *)
SOCKET_AF_OSI:INT:=SOCKET_AF_ISO;
SOCKET_AF_ECMA:INT:=8; (* european computer manufacturers *)
SOCKET_AF_DATAKIT:INT:=9; (* datakit protocols *)
SOCKET_AF_CCITT:INT:=10; (* CCITT protocols, X.25 etc *)
SOCKET_AF_SNA:INT:=11; (* IBM SNA *)
SOCKET_AF_DECnet:INT:=12; (* DECnet *)
SOCKET_AF_DLI:INT:=13; (* DEC Direct data link interface *)
SOCKET_AF_LAT:INT:= 14; (* LAT *)
SOCKET_AF_HYLINK:INT:=15; (* NSC Hyperchannel *)
SOCKET_AF_APPLETALK:INT:=16; (* Apple Talk *)
SOCKET_AF_ROUTE:INT:=17; (* Internal Routing Protocol *)
SOCKET_AF_LINK:INT:=18; (* Link layer interface *)
SOCKET_pseudo_AF_XTP:INT:=19; (* eXpress Transfer Protocol (no AF) *)
SOCKET_AF_COIP:INT:=20; (* connection-oriented IP, aka ST II *)
SOCKET_AF_CNT:INT:=21; (* Computer Network Technology *)
SOCKET_pseudo_AF_RTIP:INT:=22; (* Help Identify RTIP packets *)
SOCKET_AF_IPX:INT:=23; (* Novell Internet Protocol *)
SOCKET_AF_SIP:INT:=24; (* Simple Internet Protocol *)
SOCKET_pseudo_AF_PIP:INT:=25; (* Help Identify PIP packets *)
SOCKET_AF_MAX:INT:=26;
SOCKET_AF_INET_BSD:INT:=100; (* BSD-specific INET af *)
SOCKET_AF_INET_STREAMS:INT:=101; (* STREAMS-specific INET af *)

(* Level number for (get/set)sockopt() to apply to socket itself. *)
SOCKET_SOL:WORD:=16#ffff;

(* Socket options *)
SOCKET_SO_DEBUG:DINT:=16#0001; (* turn on debugging info recording *)
SOCKET_SO_ACCEPTCONN:DINT:=16#0002; (* socket has had listen() *)
SOCKET_SO_REUSEADDR:DINT:=16#0004; (* allow local address reuse *)
SOCKET_SO_KEEPALIVE:DINT:=16#0008; (* keep connections alive *)
SOCKET_SO_DONTROUTE:DINT:=16#0010; (* just use interface addresses *)
SOCKET_SO_BROADCAST:DINT:=16#0020; (* permit sending of broadcast msgs *)
SOCKET_SO_USELOOPBACK:DINT:=16#0040; (* bypass hardware when possible *)
SOCKET_SO_LINGER:DINT:=16#0080; (* linger on close if data present *)
SOCKET_SO_OOBINLINE:DINT:=16#0100; (* leave received OOB data in line *)
SOCKET_SO_REUSEPORT:DINT:=16#0200; (* allow local address & port reuse *)
SOCKET_SO_SNDBUF:DINT:=16#1001; (* send buffer size *)
SOCKET_SO_RCVBUF:DINT:= 16#1002; (* receive buffer size *)
SOCKET_SO_SNDLOWAT:DINT:=16#1003; (* send low-water mark *)
SOCKET_SO_RCVLOWAT:DINT:=16#1004; (* receive low-water mark *)
SOCKET_SO_SNDTIMEO:DINT:=16#1005; (* send timeout *)
SOCKET_SO_RCVTIMEO:DINT:=16#1006; (* receive timeout *)
SOCKET_SO_ERROR:DINT:=16#1007; (* get error status and clear *)
SOCKET_SO_TYPE:DINT:=16#1008; (* get socket type *)
SOCKET_SO_PROTOTYPE:DINT:=16#1009; (* get/set protocol type *)
(* TCPIP socket options *)
SOCKET_TCP_NODELAY:DINT:=16#01; (* don't delay send to coalesce packets *)
SOCKET_TCP_MAXSEG:DINT:=16#02; (* set maximum segment size *)

(* Socket types *)
SOCKET_STREAM:DINT:=1; (* stream socket *)
SOCKET_DGRAM:DINT:=2; (* datagram socket *)
SOCKET_RAW:DINT:=3; (* raw-protocol interface *)
SOCKET_RDM:DINT:=4; (* reliably-delivered message *)
SOCKET_SEQPACKET:DINT:=5; (* sequenced packet stream *)

(* Inet address definitions *)
SOCKET_INADDR_ANY:UDINT:=16#00000000;
SOCKET_INADDR_LOOPBACK:UDINT:=16#7f000001;
SOCKET_INADDR_BROADCAST:UDINT:=16#ffffffff;
SOCKET_INADDR_NONE:UDINT:=16#ffffffff;

(* Protocols *)
SOCKET_IPPROTO_IP:DINT:=0; (* dummy for IP *)
SOCKET_IPPROTO_ICMP:DINT:=1; (* control message protocol *)
SOCKET_IPPROTO_IGMP:DINT:=2; (* group management protocol *)
SOCKET_IPPROTO_GGP:DINT:=3; (* gateway^2 (deprecated) *)
SOCKET_IPPROTO_TCP:DINT:=6; (* tcp *)
SOCKET_IPPROTO_PUP:DINT:=12; (* pup *)
SOCKET_IPPROTO_UDP:DINT:=17; (* user datagram protocol *)
SOCKET_IPPROTO_IDP:DINT:=22; (* xns idp *)
SOCKET_IPPROTO_ND:DINT:=77; (* UNOFFICIAL net disk proto *)
SOCKET_IPPROTO_RAW:DINT:=255; (* raw IP packet *)
SOCKET_IPPROTO_MAX:DINT:=256;

(* Flags *)
SOCKET_MSG_OOB:DINT:=16#1; (* process out-of-band data *)
SOCKET_MSG_PEEK:DINT:=16#2; (* peek at incoming message *)
SOCKET_MSG_DONTROUTE:DINT:=16#4; (* send without using routing tables *)

(* Ioctl commands *)
SOCKET_FIONREAD:DINT:=1; (* get num chars available to read *)
SOCKET_FIONBIO:DINT:=2; (* set to non-blocking *)

(* For SysSockSelect() descriptors *)
SOCKET_FD_SETSIZE :DINT := 64;
MAX_SOCKET_FD_SETSIZE : DINT := 63;
END_VAR

inovent

wunderbar vielen dank
und schon läufts :-)

unten noch der code der umsetzung.
das ganze soll virtuelle ein und ausgänge lesen bzw schreiben.
gedacht habe ich mir das so das ich einfach zyklisch zwischen senden und empfangen umschalte. (sendenteil noch nicht implementiert)

ergibt das so sinn oder totaler nonsense?
konnte das leider noch nicht auf der hardware testen

PROGRAM MODBUS
VAR
IP_CONTROL2_1: IP_CONTROL2;
MB_CLIENT_1: MB_CLIENT;
IP_C: IP_C;

S_BUF: NETWORK_BUFFER_SHORT;
R_BUF: NETWORK_BUFFER_SHORT;

W_DATA_BITPOS: INT;
W_DATA_ADR: INT;
W_POINTS: INT;
W_ADDR: INT;
R_DATA_BITPOS: INT;
R_DATA_ADR: INT;
R_POINTS: INT;
R_ADDR: INT;

IP : DWORD;
FC : INT;

DATA: ARRAY[0..255] OF WORD;
DATA_IN: ARRAY[0..7] OF WORD;
DATA_OUT: ARRAY[0..7] OF WORD;

Send_state : UINT;

i: USINT;
END_VAR




IP := DWORD_OF_BYTE(192,168,178,001);

IP_CONTROL2_1.IP := IP;
IP_CONTROL2_1.PORT := 502;
IP_CONTROL2_1.TIME_OUT := t#5s;
IP_CONTROL2_1(IP_C := IP_C,S_BUF := S_BUF,R_BUF := R_BUF);

MB_CLIENT_1.DATA_SIZE := 8;
MB_CLIENT_1.UDP := FALSE;

MB_CLIENT_1(S_BUF := S_BUF,R_BUF := R_BUF,IP_C := IP_C,DATA := DATA);


CASE Send_state OF

0:  (*READ virtual output, PILZ -> *)
FC := 3;
R_ADDR := 512;
R_POINTS := 8;
R_DATA_ADR := 0;
MB_CLIENT_1.ENABLE := TRUE;

Send_state := 1;

1:
IF NOT MB_CLIENT_1.BUSY THEN
FOR i := 0 TO 7 BY 1 DO
DATA_OUT[i] := DATA[i];
END_FOR;
Send_state := 2;
MB_CLIENT_1.ENABLE := FALSE;
END_IF;

2: (*WRITE virtual input*)

Send_state := 0;


ELSE
Send_state:= 0;

END_CASE;


MB_CLIENT_1.R_ADDR := R_ADDR;
MB_CLIENT_1.R_POINTS := R_POINTS;
MB_CLIENT_1.R_DATA_ADR := R_DATA_ADR;
MB_CLIENT_1.R_DATA_BITPOS := R_DATA_BITPOS;
MB_CLIENT_1.W_ADDR := W_ADDR;
MB_CLIENT_1.W_POINTS := W_POINTS;
MB_CLIENT_1.W_DATA_ADR := W_DATA_ADR;
MB_CLIENT_1.W_DATA_BITPOS := W_DATA_BITPOS;
MB_CLIENT_1.FC := FC;


peewit

#38
schau dir das "MB_CLIENT_DEMO" Programm an das in der network bibliothek im ordner "demo" zu finden ist.
das nimmst du und  parametrierst den baustein nach deinen bedürfnissen.
für was kopierst du die data_in und data_out noch extra hin und her, du kannst doch direkt mit data[index] daten lesen bzw. schreiben
und wo die lesen/schreib daten im DATA array liegen kannst du ja mit dem bausteinparametern vorgeben

wenn du mehr als einen befehlsblock brauchst , dann machst du einfach noch eine baustein instanz vom mb_client
die instanzen koordineren sich automatisch untereinander so dass alle der reihe nach arbeiten (zyklisch)
du kannst aber auch block lesen und block schreiben mit einem einzigen befehl bzw instanz erledigen (ist effektiver)

das mb_client.enable on/off solltest du nicht machen, da hierbei die tcp verbindung auch ständig auf/abgebaut wird
einfach freigeben und in ruhe lassen, solange du kommunizieren willst


EMV-Fuzzi

Hallo peewit,
hallo inovent,

nach längerer Abstinenz möchte ich doch das Thema "Eckelmann-SPS und Netzwerk"
für mich zum Abschluß bringen:

Soweit ich inzwischen recherchiert, gelesen und getestet habe, sieht es für mich so aus,
daß diese Steuerungen NICHT für Netzwerk-Funktionen gemacht sind! Die haben dort
irgendwelchen proprietären Kram eingebaut, damit der Kunde darauf angewiesen ist,
ein PC-Programm von denen einzusetzen, wenn es darum geht die Steuerung mit der
Außenwelt zu verbinden.
Alle Netzwerk-Funktionen, die ich ausgetestet habe, laufen nicht dauerhaft stabil!
Es sieht immer so aus, daß das geht, aber wenn ich das dann im Produktivbetrieb habe,
bleibt die Steuerung irgendwann ohne Vorwarnung stehen.

Die einzige dauerhaft funktionierende Netzwerk-Kommunikation mit der Außenwelt
scheinen die Netzwerk-Variablen zu sein. Diese Variante habe ich allerdings nicht
weiter verfolgt, weil ich die Steuerung mit beliebigen anderen Komponenten (Web-
Browser, Mail-Server, Modbus-Clients, etc) verbinden und nicht nur Daten zwischen
Steuerungen hin- und herschieben wollte.

Wenn mich heute jemand fragen sollte, welche Steuerung ich für Home-Automation
einsetzen würde, die auch noch mit der Außenwelt kommunizieren soll/muß, so würde
ich "Wago" empfehlen! Die sind standardmäßig auf Netzwerk-Betrieb ausgelegt und
funktionieren! Damit habe ich inzwischen auch die Verbindung zwischen SAT-Empfänger,
mehreren PCs und der Steuerung ohne Probleme hinbekommen. Die sprechen alle
untereinander mit standardisierten Protokollen (HTTP, Modbus-TCP, SMTP, etc.).


inovent

Halllo
ich bin auch etwas weiter gekommen,
habe noch ein paar probleme mit der modbus verbindung, läuft wie bei emv-fuzzi beschrieben anscheiend stabil, dann bricht aber die verbindung teils ab.
teils heißt: nur eine richtung bleibt stabil bestehen, d.h. teils bricht das lesen, oder das schreiben auf den modbusteilnehmer ab. die bestehenden verbindungen bleiben dann aber stabil.
bei diesem vorgang bleibt mb_client in state 30 stehen.

allerdings hatte ich auch ein problem mit den codesys eigenen netzwerkvariablen, hier brach die verbindung öfters ab.
die lösung war die eigene implementierung einer udp verbindung durch ein beispielprojekt von eckelmann.
hier bleibt die verbindung seitdem stabil.

d.h. verbindungen nach außen ohne verwendung der netzwerkvariablen herzustellen ist möglich.

somit sollte also auch modbus möglich sein.
hier der code von eckelmann für senden und empfangen:
vielleicht hat jemand eine idee worin der unterschied zum mb_client besteht, oder wie man dem fehler näher kommen könnte

IF NOT Init_bit THEN
SysCreateConn('172.16.5.22', 1000, ADR(Connection_r));
Init_bit := TRUE;
END_IF
(* --------- Receive --------- *)
Result_di := SysSockRecvFrom(Connection_r.UdpSock_di,
ADR(Connection_r.RxMsg_r),
SIZEOF(Connection_r.RxMsg_r),
0,
ADR(UdpRecvAddr_r),
SIZEOF(UdpRecvAddr_r));



IF Result_di > 0 THEN
(* Check correct IP address *)
IF UdpRecvAddr_r.sin_addr = Connection_r.EseeSockAddr_r.sin_addr THEN

(* message received *)

END_IF
END_IF

(* --------- Send --------- *)
IF send THEN
SysSockSendTo(Connection_r.UdpSock_di,
ADR(Connection_r.TxMsg_r),
Connection_r.TxMsg_r.Header.Length,
0,
ADR(Connection_r.EseeSockAddr_r),
SIZEOF(Connection_r.EseeSockAddr_r));

END_IF


peewit

hallo

das ist alles ziemlich schwierig von der ferne ohne dieser hardware die sachlage zu beurteilen

das einzig sinnvolle wäre ein etherreal bzw. wireshark mitschnitt , damit könnte man erkennen welcher teil was macht oder nicht macht.....

anders werde ich euch nicht weiterhelfen können

die oscat modbus bausteine können auch im udp modus betrieben werden, natürlich müssen beide seiten das auch unterstützen

inovent

mal schauen ob ich irgendwie wireshark aufzeichnungen machen kann.
werde mich dann doch mal versuchen selbst durch den baustein durch zu hangeln.
an welchen stellen müsste ich denn ansetzten um die direkte ethernetverbindung von den allgemeinen oscat funktionen auf die eckelmannvorschläge umzubauen?
das müsste ja eigentlich alles rein im ip_control sitzen oder?

peewit

der code von eckelmann ist das was man selber in 5 minuten macht
wenn es so einfach wäre ......


leider gibt es allein bei den verbindungsarten schon client oder server und tcp oder udp modus
der beispielcode ist nur für udp-client kommunikation
es fehlt ja saogar die möglichkeit den socket wieder zu schliessen (SysSockClose)


ich würde ein für dich durchführbares oscat demo programm nehmen und laufen lassen
schauen wie lange es läuft, und optimal wäre in dieser zeit eine wireshark aufzeichnung zu machen...