Python Forum

Full Version: Help reading data from serial RS485
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello ,
Hello ,
I'm trying to read RS485 data from one pi to another (using TTL to RS485 device)

on the "sender" side I have this simple code:
import time
import serial
from time import sleep
import random
import string

send = serial.Serial(
    port='/dev/serial0',
    baudrate = 9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)


while True:
    letters = string.ascii_letters
    digits = string.digits
    data = ''.join(random.choice(letters) + random.choice(digits) for i in range(20))
    data = (data +"\n\r")
    send.write(data)
    print(data)
    time.sleep(0.2)
in the receiver side I have this code:
import serial

RS485 = serial.Serial(
    port='/dev/serial0',
    baudrate = 9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)

while True:
    x = RS485.readline()
    print(x)



I can see the sender sending this data:
f6d6d0F9B3L1K2C6K0y6m0N2O4S9A8u5y2t0J7f2

H1r1W2X6X0B2i0Y4b0w8U2M6C8X3i1D1D5p9F2y5

f8J8m7z6y3m2U6I3U0Z7J6M4l7Z0B5v4F6H5e2Q2

L6Z0G8m1Q2Q2d6O3t7M8J7h8h8E8b8Z9H3P5I5R2

l3N3T7C2o3T3K3c8G2S5h3G6x6b1O4X1R5B6o1U0

O5S2S3m5L4J5Z7i3U6r5J8h1J2r5k6y8T4S6h7I7

B9E4t5S0k0K1k0T4w4j3t1i0K3w2A5Y9h9N6k2m5

u7E9p4O9D9X0O7V1h1Y6J1R4n3s0g6L2P1A3Z9q9

p3K1X6t0a5P1W4Q6N9G1S8L7C2U2q8k1f6G9O7Q3

r3M9t1J7r0q3c0A0d0z5R0I6b9k1t5f3Q7I5D3w6

I9o6U4F9u8p3m3q5Y3v3I5W0K9O8w7j8z1L8i4f5

Y0I2r5s0K2Q2j9g2Z9T4Y8a9M6W4V5W1C1X5k1K4
but on the receiver I get this :

b'@(\tB\xf7D\xe6\x81F\xb2\x1a@\xa8\x11d3\x8a`\x89@\xfa\x82\xfe\x18`*b\x12dd\x18\xa2@\xb6D\x92 2\x08\xa3@\r\x01B\x11"`\xf2\x12b\x18d\xe6\xa3\x89`w>B\x8fD"d\xf7\x89@\xc9\x82\xff\xa3\xa7@\xf6B\x98\xb2`M\xb2F\x03B\xb3\x82\xfe0+`D\x81DB\x99\x82F{&F\x0b\xfe\x11b\x99\x02F\x8d&d\x19\tB#`J\x81"\x92B\rD\x11b\x98\xb2D\xb2@;F\xe6+D\x0b\x1ab\xa8\xa3`\x99@\xcd\x19D\x10 \x91`\x0c\x7fd:@w\xb2@\x96@\x9bf\xe6*F#`\x89f\x0c\xb7b\x89\x11bd\xbe\xff\xb9\xacf@\t\x1aD\t\x8a@\x98\x86B~+ \x8aB\x10:bM\x8bf\xb2dww`\x83 \x11\x99FJD\x98wD\x913d\x99\xb2F\n'
b'\xfe\xa8@\x0bF\x99\x8b@\x9eFrd\x12`\x82\xfesd\xaab7\x07B;D\xa8\n'
b'd\xc9\x99  F63BD\x99b\x11B7b\x91\x81\x01B\x10\x02B\x19\t`3b:`\tD\xe6\x19ds\xb3B:D\x11Bm:@\td\xe6I\x91B\x12BN\xa2bwB\x8c\x82@3 \x83F\x82B\xea\x11b\x18\x82b\x08\xa2d\x91\x81\n'
b'`\xa2db\xba`\x07f\x91"D\x1a *+Bb7+F\x11@\x8aD\x01d\x81\x90D\x90oB\x91+FD\xec:d@H\xfew2F\x02@\x93d\x11FI+dJ\x01 D\x1fB#@\x11\xa2@`\x08\tF\x0b \xbcB\x8eg@\x01B\t\xb2BH`\x10+ ;\x1bd\x8d>B\x8d*d\x89B\x16b\xb2 B\x16@;B\x98d\x19D\xaa@;; \xa2@7\x03Bbb#b\xc9\x81@L\x82\xfe%\xabDw\x12B\x12`J\xafb\xb2bB\xe7\x18\x0ef\x10@\x10\xa2`\x88*b7@B\xe6\xaa\xc9\xbbDbnDw\xb2bI\xa7F\xbb\x81r\tFr\x1ab\xc8\xb2B\x98\x11B\x8eB\x82\xfe\xe8\x11Dv\x89d\x0cb\x91\x11Ds\xbb@\x82\xff3\x82@\xe8D\xc8\x0bB\[email protected] \xf2#F\xc9d;@\xb2\n'
**when I connect it to my computer I can see the data correcrt.


