Pyserial can't read device - python

I'm trying to read data off of a sensor that I bought, using a conversion module (SSI to RS232). I have the module plugged into my Windows laptop via USB/serial converter.
When I use Putty in Serial mode, I can send the command $2RD and receive the appropriate response from the sensor unit. When I run a script to try to do the same thing, the unit returns: ''
Here is the code I am using:
import sys
import serial
import time
ser = serial.Serial(
port='COM4',
baudrate=9600,
timeout=1,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
)
while True:
ser.write('$2RD'.encode())
#time.sleep(1)
s = ser.read(26)
print s
A few other notes:
I've tried some variations using flushInput, flushOutput, sleeping, waiting, etc...nothing seems to help.
I know I have the COM ports right/the hardware all works in Putty, so pretty sure this is something with my code.
I've also tries 13,400 BAUD with no difference in outcome.
If I connect the TX and RX lines from the USB, I can read the command I'm sending...so it should be at least getting to the RS232/SSI conversion device.

s = ser.read(26) should probably be ser.read(size=26) since it takes keyword argument and not positional argument.
Also, you can try to set a timeout to see what was sent after a specific time because otherwise the function can block if 26 bytes aren't sent as specified in the read docs of pyserial :
Read size bytes from the serial port. If a timeout is set it may return less characters as requested. With no timeout it will block until the requested number of bytes is read.

Related

Why can't I read my data from my serial port?

Why is this code not working?
import serial
s = serial.Serial('/dev/ttyUSB1')
#s.open()
s.write(b"1234")
print(s.read())
print(s.read_all())
When I run this code, I get this output:
b'1'
b''
Since there is on Information about any device connected and the output is empty the second time I assume you need a delay or some kind of waiting in your code. This is because the machine you are running the python script on executes much faster than your baudrate of the serial device.
Try this for example:
import serial
import time
s = serial.Serial('/dev/ttyUSB1')
s.write(b'1234')
time.sleep(1)
print(s.read_all())

Pyserial: readline() is blocking, although timeout is defined

I have an issue with readline() from pyserial.
My code is:
import serial
uart = serial.Serial(port='/dev/ttyS0', baudrate=9600, timeout=3)
data = uart.readline().decode()
print(data)
uart.close()
I'm receiving data from a microcontroller. The problem is, if no data is send from the mc, the program is waiting "forever", although I defined a timeout of 3 seconds.
What am I doing wrong?
Ok, I have discovered the solution
The problem is, that the Raspberry Pi 3 and 4 uses the "miniUART" as the primary UART and the Raspberry Pi 1 and 2 uses the "PL011".
You can the details here: https://www.raspberrypi.org/documentation/configuration/uart.md
To get the timeout break working, you have to change the "PL011" to UART0. By default UART0 (GPIO 14 and 15) is set to "miniUART" and "PL011" is used for the bluetooth modem.
You have to edit the /boot/config.txt and add dtoverlay=disable-bt.
You also have to disable the system service, that initialises the modem, so it does not connect to the UART, using sudo systemctl disable hciuart.
I have done that and now the program waits the timeout for a message and goes on, if no message is received.
timeout will only affect the maximum time that readline() will wait
timeout = x: set timeout to x seconds (float allowed) returns immediately when the requested number of bytes are available, otherwise wait until the timeout expires and return all bytes that were received until then
try this :
import serial
uart = serial.Serial(port='/dev/ttyS0', baudrate=9600, timeout=3)
while True:
data = uart.readline().decode()
print(data)
if not data :
break
uart.close()

Serial communication with python

I'm fiddling a bit with python for serial communication, I have a switch that interacts with a screen and this screen in turn has 2 PCs connected to its HDMI ports, what I want to do is make this switch change from HDMI1 to HDMI2 port what I've been trying looks like this:
import pyserial
connection = serial.Serial(
'COM1',
baudrate=9600,
bytesize=8,
patity='N',
stopbits=1
)
I really believe that the connection is well established, when I do the following connection.is_open the answer is True.
However, I think that my problem is in what is the correct way to compose the chain that sends the commands to the switch through the function connection.write()
r source! ( Reading the input source at that time )
s source 1! ( Switch HDMI1 input(1:HDMI1,2:HDMI2,
3:HDMI3,4:DisplayPort,5:VGA/YPBPR/C-VIDEO) )
s hdmi1 auido 0! ( Choice of audio source as audio input
HDMI1 (0: Emb,1: Ext1,2: Ext2,3:Ext3,4:Ext4,5:Ext5) )
I really believe that my real problem is not knowing how to compose the command string that is sent with the function write() other aspect to consider is that I am using python 2.7 and windows.
the truth is that I am a newbie, if you can help me I will be very grateful.
just set a timeout and read until that happens
import pyserial
connection = serial.Serial(
'COM1',
baudrate=9600,
bytesize=8,
patity='N',
stopbits=1,
timeout=1 # could probably be less
)
# maybe .... are there some docs for whatever switch you are using?
connection.write("r source!\n")
# you might need connection.write(b"r source!")
print(connection.read(1000)) # try and read 1000 bytes or until timeout ocurres(1 sec)
# if you knew what the terminal character the device sends is you could just readuntil that character

Errors in the data received through serial using Python

I want to send data to a peripheral using PySerial. However, errors sometime appear in the data received.
import serial
dongle = serial.Serial("/dev/ttyUSB0", 9600)
dongle.write("Some data\n")
And then, Some data\n is transmitted to the peripheral.
Sometime it works great, but sometime, errors appear in the data received: Somata\n, Som a\n, etc…
How to fix that issue?
I suspect you need to add an inter-char delay to your serial write. Unfortunately, such a thing is not available in PySerial. There is an inter_byte_timeout, but that's for reads.
Something like:
import serial
import time
def write_with_delay(command):
while len(command)>0: # Loop till all of string has been sent
char_to_tx = command[0] # Get a
dongle.write(char_to_tx)
command = command[1:] # Remove sent character
time.sleep(0.01)
dongle = serial.Serial("/dev/ttyUSB0", 9600)
write_with_delay('Some data\n')
Which will send the string with a 10ms (0.01s) delay between each character. Ordinarily, adding arbitrary delays into code is a bad thing, but for serial comms it is sometimes necessary.

Reading a Serial Port with Python. How does the buffers work?

I am just wondering how the buffers work on a com port.. The code below is a snip of how I am reading a com port. I am wondering if by doing serial_connection.close() and serial_connection.open() I would be losing any data, or would it remain in the buffer? You might ask why I am closing and opening the comport.. The reason being is that it is actually a virtual port and for what ever reason when I stay connected to it for a length of time data stops transmitting...
import serial
serial_connection = serial.Serial(
port = self.SERIAL_PORT,
baudrate = self.BAUD_RATE,
timeout = 10
)
while true:
serial_connection.close()
serial_connection.open()
line = serial_connection.readline()
print line
PySerial has a separate thread that sits there listening for data to make sure that nothing gets lost. However, the OS itself does not buffer data. There is a slim chance that you could lose some data for the brief period of time between when you close the port and open it again.

Categories