Today is...
Wednesday, November 22, 2017
Welcome to Control.com, the global online
community of automation professionals.
Featured Video...
Featured Video
Watch an animation of a conveyor stacking operation demonstrating the use of a move on a gear command.
Our Advertisers
Help keep our servers running...
Patronize our advertisers!
Visit our Post Archive
Reading Register Data from a Modbus PLC Simulator
Establishing a connection to a Modbus PLC simulator via Modbus TCP using C code by reading register data.

I am trying to establish a connection to a Modbus PLC simulator via Modbus TCP using C programming by reading its registers data. I was able to communicate with the Modbus PLC simulator (slave) via TCP/IP, but I am having issues trying to send and receive register data from it.

Any help will be greatly appreciated!

Whose simulator are you using?

What configuration have you given it? (like value 123.456 in register 400031)

Hello,

>Whose simulator are you using?
>
>What configuration have you given it? (like value 123.456 in
>register 400031)

I am using a free plc simulator named "MOD_RSSIM" which I found in http://www.plcsimulator.org/

I've been able to establish a connection with the simulator and sending data to it. But I am not sure about how to receive the response to see if I am getting the same requested data back. Is there a way I can receive the requested data back and maybe save it in a parameter to output it in my C code? I am programming in Visual Studio 2015 using C code. Thank you.

Below is my C code:


/*
Create a TCP socket
*/
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library

// A sample of the select() return value
int recvTimeOutTCP(SOCKET socket, long sec, long usec)
{
// Setup timeval variable
struct timeval timeout;
struct fd_set fds;

// assign the second and microsecond variables
timeout.tv_sec = sec;
timeout.tv_usec = usec;
// Setup fd_set structure
FD_ZERO(&fds);
FD_SET(socket, &fds);
// Possible return values:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
return select(0, &fds, 0, 0, &timeout);
}

int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
int SelectTiming;
const char MSG_LEN = 12;
char raw_req[12] = {0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xFF, 0x04, 0x00, 0x01, 0x00, 0x01};
char server_reply[2000];
int recv_size;

printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}

printf("Initialised.\n");

//Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}

printf("Socket created.\n");


server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(502);

//Connect to remote server
if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts("Connected");

// Set 20 seconds 20 useconds timeout
SelectTiming = recvTimeOutTCP(s, 5, 5);

//Send Register data

if (send(s, raw_req, MSG_LEN, 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send\n");

return 0;

//Receive a reply from the server
if ((recv_size = recv(s, server_reply, 2000, 0)) == SOCKET_ERROR)
{
puts("recv failed");
}

puts("Reply received\n");

char a = server_reply;
printf("Char", a);

return 0;

}

>Whose simulator are you using?
>
>What configuration have you given it? (like value 123.456 in
>register 400031)

Also, I gave a value of 100 in Registers 30001, 30002 and 30003.

I got it to work now. I am able to request data and get a response from the Server. One thing that I am having issues with though, is that I am getting the data swap (little-endian format). I am trying to incorporate the htons function into my code to have a single format for all the sending/receiving data. but I am not sure where to include it. Can you please help me on that?

Thanks.

Code:


/*
Create a TCP socket
*/
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library

// A sample of the select() return value
int recvTimeOutTCP(SOCKET socket, long sec, long usec)
{
// Setup timeval variable
struct timeval timeout;
struct fd_set fds;

// assign the second and microsecond variables
timeout.tv_sec = sec;
timeout.tv_usec = usec;
// Setup fd_set structure
FD_ZERO(&fds);
FD_SET(socket, &fds);
// Possible return values:
// -1: error occurred
// 0: timed out
// > 0: data ready to be read
return select(0, &fds, 0, 0, &timeout);
}

int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
int SelectTiming;
const char MSG_LEN = 12;
char raw_req[12] = {0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0xFF, 0x04, 0x00, 0x00, 0x00, 0x03};
unsigned char server_reply[15];
int recv_size;

printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}

printf("Initialised.\n");

//Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
}

printf("Socket created.\n");


server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(502);

//Connect to remote server
if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0)
{
puts("connect error");
return 1;
}
puts(" Connected");

// Set 20 seconds 20 useconds timeout
//SelectTiming = recvTimeOutTCP(s, 10, 10);

//Send Register data
if (send(s, raw_req, MSG_LEN, 0) < 0)
{
puts("Send failed");
return 1;
}
puts("Data Send.\n");

//Receive a reply from the server
if ((recv_size = recv(s, server_reply, 15, 0)) == SOCKET_ERROR)
{
puts("recv failed");
}

puts("Reply received.\n");

printf("Data reg1: %d \n", server_reply[10]);
printf("Data reg2: %d \n", server_reply[12]);
printf("Data reg3: %d \n", server_reply[14]);

//printf("Data: %d", *(short*)(&server_reply[10]));

}