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.

  • 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. – sawdust Mar 14 '21 at 00:13
  • But I don't know how to enable the HW transition between transmission and receiving. – Tomáš Macháček Mar 14 '21 at 08:16
  • Your device does not support hardware RX/TX toggle. See my answer. – Marcos G. Mar 14 '21 at 09:17
  • Why not try the same using Pymobdus, it may make your output easier to understand and, therefore, to debug – Hayden Eastwood Mar 14 '21 at 20:58

1 Answers1

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.

Marcos G.
  • 3,371
  • 2
  • 8
  • 16