Reading Register Data from a Modbus PLC Simulator

C

Thread Starter

Chuy

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!
 
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:<pre>
/*
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;

}</pre>
 
>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:<pre>
/*
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]));

}</pre>
 
Top