stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.53k stars 1.77k forks source link

Invalid CRC #744

Closed theprelior closed 4 months ago

theprelior commented 7 months ago

libmodbus version

3.1.10

OS and/or distribution

Ubuntu 22.04.4 Jammy release

Environment

Raspberry Pi 4B Arc

Description

Hello, I'm trying to connect and get datas from specific registers that is on a slave connected to raspbery pi from /dev/ttyUSB0 port. Connecting and opening port are okay but here is the problem whenever I tried to read registers which is starting 30001 and up to 30004 it says invalid crc. But if I start with 0 I got these different datas from expected

Actual behavior if applicable

int rc=modbus_read_registers(ctx,30001,3,tab_reg); Opening /dev/ttyUSB0 at 9600 bauds (O, 8, 1) [21][03][75][30][00][04][59][6A] Sending request using RTS signal Waiting for a confirmation...

<21><00><00><00><00> ERROR CRC received 0x0 != CRC calculated 0x21CA Invalid CRC int rc=modbus_read_registers(ctx,0,3,tab_reg); Opening /dev/ttyUSB0 at 9600 bauds (O, 8, 1) [21][03][00][00][00][03][02][AB] Sending request using RTS signal Waiting for a confirmation... <21><03><06><00><00><00><00><00><21><78> reg[0]=0 (0x0) reg[1]=0 (0x0) reg[2]=33 (0x21) reg[3]=0 (0x0) ## Expected behavior or suggestion ![image](https://github.com/stephane/libmodbus/assets/43340373/54f4e1d0-f29b-484c-b7c3-aee4d29d2b81) ![image](https://github.com/stephane/libmodbus/assets/43340373/09bc54e0-c1aa-4a7b-bdea-8528c65ea54a) ## Steps to reproduce the behavior (commands or source code) ``` #include #include #include #include int main(){ const int REMOTE_ID = 33; modbus_t *ctx; uint16_t tab_reg[4]; ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'O', 8, 1); modbus_set_slave(ctx, 33); modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485); modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP); modbus_rtu_set_rts_delay(ctx, 3); modbus_set_debug(ctx, 1); if (ctx == NULL) { fprintf(stderr, "Unable to create the libmodbus context\n"); return -1; } if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } int rc=modbus_read_registers(ctx,30001,3,tab_reg); if(rc==-1){ fprintf(stderr,"%s\n",modbus_strerror(errno)); std::cout<<"Reading register error"; return -1; } for (int i=0;i
karlp commented 7 months ago

Correct. Welcome to the wonderful world of modbus. "30000" just means "registers" and 20000 and 40000 just mean "input registers" and "coils"

it's kinda like "modbus_opration(3000x)" will automatically do a read_registers(x) and "modbus_operation(4000x)" will automatically do a "read_holding_registers(x)"

libmodbus doesn't support the 30000 style, just the "full" style.

theprelior commented 7 months ago

How can I solve this problem and read these datas as I expected on top?Btw tried to start with 40001. I already wrote a code snippet which is working with termios but here too, the datas are not resolvable.

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <cstdint>
#define DEVICE_PATH "/dev/ttyUSB0" // Update the serial port path appropriately
#define REMOTE_ID 33 // Device's slave ID
#define START_ADDRESS 30001 // Start register address
#define NUM_REGISTERS 4 // Number of registers to read

int main() {
    int fd;
    struct termios serial;
    uint16_t tab_reg[NUM_REGISTERS];

    // Open the serial port
    fd = open(DEVICE_PATH, O_RDWR | O_NOCTTY);
    if (fd == -1) {
        perror("open");
        return -1;
    }

    // Configure the serial port settings
    tcgetattr(fd, &serial);
    cfsetispeed(&serial, B9600); // Set input baud rate
    cfsetospeed(&serial, B9600); // Set output baud rate
    serial.c_cflag |= (CLOCAL | CREAD); // Enable port for local and reading capabilities
    serial.c_cflag &= ~PARENB; // Disable parity
    serial.c_cflag |= PARODD;
    serial.c_cflag &= ~CSTOPB; // Use 1 stop bit
    serial.c_cflag &= ~CSIZE; // Clear data bits
    serial.c_cflag |= CS8; // Use 8 data bits
    serial.c_cc[VMIN] = 0; // Set minimum character count to 0
    serial.c_cc[VTIME] = 10; // Set timeout to 1 second

    // Apply the serial port settings
    tcsetattr(fd, TCSANOW, &serial);

    // Modbus read operation
    if (write(fd, "\x21\x03\x75\x31\x00\x04\x49\x68", 8) != 8) {
        perror("write");
        return -1;
    }

    sleep(3); // Wait for 0.5 seconds

    int rc = read(fd, tab_reg, sizeof(tab_reg));
    if (rc == -1) {
        perror("read");
        return -1;
    }

    // Print the read register values
    for (int i = 0; i < NUM_REGISTERS; i++) {
        printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
    }

    // Close the serial port
    close(fd);

    return 0;
}

output: reg[0]=45936 (0xB370) reg[1]=51248 (0xC830) reg[2]=65535 (0xFFFF) reg[3]=0 (0x0)

karlp commented 7 months ago

You simply don't. libmodbus (much as many other tools) simply doens't use the 300xx / 400xx addressing. If you want to read 30013, you do a "read regs 13" if you want 40013, you do a "read holding regs 13" (or vice versa, I never remember which is holding and which is input)

stephane commented 4 months ago

Thank you @karlp for your comments.