Fail to read AcuRev energy meter : Invalid CRC

305 views
Skip to first unread message

zouro...@gmail.com

unread,
Jun 28, 2018, 11:02:43 AM6/28/18
to libmodbus

Dear All,

 

I am new to the LibModBus library and I have been working with it for the past two weeks or so. I have installed LibModBus 3.1.4 on a Raspbian lite on a RPI3.

 

I am attempting to read an AcuRev 1300 energy meter as well. However, I am still getting the same error of Invalid CRC. Here is a sample output:

Opening /dev/ttyAMA0 at 9600 bauds (N, 8, 1)
[01][04][00][0A][00][12][50][05]
Waiting for a confirmation...
<01><04><00><0A><00>
ERROR CRC received A00 != CRC calculated 22C0
Fail to read energy meter registers: Invalid CRC

I have the A socket from the meter connected to the Rx port on the pi, and the B socket from the meter connected to the Tx port on the pi. And the S from the meter connected to the GND on the Pi.


Next, after reading some of the issues on the form, I tried setting the timeout using modbus_set_response_timeout(ctx, 0, 200000); but I got a segmentation fault message.


Any help/suggestions/advice would be greatly appreciated. 


zouro...@gmail.com

unread,
Jun 28, 2018, 11:05:29 AM6/28/18
to libmodbus
This is the code I am working with:


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <modbus-rtu.h>

const int EXCEPTION_RC = 2;

enum { TCP, TCP_PI, RTU };

#define SERVER_ID 1

