Closed theprelior closed 4 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.
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)
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)
Thank you @karlp for your comments.
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>