I am running a wago PFC200 PLC and try to drive a equipment using ethernet TCP protocol under Codesys V2.3. I am able to create and connect a socket, send data and close the socket. Yet each time I want to receive data, that I know to be send by the equipment the connexion got stuck and I just have to switch on and of the equipment and restart my PLC.
When I check if the equipement is ready to send back data using SysSockSelect, it returns 0, meaning that it is not ready to talk although it does send data. If I don't use the SysSockSelect and go straight to SysSockRecv then the program got stuck.
IF openSocket THEN
openSocket:=FALSE;
IF(diSocket=-1) THEN
diSocket := TcpClientOpenSocket(iPort, stDestIPAddress, 1000);
END_IF
END_IF
IF recvBt THEN
IF diSocket <> -1 THEN
TcpReceiveData(diSocket, ADR(byRecv), SIZEOF(byRecv), 2);
END_IF
recvBt:=FALSE;
END_IF
IF sendBt THEN
IF diSocket <> -1 THEN
TcpSendData(diSocket, ADR(bySend), SIZEOF(bySend), 2);
END_IF
sendBt:=FALSE;
END_IF
IF closeSocket THEN
closeSocket := FALSE;
SysSockClose(diSocket:=diSocket);
diSocket := -1;
END_IF
(*******)
FUNCTION TcpClientOpenSocket : DINT
( Open TCP client socket to connect to server.
Return: Socket-Id for connection session )
VAR_INPUT
iPort:INT; ( Port number of TCP socket to open )
stIPAddress:STRING; ( IP-Address of server to connect to )
diMaxDataSize:DINT; ( Max size of data to transmitt; if size = 0 default values are used )
END_VAR
VAR
diSocket:DINT;
bOptNoDelay:BOOL;
lOptLinger:SOCKET_LINGER;
bResult:BOOL;
sa:SOCKADDRESS;
END_VAR
END_IF
TcpClientOpenSocket:=diSocket;
(*******)
FUNCTION TcpReceiveData : DINT
( Receive data from a tcp socket.
Return: Number of bytes received )
VAR_INPUT
diSocket:DINT; ( Socket Id )
pbyData:DWORD; ( Address of data buffer )
diDataSize:DINT; ( Size of data to send )
diTImeout : DINT; ( Timeout in seconds )
END_VAR
VAR
fdRead:SOCKET_FD_SET;
tvTimeout:SOCKET_TIMEVAL;
rr:DINT;
IF (SysSockSelect(SOCKET_FD_SETSIZE, ADR(fdRead), 0, 0, ADR(tvTimeout)) > 0) THEN
TcpReceiveData:=SysSockRecv(diSocket, pbyData, diDataSize, 0);
END_IF
(*******)
FUNCTION TcpSendData : DINT
( Send data via TCP socket.
Return: Number of bytes sent )
VAR_INPUT
diSocket:DINT; ( Socket Id )
pbyData:DWORD; ( Address of data buffer )
diDataSize:DINT; ( Size of data to send )
diTImeout : DINT; ( Timeout in seconds )
END_VAR
VAR
fdWrite:SOCKET_FD_SET;
tvTimeout:SOCKET_TIMEVAL;
END_VAR
tvTimeout.tv_sec := diTimeout ;
tvTimeout.tv_usec := 0;
fdWrite.fd_count := 1;
fdWrite.fd_array[0] := diSocket;
IF (SysSockSelect(SOCKET_FD_SETSIZE, 0, ADR(fdWrite), 0, ADR(tvTimeout)) > 0) THEN
TcpSendData:=SysSockSend(diSocket, pbyData, diDataSize, 0);
END_IF
(*******)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello
Me again
Actually I have found where the problem came from. The code was ok but the format of the command I used was missing a new line character at the end (what was not said in the notice).
I have managed to see that using Wireshark a freeware that allows tcp frame inspection on the net. There I saw that the '0a' character was missing compared to the utility software provided by the manufacturer.
Though nobody answered I have thought It might be usefull to some of you to have a clue on how to debug this kind of problem.
Michel
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I am running a wago PFC200 PLC and try to drive a equipment using ethernet TCP protocol under Codesys V2.3. I am able to create and connect a socket, send data and close the socket. Yet each time I want to receive data, that I know to be send by the equipment the connexion got stuck and I just have to switch on and of the equipment and restart my PLC.
When I check if the equipement is ready to send back data using SysSockSelect, it returns 0, meaning that it is not ready to talk although it does send data. If I don't use the SysSockSelect and go straight to SysSockRecv then the program got stuck.
Does anyone have an idea ?
Thank for your help.
Michel
PROGRAM PLC_PRG
VAR
END_VAR
IF openSocket THEN
openSocket:=FALSE;
IF(diSocket=-1) THEN
diSocket := TcpClientOpenSocket(iPort, stDestIPAddress, 1000);
END_IF
END_IF
IF recvBt THEN
IF diSocket <> -1 THEN
TcpReceiveData(diSocket, ADR(byRecv), SIZEOF(byRecv), 2);
END_IF
recvBt:=FALSE;
END_IF
IF sendBt THEN
IF diSocket <> -1 THEN
TcpSendData(diSocket, ADR(bySend), SIZEOF(bySend), 2);
END_IF
sendBt:=FALSE;
END_IF
IF closeSocket THEN
closeSocket := FALSE;
SysSockClose(diSocket:=diSocket);
diSocket := -1;
END_IF
(*******)
FUNCTION TcpClientOpenSocket : DINT
( Open TCP client socket to connect to server.
Return: Socket-Id for connection session
)
VAR_INPUT
iPort:INT; ( Port number of TCP socket to open )
stIPAddress:STRING; ( IP-Address of server to connect to )
diMaxDataSize:DINT; ( Max size of data to transmitt; if size = 0 default values are used )
END_VAR
VAR
diSocket:DINT;
bOptNoDelay:BOOL;
lOptLinger:SOCKET_LINGER;
bResult:BOOL;
sa:SOCKADDRESS;
END_VAR
diSocket:=SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, 0);
IF diSocket <> SOCKET_INVALID THEN
END_IF
TcpClientOpenSocket:=diSocket;
(*******)
FUNCTION TcpReceiveData : DINT
( Receive data from a tcp socket.
Return: Number of bytes received
)
VAR_INPUT
diSocket:DINT; ( Socket Id )
pbyData:DWORD; ( Address of data buffer )
diDataSize:DINT; ( Size of data to send )
diTImeout : DINT; ( Timeout in seconds )
END_VAR
VAR
fdRead:SOCKET_FD_SET;
tvTimeout:SOCKET_TIMEVAL;
rr:DINT;
END_VAR
tvTimeout.tv_usec := 0;
fdRead.fd_count := 1;
fdRead.fd_array[0] := diSocket;
IF (SysSockSelect(SOCKET_FD_SETSIZE, ADR(fdRead), 0, 0, ADR(tvTimeout)) > 0) THEN
TcpReceiveData:=SysSockRecv(diSocket, pbyData, diDataSize, 0);
END_IF
(*******)
FUNCTION TcpSendData : DINT
( Send data via TCP socket.
Return: Number of bytes sent
)
VAR_INPUT
diSocket:DINT; ( Socket Id )
pbyData:DWORD; ( Address of data buffer )
diDataSize:DINT; ( Size of data to send )
diTImeout : DINT; ( Timeout in seconds )
END_VAR
VAR
fdWrite:SOCKET_FD_SET;
tvTimeout:SOCKET_TIMEVAL;
END_VAR
tvTimeout.tv_sec := diTimeout ;
tvTimeout.tv_usec := 0;
fdWrite.fd_count := 1;
fdWrite.fd_array[0] := diSocket;
IF (SysSockSelect(SOCKET_FD_SETSIZE, 0, ADR(fdWrite), 0, ADR(tvTimeout)) > 0) THEN
TcpSendData:=SysSockSend(diSocket, pbyData, diDataSize, 0);
END_IF
(*******)
Hello
Me again
Actually I have found where the problem came from. The code was ok but the format of the command I used was missing a new line character at the end (what was not said in the notice).
I have managed to see that using Wireshark a freeware that allows tcp frame inspection on the net. There I saw that the '0a' character was missing compared to the utility software provided by the manufacturer.
Though nobody answered I have thought It might be usefull to some of you to have a clue on how to debug this kind of problem.
Michel
did you able to send and receive data later ?