1

I'm having trouble reading packets over a serial line, in the modbus protocol. I want to read the temperature from my thermometer that uses RS485 communication, so I used raspberry pi in combination with waveshare rs485 can hat.

Here is a code sample.

   #!/usr/bin/python3

import RPi.GPIO as GPIO
import serial
import time
from prectime import processor_sleep

rsp = 4
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(rsp, GPIO.OUT)
GPIO.output(rsp, 0)
a = float(7.5)
command = [0x02,0x04,0x00,0x05,0x00,0x01,0x21,0xF8]
r = str(0)

ser = serial.Serial('/dev/ttyS0', 9600, timeout = 0.1)

while len(str(r)) < 31:
    GPIO.output(rsp, 1)
    ser.write(command)
    processor_sleep(a)
    GPIO.output(rsp, 0)
    r = ser.readline()
    print(r,' --- ',a)
    a = a + 0.1
    processor_sleep(1000)

ser.close()

My prectime library with the processorsleep () function is here.

import time

def processor_sleep(ms):
    _ = time.perf_counter() + ms/1000
    while time.perf_counter() < _:
        pass

As soon as I connect the sniffer in parallel to the line I can see that the initiating packet is received and answered by the sensor correctly, however, when I try to read the same answer via python the result is this:

b''  ---  7.5
b''  ---  7.6
b''  ---  7.699999999999999
b'\x02\x04\x02\x01S\xbc\x9d'  ---  7.799999999999999
b'\x02\x04\x02\x01S\xbc\x9d'  ---  7.899999999999999
b'\x02\x04\x02\x01S\xbc\x9d'  ---  7.999999999999998
b'\x02\x04\x02\x01S\xbc\x9d'  ---  8.099999999999998

and it should look like (from sniffer)

b'\x02\x04\x02\x01\x52\xbc\x9d'

I don't know what's going on, sometimes it happens that I catch the packet well, but it's rare.

Thanks in advance.

4
  • I don't use/know Python, but using ser.readline() to retrieve what looks like binary data (rather than a line of ASCII text) is probably incorrect. Also, sleeping after the write and then flipping the GPIO is likely to be problematic because userspace is not synchronized with device I/O. If the transition between transmitting to receiving mode is delayed, you could risk losing input. Switch too early, and transmission is then cut off. Usually RS-485 utilizes HW to perform this mode transition. Commented Mar 14, 2021 at 0:13
  • But I don't know how to enable the HW transition between transmission and receiving. Commented Mar 14, 2021 at 8:16
  • Your device does not support hardware RX/TX toggle. See my answer. Commented Mar 14, 2021 at 9:17
  • Why not try the same using Pymobdus, it may make your output easier to understand and, therefore, to debug Commented Mar 14, 2021 at 20:58

1 Answer 1

1

This topic has been already discussed at length.

Just go here and follow the rabbit hole of links in my answer. You should be able to solve your problem.

I would go for the libmodbus solution (there is a Python wrapper too) but you can also stay with pymodbus if you want.

Anyway, what sawdust says in the comments is also very good advice. The easiest would be to invest 10 bucks and buy a transceiver that is able to toggle itself. Yours is not, unfortunately.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.