I am currently working on a project which will allow different automates to communicate. To do so, I would like to create a client and a server that will talk using the modbus protocol. I am not sure if I want to be using ModBus/TCP, ModBus/RTU or ModBus/ASCII for now.
I have searched for client/server examples in C and I could find libraries but no simple example of communication. I would like to start from scratch so libraries are not what I am looking for.
What I am asking for is if someone could give me a simple code written in C for a client and/or a server that communicate using Modbus, since I am not sure of what I will be using any type of Modbus would be a great help (RTU/TCP/ASCII).
The simpler the better, what I would like the code to demonstrate is, for example : an initialization to the server, a request, an answer, closing the connection.
Thank you very much for your time.
Three things:
Take a look at this short but quite complete description, and also at the documentation of this constantly updated library.
Here's a super-simplified RTU example for Linux, based on libmodbus.
Allow me some C99 relaxation for compactness.
In the real world you should also properly handle signals like SIGTERM, etc...
There's also a modbus_rtu_set_serial_mode
(RS232 vs RS485) function for Linux kernels 2.6.28 onwards. You may find other libraries that make working with RS485 easier on your platform.
//Create a new RTU context with proper serial parameters (in this example,
//device name /dev/ttyS0, baud rate 9600, no parity bit, 8 data bits, 1 stop bit)
modbus_t *ctx = modbus_new_rtu("/dev/ttyS0", 9600, 'N', 8, 1);
if (!ctx) {
fprintf(stderr, "Failed to create the context: %s\n", modbus_strerror(errno));
exit(1);
}
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Unable to connect: %s\n", modbus_strerror(errno));
modbus_free(ctx);
exit(1);
}
//Set the Modbus address of the remote slave (to 3)
modbus_set_slave(ctx, 3);
uint16_t reg[5];// will store read registers values
//Read 5 holding registers starting from address 10
int num = modbus_read_registers(ctx, 10, 5, reg);
if (num != 5) {// number of read registers is not the one expected
fprintf(stderr, "Failed to read: %s\n", modbus_strerror(errno));
}
modbus_close(ctx);
modbus_free(ctx);
//Prepare a Modbus mapping with 30 holding registers
//(plus no output coil, one input coil and two input registers)
//This will also automatically set the value of each register to 0
modbus_mapping_t *mapping = modbus_mapping_new(0, 1, 30, 2);
if (!mapping) {
fprintf(stderr, "Failed to allocate the mapping: %s\n", modbus_strerror(errno));
exit(1);
}
//Example: set register 12 to integer value 623
mapping->tab_registers[12] = 623;
modbus_t *ctx = modbus_new_rtu("/dev/ttyS0", 9600, 'N', 8, 1);
if (!ctx) {
fprintf(stderr, "Failed to create the context: %s\n", modbus_strerror(errno));
exit(1);
}
//Set the Modbus address of this slave (to 3)
modbus_set_slave(ctx, 3);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Unable to connect: %s\n", modbus_strerror(errno));
modbus_free(ctx);
exit(1);
}
uint8_t req[MODBUS_RTU_MAX_ADU_LENGTH];// request buffer
int len;// length of the request/response
while(1) {
len = modbus_receive(ctx, req);
if (len == -1) break;
len = modbus_reply(ctx, req, len, mapping);
if (len == -1) break;
}
printf("Exit the loop: %s\n", modbus_strerror(errno));
modbus_mapping_free(mapping);
modbus_close(ctx);
modbus_free(ctx);
Thank you very much for your answer, I was looing hope. I am forced to use modbus and even if I wasn't the situation I am working on makes using modbus the, or a, logical solution. Yes I understood that Modbus TCp isn't RTU or ASCII over TCP, what I meant is that modbus TCP is like any TCP communication, the only difference is the data structure (right ?). Thank you for the links, I already got the modbus library, but I would really like an exemple in C which is not using any library.
Well, they explain how to do it, but I would like a written example (in C at best but another language would be ok) to be sure I understand correctly before I start to implement this communication protocol. You seem to know a bit about modbus, maybe you could write a short code showing modbus RTU or ASCII (I understand modbus TCP) interaction between a client and a server ? I would love you for it !
Just updating that I still stuck on modbus serial communication whether it is RTU or ASCII.
Given all you said, in the end I really think that starting from scratch would be very unwise in your case. Though it's very important that you understand the details of the Modbus protocol variants, I do recommend you to not reinvent the wheel and go with an existing C library that fits your platform. I'm going to post a simplified RTU example (ASCII is actually a legacy nowadays) based on libmodbus as soon as I have time. In such kind of programs, you just refer to an OS device name (e.g. /dev/ttyS0, COM6); it's up to you to have that device working as rs232/rs485 serial link.
Thank you very much for the code, I will try to implement it as soon as I can, I am amazed by the time you took to help me and I thank you very very much.