int main(int argc, char *argv[]) {
    modbus_t *ctx = NULL;
    uint16_t *tab_rp_bits = NULL;
    struct timeval old_response;
    struct timeval new_response;
    uint32_t old_response_to_sec;
    uint32_t old_response_to_usec;
    uint32_t new_response_to_sec;
    uint32_t new_response_to_usec;
    uint32_t old_byte_to_sec;
    uint32_t old_byte_to_usec;
    int rc;
    int server_id = SERVER_ID;

    // UPDATE THE DEVICE NAME AS NECESSARY
    ctx = modbus_new_rtu("/dev/ttySC0",1200 , 'N', 8, 1);
    if (ctx == NULL) {
        fprintf(stderr, "Could not connect to MODBUS: %s\n", modbus_strerror(errno));
        return -1;
    }

    printf("Setting slave_id %d\n", server_id);
    fflush(stdout);
    rc = modbus_set_slave(ctx, server_id);
    if (rc == -1) {
        fprintf(stderr, "server_id=%d Invalid slave ID: %s\n", server_id, modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    modbus_set_debug(ctx, TRUE);
    // Not needed for USB-RS485 adapters
   /* rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
    if (rc == -1) {
        fprintf(stderr, "server_id=%d Failed to set serial mode: %s\n", server_id, modbus_strerror(errno));
        // modbus_free(ctx);
        // return -1;
        server_id++;
        goto retry_slave;
    }*/
    modbus_set_error_recovery(ctx,
                              MODBUS_ERROR_RECOVERY_LINK |
                              MODBUS_ERROR_RECOVERY_PROTOCOL);

 modbus_get_response_timeout(ctx, &old_response_to_sec , &old_response_to_usec);
    printf("old response to sec = %d old response to usec = %d \n", old_response_to_sec, old_response_to_usec);
   // modbus_set_response_timeout(ctx,0 , 2125663232);
    printf("old response to sec = %d old response to usec = %d \n", old_response_to_sec, old_response_to_usec);
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }
    modbus_get_response_timeout(ctx, &new_response_to_sec ,&new_response_to_usec);

    tab_rp_bits = (uint16_t *) malloc(1000 * sizeof(uint16_t));
    memset(tab_rp_bits, 0, 1000 * sizeof(uint16_t));

    while (TRUE) {
        rc = modbus_read_input_registers(ctx,0 , 100, tab_rp_bits);
        if (rc == -1) {
            fprintf(stderr, "Failed to modbus_read_input_registers: %s\n", modbus_strerror(errno));
            /* modbus_free(ctx);
            return -1; */
        }
        printf("server_id=%d rc=%d temp=%f \n", server_id, rc, (double)(tab_rp_bits[0] / 100.0));
        printf("tab 2 = %d tab 3 = %d \n",(double)(tab_rp_bits[1] / 100.0),(double)(tab_rp_bits[2] / 100.0));
        sleep(1);
    }

    close:
    /* Free the memory */
    free(tab_rp_bits);

 // free(tab_rp_registers);

    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;

Michael Heimpold

unread,
Jun 28, 2018, 2:44:13 PM6/28/18
to libmodbus
hi,

when I start with a new device, I always try to connect it first to PC using an USB RS-485 adapter
and a simple terminal program. I recommend hterm (also available for Linux), where you can
send also hex strings etc.
Or you can use a tool like QModbus or so to verify, that the meter is responding correctly.
I assume that your meter sends a complete response packet, but your timeout is too short and
thus you fetch only the first part of the response message which then in turn looks like a  wrong CRC.
You can also attach a logic analyzer after thr RS-485 line driver in case you want to see whats going on on the wire...

Regards,
mhei

zouro...@gmail.com

unread,
Jun 28, 2018, 2:59:45 PM6/28/18
to libmodbus
Extremely thankful for your reply. I will try to check the meter itself as you have suggested, but I want to ask you this just because I am currently stuck at it. Why is it when I try to set the timeout it gives me a segmentation fault?? I have read something in one of the posts about the .so file being of version 5.0 and that it should be 3.x.0. This is the actual post: https://groups.google.com/forum/#!topic/libmodbus/bgE2Yh8JkzU 

Can you please provide me further insight on this solution? it might help with my current segmentation fault.

Thank you.

watsocd

unread,
Jun 28, 2018, 3:37:11 PM6/28/18
to libm...@googlegroups.com
For troubleshooting of segmentation faults I found it useful to use Valgrind on a full PC.

This helped me tremendously with debugging before I tried the code on a Raspberry Pi.


Sent via the Samsung Galaxy Note5, an AT&T 4G LTE smartphone
--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes "libmodbus".
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse libmodbus+...@googlegroups.com.
Pour obtenir davantage d'options, consultez la page https://groups.google.com/d/optout.

zouro...@gmail.com

unread,
Jun 29, 2018, 12:16:02 PM6/29/18
to libmodbus
I am not sure if this is progress or not, but now I am getting an Illegal Function message when I try to read.

root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests# ./Zourob_Test
Setting slave_id 1
Opening /dev/ttySC0 at 19200 bauds (N, 8, 1)
[01][04][00][64][00][01][70][15]
Waiting for a confirmation...
<01><84><01><82><C0>
ERROR Illegal function
Failed to modbus_read_input_registers: Illegal function
server_id=1 rc=-1 temp=0.000000

zouro...@gmail.com

unread,
Jun 29, 2018, 12:18:17 PM6/29/18
to libmodbus
It seems I had the wrong baud rate and that's why I am getting an illegal function response. What does an illegal function mean?

Michael Heimpold

unread,
Jun 29, 2018, 3:27:29 PM6/29/18
to libmodbus
In Modbus protocol there are "holding registers" vs. "input registers", both require different function codes to query.
Check the datasheet of the meter, whether the registers are declared as holding or input registers,
and then use the right libmodbus function query. I would guess, that the registers are holding registers and sometimes
meters don't distinguish between and you can use either function code.

The timeout functions changed between stable libmodbus release and latest developer version, so check which library
version you are using and call the function with right arguments. Then not segfault should occur.

zouro...@gmail.com

unread,
Jul 4, 2018, 11:43:19 AM7/4/18
to libmodbus
Thank you very much for your help. The meter I am using only uses two function codes (03H) and (10H). I was able to read and write successfully. However, rarely the timeout message would pop up for some reason. Here is an example:

root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests/Zoruob_Files# ./ModBus_Read_Registers_F03
Setting slave_id 5
old response to sec = 0 old response to usec = 500000
old response to sec = 0 old response to usec = 500000
Opening /dev/ttyUSB0 at 19200 bauds (N, 8, 1)
[05][03][04][02][00][08][E5][78]
Waiting for a confirmation...
<05><03><10><00><01><00><07><00><0D><00><03><00><00><00><05><00><11><00><15><AD><B8>
Server ID = 5 RC = 8
Register: 0402 --> 1
Register: 0403 --> 7
Register: 0404 --> 13
Register: 0405 --> 3
Register: 0406 --> 0
Register: 0407 --> 5
Register: 0408 --> 17
Register: 0409 --> 21
root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests/Zoruob_Files# ./ModBus_Read_Registers_F03
Setting slave_id 5
old response to sec = 0 old response to usec = 500000
old response to sec = 0 old response to usec = 500000
Opening /dev/ttyUSB0 at 19200 bauds (N, 8, 1)
[05][03][04][02][00][08][E5][78]
Waiting for a confirmation...
<05><03><10><00><01><00><07><00><0D><00><03><00><00><00><05><00><11><00><15><AD><B8>
Server ID = 5 RC = 8
Register: 0402 --> 1
Register: 0403 --> 7
Register: 0404 --> 13
Register: 0405 --> 3
Register: 0406 --> 0
Register: 0407 --> 5
Register: 0408 --> 17
Register: 0409 --> 21
root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests/Zoruob_Files# ./ModBus_Read_Registers_F03
Setting slave_id 5
old response to sec = 0 old response to usec = 500000
old response to sec = 0 old response to usec = 500000
Opening /dev/ttyUSB0 at 19200 bauds (N, 8, 1)
[05][03][04][02][00][08][E5][78]
Waiting for a confirmation...
ERROR Connection timed out: select
Bytes flushed (0)
Failed to modbus_read_registers: Connection timed out
Server ID = 5 RC = -1
Register: 0402 --> 0
Register: 0403 --> 0
Register: 0404 --> 0
Register: 0405 --> 0
Register: 0406 --> 0
Register: 0407 --> 0
Register: 0408 --> 0
Register: 0409 --> 0
root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests/Zoruob_Files# nano ModBus_Read_Registers_F03.c                                                     
root@techbase:/home/user/Zourob_Exp/libmodbus-3.1.4/tests/Zoruob_Files# ./ModBus_Read_Registers_F03
Setting slave_id 5
old response to sec = 0 old response to usec = 500000
old response to sec = 0 old response to usec = 500000
Opening /dev/ttyUSB0 at 19200 bauds (N, 8, 1)
[05][03][04][02][00][08][E5][78]
Waiting for a confirmation...
<05><03><10><00><01><00><07><00><0D><00><03><00><00><00><05><00><11><00><15><AD><B8>
Server ID = 5 RC = 8
Register: 0402 --> 1
Register: 0403 --> 7
Register: 0404 --> 13
Register: 0405 --> 3
Register: 0406 --> 0
Register: 0407 --> 5
Register: 0408 --> 17
Register: 0409 --> 21

Moreover, after installing libmodbus 3.1.2, the segmentation fault message diapered when I call the modbus_set_response_timeout function. However, before calling it, when I try to get_response_timeout, now it is set to a fixed value of 500000 micro seconds. Is there a way to control and set the timeout on the device?

Thank you!
Reply all
Reply to author
Forward
0 new messages