Search code examples
cmodbusmodbus-tcp

How to read from modbus/tcp using libmodbus


I have a moxa ioLogik E1214 and I want to communicate with it using modbus/tcp. I found a library that should do that - libmodbus. Firstly i copied the code sample from their website and changed it a litte so it looks like this:

#include <stdio.h>
#ifndef _MSC_VER
#include <unistd.h>
#include <sys/time.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <modbus.h>
#define G_MSEC_PER_SEC 1000

int main(int argc, char *argv[])
{
    modbus_t *mb;
    uint16_t tab_reg[30];
    int length = 6;

    mb = modbus_new_tcp("192.168.127.254", 502);
    if (modbus_connect(mb) == -1) {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(mb);
        return -1;
    }

    /* Read "length" registers from the address 0 */
    int read_val = modbus_read_registers(mb, 0, length, tab_reg);

    if(read_val==-1)
        printf("ERROR: %s\n", modbus_strerror(errno));
    else
    {
        printf("Read registers: %d\n", read_val);
        for(int i=0; i<length; i++)
        {
            printf("%d ", tab_reg[i]);
        }
        printf("\n");
    }
    modbus_close(mb);
    modbus_free(mb);
    return 0;
}

The connection is working but I have a problems reading registers. In documentation there are some parameters with description, start address, length etc, it looks like this: moxa documentation

So I understand that using int read_val = modbus_read_registers(mb, 0, length, tab_reg); should read a value from address 0 and store it in tab_reg. But I get error "Illegal data address". The same is for other addresses I tried to read.

So, to sum up - do I understand everything correctly? How should I use libmodbus to actually read registers?


Solution

  • It seems your slave does not have any holding registers at address 0, and hence it's complaining with the illegal data address error.

    You need to look at the Modbus register map you have and use the correct Modbus function from libmodbus accordingly. For instance, if you want to read your variable RLY_pulseOnWidth you have to use:

    int read_val = modbus_read_input_registers(mb, 52, length, tab_reg);
    

    But to read RLY_TotalCount:

    int read_val = modbus_read_registers(mb, 64, length, tab_reg);
    

    You can check all Modbus function codes that relate to your "Point Type" column here:

    https://github.com/stephane/libmodbus/blob/ddac0cf909d9ab05423df7b9a66e6e60e8bb0fbb/src/modbus.h