pySerial read_until() reads only the first byte - python

So I'm receiving data from a serial port using pySerial. I've a very simple code that reads the first byte, check if it's the start byte ( 0x02 in my case) and then read until it finds the end byte ( 0x03 in my case).
Config the serial communciation
port = 'COM3'
baud = 38400
ser = serial.Serial(port, baud, timeout=0)
if ser.isOpen():
ser.close()
ser.open()
ser.reset_input_buffer()
ser.reset_output_buffer()
The main loop is inside a while True staement as below.
while True:
data = ""
data_raw = ser.read(1)
if data_raw == b'\x02':
data_raw = ser.read_until(b'\x03')
print(str(data_raw))
ser.reset_input_buffer()
ser.reset_output_buffer()
time.sleep(.5)
The issue is that, for some reason, the read_until() actually reads only the first bye while the data I'm receiving from the serial port are actually b'\x02\xff\x9c\x81E1\x03\'
After reading correctly the \x02 the read_until() statement just read only the next \xff and I can't understand why

It seems a bug never fixed by the pySerial module itself https://github.com/pyserial/pyserial/issues/181
Using timeout=None in serial.Serial() resolved the issue

Related

How do I use python to read a serial value from the serial port of a Cardinal Scale head?

If I use Putty to connect with serial to COM1, 1200 baud I get a black screen but when I type Ctlr-E on the keyboard I get the value that I'm looking to record. If I use serial.tools.miniterm and I type Ctrl-E on the keyboard I get the proper value. When I use the following code it seems as though I connect and there is nothing waiting in the buffer:
import serial
ser = serial.Serial(
port='com1',\
baudrate=1200,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
print(ser.flush())
print(ser.flushInput())
print(ser.reset_input_buffer())
print(ser.flushOutput())
print(ser.reset_output_buffer())
print(ser.in_waiting)
print(ser.out_waiting)
print(ser.readline())
print(ser.read())
print(ser.read(1))
ser.close()
I get back on screen:
None
None
None
None
0
0
b''
b''
b''
I was expecting one of these results to be the value I get in Putty and Miniterm.
What am I doing wrong? After connecting with Python can I send that same key sequence that is sent by Putty when I type Ctrl-E?
I figured out what was needed / missing partially due to a post from here on Oct 2nd, 2013 by Chaosphere2112. I need to both send an encapsulated \x05 (thanks barny) but also wait and then read the value in the buffer.
here is the code that worked in the end:
import serial
import time
ser = serial.Serial(
port='com1',\
baudrate=1200,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
ser.write('\x05'.encode('utf-8'))
time.sleep(1)
read_val = ser.read(size=64)
if read_val != '':
print(read_val)
ser.close()
Thank you.

Unable to send/receive data via HC-12/UART in Python

I've written some code to communicate between two Raspberry Pi's, using identical HC-12 433Mhz transceivers. I was able to successfully echo between the two Pi's using a direct serial connection and echo/cat, however am unable to replicate this using HC-12s, which theoretically work by a similar principal. I'm using the port ttyAMA0 on both for this example, but ttyS0 is also available and have tried every combination of these ports.
The following code is common to both the sending and receiving, just writing once for sake of brevity:
import serial
import time
ser = serial.Serial(
port = "/dev/ttyAMA0",
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS
)
print("Serial status: " + str(ser.isOpen()))
This is the sending program:
while True:
print("Sending...")
ser.write("hello\n".encode())
time.sleep(1)
And the receiving program:
while True:
print("Receiving...")
data = ser.readlines()
print(data.decode())
The sending program simply loops as expected, but the receiver prints "Receiving...", and then nothing.
When I keyboard interrupt the receiving program at that point, it says it is currently up to data = ser.readlines().
Any help would be much appreciated - I've spent the better part of the last week trawling and exhausting forums and READMEs to no avail, and this is literally my last option. Am close to insanity on this one!
The pyserial readlines() function relies on the timeout parameter to know when end-of-file is reached - this is warned about in the doco. So with no timeout, the end never occurs, so it keeps buffering all lines read forever.
So you can just add a timeout to the serial port open, and your existing code will begin to work.
ser = serial.Serial(
port = "/dev/ttyAMA0",
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 2 # seconds # <-- HERE
)
A better approach might be to use readline() (note singular, no 's'), for each line in turn:
print( "Receiving..." )
while True:
try:
data = ser.readline()
print( data.decode() )
# TODO - something with data
except:
print( "Error reading from port" )
break
As that will allow the code to act on the input line-by-line.
Use Serial.read_until method. The default termination character is \n.
For example,
data = ser.read_until()
print(data)

Reading Data from ttl rs485 converter In Python

I was trying to read data from smart power meter using ttl rs485 converter and ft232 serial converter connected to PC. I've tried to read the data from serial port using the Pyserial python module and used the code below but the only output I've got was ("b, "b, ",b), I was wondering if there is any mistake in my code!
Thanks.
The code I used
import serial
ser = serial.Serial(
port= 'COM5',
baudrate= 9600,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout= 2
)
print("connected to: " + ser.portstr, "Please wait" )
print('COM5 is now Open!')
ser.flushInput()
ser.flushOutput()
while True:
data = ser.readline()
print(data)
The output I got
connected to: COM5 Please wait
COM5 is now Open!
b''
b''
b''
b''
b''

Read data through RS232 from a device (Displacement measurement) with Python

I've a displacemente measurement and I want that Python give me the values, but I do not know, How receive the data.I use this code, and give me the following error - TypeError: can't concat bytes to str.
`import serial
port = "COM3"
baud = 115200
ser = serial.Serial(port, baud, timeout=1)
# open the serial port
if ser.isOpen():
print(ser.name + ' is open...')
while True:
cmd = input("Enter command or 'exit':")
# for Python 2
# cmd = input("Enter command or 'exit':")
# for Python 3
if cmd == 'exit':
ser.close()
exit()
else:
ser.write(cmd.encode('ascii','strict')+'\r\n')
out = ser.read()
print('Receiving...'+out)
`
write(... does only accept binary data.
Documentation pySerial API
write(data)
Write the bytes data to the port. This should be of type bytes (or compatible such as bytearray or memoryview). Unicode strings must be encoded (e.g.'hello'.encode('utf-8').

Python serial write - lost bytes

I'm trying to send 9 bytes through a serial port (tested with RS232, RS485) with Python 2.7 pySerial package.
If I write out the bytes to the serial port, some of the bytes randomly get lost (do not arrive on the receiving end).
If I use a 1 millisec wait between every write of a single byte, all bytes arrive to the receiving end.
I tested the functionality between 2 serial terminals on the same OS.
Here is the code fragment which causes packet (byte) losses:
import serial
import struct
ser = serial.Serial()
ser.baudrate = 9600
ser.parity = "N"
ser.rtscts = False
ser.xonxoff = False
ser.write(struct.pack('B', 0x61))
ser.write(struct.pack('B', 0x62))
ser.write(struct.pack('B', 0x63))
...
ser.close()
The fragment which is working:
import serial
import struct
from time import sleep
ser = serial.Serial()
ser.baudrate = 9600
ser.parity = "N"
ser.rtscts = False
ser.xonxoff = False
ser.write(struct.pack('B', 0x61))
sleep(0.001)
ser.write(struct.pack('B', 0x62))
sleep(0.001)
ser.write(struct.pack('B', 0x63))
sleep(0.001)
...
ser.close()
What can be the root cause for the random packet losses?
System details:
OSX 10.9.4
Python 2.7
Minicom or screen was used for terminal emulation
Test environment:
ATC USB/RS485 converters
ATC Serial/RS485 converters with USB-Serial adapter
Typically USB serial converters have to be configured to not flush the buffers on close. As you're seeing if you provide a sleep to wait for the data to complete it works. But if you just dump a bunch of characters then close the device it's buffer may still have data which gets trashed on the close. I'd simply recommend either configuring your device to not flush the buffers (if possible) or wait the character time before performing your close.

Categories

Resources