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

When "data_format='f'",Invalid CRC in response #176

Open
waCoding opened this issue Nov 21, 2022 · 7 comments
Open

When "data_format='f'",Invalid CRC in response #176

waCoding opened this issue Nov 21, 2022 · 7 comments

Comments

@waCoding
Copy link

My board surport float point number transmission. When excute" data = master.execute(address, cst.READ_HOLDING_REGISTERS, regAddress, quantity, data_format='f')", "modbus_tk.exceptions.ModbusInvalidResponseError: Invalid CRC in response" is display.
Please, help.

@jacksonmatheson
Copy link

Can you please sniff the packets between the 2 devices and paste the raw transmission details for me to review please. Can't really help with so little info.

@waCoding
Copy link
Author

waCoding commented Nov 21, 2022

Can you please sniff the packets between the 2 devices and paste the raw transmission details for me to review please. Can't really help with so little info.

Thanks for answer.
The device for Modbus Slave is STM32F407 with UCOSIII and uCModBus ported. uCModbus Slave support float point transmission, if the register address is higher than "MODBUS_CFG_FP_START_IX"(here is 100) , and the device will send 4 Bytes with format of IEEE 754.

The data transmitted by modbus_tk excute is : 01 03 00 64 00 01 C5 D5
The reply is below.
01 03 04 3E B0 F1 AF F3 D0
01 03 04 3E B2 AC C9 EA AA
01 03 04 3E B3 7C 2F 67 20
01 03 04 3E B6 BF 70 67 E9
01 03 04 3E B5 0C 8A 62 9A
01 03 04 3E B3 DF 3A DE 1F
01 03 04 3E B0 64 E6 5D 76
01 03 04 3E B0 87 73 D4 29
01 03 04 3E B1 E0 F4 EF BB
01 03 04 3E B6 10 34 1A 2A

And when the register address is low than MODBUS_CFG_FP_START_IX, excute data = master.execute(address, functioncode, regAddress, quantity), it works well.

Here is my code:

import serial
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
from PySide6.QtCore import QTimer


master = modbus_rtu.RtuMaster(serial.Serial("Com7", baudrate=115200, bytesize=8, parity='N', stopbits=1, xonxoff=0))
master.set_timeout(5.0)
# master.set_verbose(True)

getDataTimer = QTimer()
data = [100]


def getdata(address=1, fuctioncode=3, regAddress=0, quantity=1):
    global data   
    data = master.execute(address, functioncode, regAddress, quantity, data_format='f')
    print(data)


getDataTimer.timeout.connect(lambda: getdata(1, cst.READ_HOLDING_REGISTERS, 65000, 1))

Thank you again

@jacksonmatheson
Copy link

Can you please copy and paste your code. There are typo's in that and i beleive it's not correct.

Firstly:

  • Line 16: def getdata(address=1, fuctioncode=3, regAddress=0, quantity=1):
  • Line 18: data = master.execute(address, functioncode, regAddress, quantity, data_format='f')
  • fuctioncode vs functioncode

Also, you state that your execute command sends 01 03 00 64 00 01 C5 D5 , but your actual master.execute (line: 22) is:
1, cst.READ_HOLDING_REGISTERS, 65000, 1 which is sending a request to slave_id=1, holding registers, starting from register 65,000, which would make the actual packet modbus_tk send be 01 03 FD E8 00 01 [CRC_HERE]

One quick thing to check though, i know you're talking about the register addresses above 100, but double check you're not trying to get more than 100 registers at one, I do know of a few slave devices that will fail when more than 100 are requested, although you should be able to poll address over 65,000.

Can you also repeat your poll at 65000 but request len=2 and let me know.

@waCoding
Copy link
Author

waCoding commented Nov 21, 2022

Sorry about this mistake,the actual code is correct, I didn't type it correctlly. Here is the copy of code.

uCModbus support 65535 holding registers. And these registers are divided in two parts by defining MODBUS_CFG_FP_START_IX, one part is for 16 bit, and another part is for float point. When the request address is equal or bigger than MODBUS_CFG_FP_START_IX, uCModbus Slave will feedback a float point number with format of IEEE 754.

import serial
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
from PySide6.QtCore import QTimer


master = modbus_rtu.RtuMaster(serial.Serial("Com7", baudrate=115200, bytesize=8, parity='N', stopbits=1, xonxoff=0))
master.set_timeout(5.0)
# master.set_verbose(True)

getDataTimer = QTimer()
data = [100]


def getdata(address=1, functioncode=3, regAddress=0, quantity=1):
    global data
    data = master.execute(address, functioncode, regAddress, quantity, data_format='f')
    print(data)


getDataTimer.timeout.connect(lambda: getdata(1, cst.READ_HOLDING_REGISTERS, 100, 1))

@waCoding
Copy link
Author

Can you please copy and paste your code. There are typo's in that and i beleive it's not correct.

Firstly:

  • Line 16: def getdata(address=1, fuctioncode=3, regAddress=0, quantity=1):
  • Line 18: data = master.execute(address, functioncode, regAddress, quantity, data_format='f')
  • fuctioncode vs functioncode

Also, you state that your execute command sends 01 03 00 64 00 01 C5 D5 , but your actual master.execute (line: 22) is: 1, cst.READ_HOLDING_REGISTERS, 65000, 1 which is sending a request to slave_id=1, holding registers, starting from register 65,000, which would make the actual packet modbus_tk send be 01 03 FD E8 00 01 [CRC_HERE]

One quick thing to check though, i know you're talking about the register addresses above 100, but double check you're not trying to get more than 100 registers at one, I do know of a few slave devices that will fail when more than 100 are requested, although you should be able to poll address over 65,000.

Can you also repeat your poll at 65000 but request len=2 and let me know.

I have repeat my test of polling at 65000 and length =2.
The result is :
If the slave is a simulation machine by modbus slave, modbus_tk works well, but if the slave is the STM32F407, the CRC Error emerged. For the simulation machine I set the data format as 32bit float little-endian. And actually, in the STM32F407 I use the same data format.
Thank you!

@waCoding
Copy link
Author

I have tracked the received response from the STM32F407 Slave machine, I got this.
image
image

And I use another poll tool to get the raw data, I got like this.
Response
image
Request
image

Thank you again.

@enev13
Copy link
Contributor

enev13 commented Apr 18, 2023

Maybe you should investigate the parse_response method of the RtuQuery class in modbus_rtu.py

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