what am I missing \ doing wrong ?


** when I try to decode the answer
x = RS485.readline()
    data = str(x, 'utf-8')
    print(data)
I get this error:
'utf-8' codec can't decode byte 0xf2 in position 0: invalid continuation byte
Serial expects data to be bytes and you give it a str. I am surprised this didn't raise an exception. What version of Python are you using? In pre-3.0 Python str and bytes were the same. Now str is made up of unicode characters.

This is some serial code I extracted from a recent project. I did some editing, so this code may not run as is.
import serial

class SerialDevice():
    def __init__(self, port_name='COM1', baudrate=19200, timeout=0.1):
        self.port = serial.Serial()
        self.port.port = port_name
        self.port.baudrate = baudrate
        self.port.timeout = timeout

    def open(self, port_name=None, baudrate=None, timeout=None):
        if port_name is not None:
            self.port.port = port_name
        if baudrate is not None:
            self.port.baudrate = baudrate
        if timeout is not None:
            self.port.timeout = timeout

        self.close()

        self.port.open()
        if not self.port.is_open:
            raise IOError(f'Open failed on port {self.port.port}')

    def close(self):
        if self.port.is_open:
            self.port.close()

    def send_cmd(self, command):
        """Send command and read reply"""
        if not self.port.is_open:
            raise IOError('Port is not open')
        self.port.write(f'{command}\r'.encode())
        reply = self.port.read_until(b'\r')   # My device uses /r as a terminator
        if not reply:
            raise IOError('Read timeout error')
        return reply.decode()
The main things you are missing are encoding the strs to bytes before sending/writing with a corresponding decoding on the other side, and a timeout. Every serial program that uses read (and especially readline) should specify a timeout.
so what do I need to do?
what do I need to to make it work ?
change something in the send code?
the sender is using python2 and the receiver use python3

now I'm sending only this:
send.write(bytes('test\r\n'))
and I get this
b'\xbe\x1b\xff'
b'\xbb\x1b\xfe'
b'\xbb\x1b\xfe'
b'\xbb\x1b\xfe'
b'\xbb\x1e\xfe'
b'\xbb\x1b\xfe'
b';\x1b\xff'
b'\xbe\x1b\xff'
b';\x1a\xfe'
b'\xbb\x1b\xfe'
b'\xbb\x1b\xfe'
so I'm getting bytes - but how do I get from this the work 'test'? (which I have sent )?

I assume it's something very easy to do ?

Thanks,
Since the sender is Python2, bytes and str should be the same. The Python3 side wil need to encode() to send and decode() to receive
Still not working

maybe you can see what is wrong

Sender side python2 :
send = serial.Serial(
    port='/dev/serial0',
    baudrate = 9600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
while True:
    send.write('test')
    time.sleep(200)
Receiver side Python3:
while True:
    x = ser.read()
    data = str(x) -->not working et the same b'\xbb\x1b\xfe'
    data1 = str(x).decode('utf-8') --> error AttributeError: 'str' object has no attribute 'decode'

    print(data)
    print(data1)
?

Thanks ,
Look at how I used encode and decode in my initial post.
I don't understand what you are saying...

this is what I understand from you :

the sender side is OK
the problem is in the receiver side, need to add decode

and now what - this is not working as you can see

what I need to change in the receiver ?
can you show\write?

Thanks,
bytes is a collection of bytes (8 bit values). str is a collection of unicode characters. encode() converts a str to bytes. decode() converts bytes to a str.

You are not using decode() correctly. data = x.decode(), not data = str(x).decode().

str(x) does not convert x from bytes to a str. it asks the class bytes to make a string representation of x, usually for the purpose of printing. bytes creates a str containing a bunch of backslashes and hex codes thinking that since it is "bytes" you want to see the hex values of the bytes.

x.decode(encoding) converts the bytes (x) to a str. This consists of grabbing one or two bytes at a time and looking up the associated unicode character. Without an "encoding" argument it assumes bytes were 8 bit ascii characters

str(x).decode() is an error str does not have a decode() method. Why would it? decode() is used to convert something else to a str. If you are already a str, you don't need to be converted to a str.

Even though you probably don't need to encode or decode in Python2 (I've never used it so I don't know for sure), I would still use encode() and decode() and bytes if such things are supported. Then the code would be mostly compatible with Python3.
I did everything you suggested

on the reader part (Pyhton3)
I put:
x = ser.read()
print(x.decode())
and in the sender :
test = 'test1'.encode()
 send.write(test)
I still get en error
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbb in position 0: invalid start byte
can you show me what is wrong?


Thanks ,