Modbus TCP in CODESYS

Hubertus

Level-1
Beiträge
1
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich möchte eine Kommunikation aufbauen. Auf der Slave Seite habe ich mehrere Soft SPS die in CODESYS erzeugt werden und auf einem Desktop PC laufen. Auf der Master Seite habe ich wiederum einen Desktop PC auf dem ein C++ Programm läuft. Diese sollen über ein LAN Kabel verbunden werden. Als Kommunikationsprotokoll soll Modbus TCP dienen.
Da ich in diesem Bereich neu bin ist mir die konkrete Umsetzung nicht klar.

Auf der Homepage von CODESYS steht, dass Modbus TCP bereits voll integriert ist. Außerdem kann man über „Geräte hinzufügen“ zum Beispiel ein ModbusTCP_Slave_Divice hinzufügen. Hier komme ich leider nicht weiter. Welche Einstellungen muss ich vornehmen? Und vermutlich brauche ich noch eine Bibliothek mit den entsprechenden Befehlen um später Daten auszutauschen. Wo finde ich die, und müsste die nicht bereits schon enthalten sein, da ja Modbus TCP angeblich voll integriert ist. Ist dieser Ansatz mit Grät hinzufügen richtig? Oder geht das ganz anders? Wie ist das weitere Vorgehen?

Da ich mich momentan im Kreis drehe wäre ich über Hilfe sehr dankbar.
Gruß Hubertus
 
Zuletzt bearbeitet:
Hallo Hubertus, nur so als Idee:

FUNCTION_BLOCK Ethernet_Server
VAR_INPUT
xOPEN_SERVER : BOOL; (* Set TRUE to enable function block *)
wPORT : WORD; (* Port number *)
xTCP_PROTOCOL : BOOL; (* TRUE => TCP; FALSE => UDP *)
tTIMEOUT : TIME:=t#20s; (* Watchdog timeout value (seconds) *)
iBYTES_TO_SEND : INT; (* Number of bytes to transmit *)
ptSEND_BUFFER : POINTER TO ARRAY[1..1500] OF BYTE; (* Transmit Buffer *)
END_VAR
VAR_IN_OUT
xSTART_SEND : BOOL; (* Set TRUE to initiate data transmittal, will be *)
(* reset FALSE when transmittal is completed *)
utRECEIVE_BUFFER : typEthernet_BUFFER; (* Receive Buffer *)
END_VAR
VAR_OUTPUT
utERROR : ETH_ERROR; (* See ETH_ERROR datatype in ETHERNET.LIB *)
(* for error codes and definitions *)
xSERVER_OPEN : BOOL; (* TRUE if socket connection made *)
wSOCKET : WORD; (* Socket connection number *)
END_VAR
VAR
MyEthernetOpen : ETHERNET_SERVER_OPEN;
MyEthernetClose : ETHERNET_SERVER_CLOSE;
MyEthernetWrite : ETHERNET_WRITE;
MyEthernetRead : ETHERNET_READ;
EthernetBuffer : ARRAY[1..1500] OF BYTE;
Status : WORD:=0;
i : INT;
getConfig : ETHERNET_GET_NETWORK_CONFIG;
watchdog_timer1 : TON;
client_SRC_IP :DWORD;
client_SRC_PORT:WORD;
CloseState :INT;
END_VAR

IF xOpen_Server THEN
watchdog_timer1(IN:=TRUE , PT:=tTIMEOUT );

IF watchdog_timer1.q THEN
watchdog_timer1(IN:=FALSE , PT:=tTIMEOUT );
MyEthernetClose(EN:= 1, SOCKET:= MyEthernetOpen.SOCKET);
MyEthernetClose(EN:= 0, SOCKET:= 0);
Status := 0; (* Try to open the server *)
END_IF

CASE Status OF
0:
getConfig(EN:=FALSE );
getConfig(EN:=TRUE );
utERROR:=0;
wSocket:=0;
CloseState:=0;
status:=1;
1: getConfig(EN:=TRUE );
IF getConfig.ENO THEN
IF getConfig.IP_ADR<>0 THEN
status:=4;
MyEthernetOpen (EN:=0);
MyEthernetRead(EN:= 0, SOCKET:=0 , DATA:=EthernetBuffer );
MyEthernetClose(EN:= 0);
ELSE
status:=0;
END_IF
END_IF
4: (* try to open a socket*)
IF xTCP_PROTOCOL THEN
MyEthernetOpen(EN:=1 , TYP:=SOCK_STREAM, PROTO := IPPROTO_TCP, PORT := wPort);
ELSE
MyEthernetOpen(EN:=1 , TYP:=SOCK_DGRAM, PROTO := IPPROTO_UDP, PORT := wPort);
END_IF
IF ((MyEthernetOpen.ERROR = 0) AND (MyEthernetOpen.ENO = 1)) THEN
Status := 10; (* socket created, wait for data to process *)
MyEthernetOpen (EN:=0);
xServer_open:=TRUE;
wSocket:=MyEthernetOpen.socket;
ELSE
Status := 0; (*socket not available, try it again *)
MyEthernetOpen (EN:=0);
xServer_open:=FALSE;
wSocket:=0;
END_IF;

