Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid CRC #744

Closed
theprelior opened this issue May 3, 2024 · 4 comments
Closed

Invalid CRC #744

theprelior opened this issue May 3, 2024 · 4 comments

Comments

@theprelior
Copy link

theprelior commented May 3, 2024

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
image

Steps to reproduce the behavior (commands or source code)

#include <stdio.h>
#include <modbus.h>
#include <cerrno>
#include <iostream>
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<sizeof(tab_reg)/sizeof(tab_reg[0]);i++){
   				printf("reg[%d]=%d (0x%X)\n",i,tab_reg[i],tab_reg[i]);
   		    }
   
   modbus_close(ctx);
   modbus_free(ctx);
}

libmodbus output with debug mode enabled

<...>

@karlp
Copy link
Contributor

karlp commented May 3, 2024

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
Copy link
Author

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
Copy link
Contributor

karlp commented May 3, 2024

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
Copy link
Owner

Thank you @karlp for your comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants