pyhys / minimalmodbus

Easy-to-use Modbus RTU and Modbus ASCII implementation for Python.
Apache License 2.0
306 stars 146 forks source link

Custom FPGA Modbus RTU no working on RPi, works on Windows #85

Closed KingMorphix closed 2 years ago

KingMorphix commented 2 years ago

I am having some trouble with my Raspberry Pi 4, and I am hoping to learn from others to help guide my troubleshooting process.

I have created the Modbus RTU protocol in VHDL for use within an FPGA. I have been able to interface with various devices successfully, but the Raspberry Pi throws me for a loop.

I am using the Minimal Modbus API (Python). On the RPi4 I can read registers with a 100% success rate and write with a ~10% success rate (device communication times out, no response). I have tried two RPI's, one with Kali Linux and the other with Raspian.

If I take the same (changing to COM port) Minimal Modbus API code to a Windows machine, I have a 100% success rate with both read and write commands.

Do you have any idea what I could look into that might explain this problem I am having with Modbus RTU, Minimal Modbus, and Raspberry Pi's?

Any information is helpful, thank you for your time!

j123b567 commented 2 years ago

We are using minimalmodbus in production for many years on several platforms. It talks to our custom MCUs and FPGAs with our firmware and it was always our fault when something similar happen and minimalmodbus was always right.

Main pitfalls we had:

Bad DE driving

The only reliable solution for us was to use circuitry which does its own handling of DE - e.g. USB/RS485 converter with propper chipset which support it.

Misunderstood Modbus RTU framing

Modbus RTU is strictly a time-based protocol. There are no other indications of frame end other than silent on the bus. You may think that you can try to understand the frame prior to the inter-frame delay but this is a big mistake.

See 2.5.1.1 MODBUS Message RTU Framing

You should check the communication with a logic analyzer so you can see all frames, inter-frame delay, handling of DE, etc.

On Windows, you can achieve slightly different timing which accidentally works. You can also play with serial port timeouts so it can wait longer for your response. But before trying random things, it is always better to see what is really on the bus.

KingMorphix commented 2 years ago

I appreciate your feedback and advice, and you were absolutely spot on.

I was able to get this figured out last night, and it came down to timing/framing. When it came to using it for Windows vs. Linux, the less accurate timing precision of Windows (~16ms), was acting as a bandage that inherently provided the 3.5 char minimum silence between messages.

I was able to update my code, and the issue seems solved. Ultimately, I misplaced my 3.5 char timing silence between receiving commands and responses.

Again, I appreciate your insight!