10: (* Wait for data to process *)

(* Monitor ethernet port for new data *)
MyEthernetRead( EN:= 1, SOCKET:=MyEthernetOpen.SOCKET , DATA:=EthernetBuffer );
MyEthernetRead( EN:= 0, SOCKET:=0 , DATA:=EthernetBuffer );

IF(MyEthernetRead.ERROR<>0) THEN (* Error reading the socket, close it *)
Status:=40;
ELSIF (MyEthernetRead.LEN_OUT <>0) THEN (* Process the data received via the ethernet port *)
Status:=20;
client_SRC_IP:=MyEthernetRead.SRC_IP;
client_SRC_PORT:=MyEthernetRead.SRC_PORT;
watchdog_timer1(IN:=FALSE , PT:=tTIMEOUT );
ELSIF (iBytes_TO_SEND > 0 AND xSTART_SEND) THEN (* Process the data received via the serial port *)
status:=30;

MyEthernetWrite( EN:= 0 , DATA:=EthernetBuffer );
END_IF

20: (* Process the data received via the ethernet port *)

FOR i := 1 TO (MyEthernetRead.LEN_OUT) DO
utReceive_buffer.index :=(utReceive_buffer.index MOD 1500)+1;
utReceive_buffer.data[utReceive_buffer.index] := EthernetBuffer;
END_FOR

Status:=10;

30: (* Process the data to send *)

EthernetBuffer :=ptSEND_BUFFER^;

(* Send data in transmit buffer out ethernet port *)
IF xTCP_PROTOCOL THEN
MyEthernetWrite( EN:= 1,
SOCKET:= MyEthernetOpen.SOCKET,
LEN_IN:=iBYTES_TO_SEND,
DATA:=EthernetBuffer );
ELSE
IF client_SRC_IP>0 AND client_SRC_PORT>0 THEN
MyEthernetWrite(EN:=1, SOCKET:=MyEthernetOpen.SOCKET , LEN_IN:=iBYTES_TO_SENd , DST_IP:=client_SRC_IP,DST_PORT:=client_SRC_PORT,DATA:=EthernetBuffer );
ELSE
status:=10;
END_IF
END_IF

IF MyEthernetWrite.eno THEN
IF(MyEthernetWrite.ERROR <>0) THEN
Status:=40;(* Error writing to the socket, close it *)
ELSE
Status:=10; (* Comms complete, read more data *)
END_IF;
xStart_send:=FALSE;
END_IF


40: (* Close the server *)

MyEthernetClose(EN:= 1, SOCKET:= MyEthernetOpen.SOCKET);
IF MyEthernetClose.eno THEN
MyEthernetClose(EN:= 0);
xServer_open:=FALSE;
utERROR:=0;
wSocket:=0;
Status := 0; (* Try to open the server again *)
END_IF

END_CASE;
ELSE
CASE CloseState OF
0:
MyEthernetClose(EN:= 0);
MyEthernetClose(EN:= 1, SOCKET:= MyEthernetOpen.SOCKET);
CloseState:=1;
1:
MyEthernetClose(EN:= 1, SOCKET:= MyEthernetOpen.SOCKET);
IF MyEthernetClose.eno THEN
MyEthernetClose(EN:= 0);
CloseState:=2;
END_IF
2:
xServer_open:=FALSE;
utERROR:=0;
wSocket:=0;
END_CASE
END_IF
 
Hallo Hubertus,
wenn es statt C++ auch Perl sein darf kann man das auch so machen:

#!/usr/bin/perl
use strict;
use Modbus::Client;
use FileHandle;
use Socket;
my $fd = new FileHandle;
my $host = "192.168.178.3";
my $port = 502;
my $remote = inet_aton($host) || die "No such host $host";
socket($fd, PF_INET, SOCK_STREAM, getprotobyname('tcp'))
|| die "Can't create socket - $!";
my $paddr = sockaddr_in($port, $remote);
connect($fd, $paddr) || die "Can't connect to $host:$port - $!";
$fd->autoflush(1);
my $bus = Modbus::Client->new($fd);
my $unit = $bus->device(1);
my @array = $unit->read(30001..30010);
print "a1: @array\n";
my $hash = $unit->read(10001..10037);
my %hash = map {$_, 1} (20007, 20012..20015, 30029, 40006);
@array = $unit->read(\%hash);
$hash = $unit->read(\%hash);
print "a2: @array\n";
# $unit->write(6 => 1, 8 => 0, 2007 => 10, 2008 => 2);
#%hash = (6 => 1, 8 => 0, 2007 => 10, 2008 => 2);
#$unit->write(%hash);
#$unit->write(\%hash);
 
Zurück
Oben