Python PySerial changing settings on timeout - python

I have a question about Python and PySerial.
On my Raspberry Pi i want to read a serial port from a device. I got 2 types of devices i want to read from. They both got different settings:
ser = serial.Serial()
ser.baudrate = 9600
ser.bytesize=serial.SEVENBITS
ser.parity=serial.PARITY_EVEN
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=0
ser.rtscts=0
ser.timeout=20
ser.port="/dev/ttyUSB0
and:
ser = serial.Serial()
ser.baudrate = 115200
ser.bytesize=serial.EIGHTBITS
ser.parity=serial.PARITY_NONE
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=1
ser.rtscts=0
ser.timeout=20
ser.port="/dev/ttyUSB0
This is the code to read the serial port:
try:
ser.open()
except:
sys.exit ("Error opening %s." % ser.name)
t_count = 0
while t_count < 20:
t_line = ''
try:
t_raw = ser.readline()
except serial.SerialException:
sys.exit ("Serial port %s could not be read." % ser.name )
t_str = str(t_raw)
t_line = t_str.strip()
print (t_line)
t_count += 1
try:
ser.close()
except:
sys.exit ("Oops %s. Program aborted. Could not close serial port." % ser.name )
So when i connect to a device with 115200 but the device runs 9600, i get timeouts ofcourse. But in my program it will just time out twenty times (times the for loop will run), and no exception to be thrown. Not even just before the program exits after looping 20 times. No error message nothing.
What i want to achieve is the following, i want to make the python script self detecting what he is connected to. When the readline() times out 20 times it should change settings. (by running another function or something).
I cant check if the readline returns something empty, because there are empty lines in the serial message.
Is there any way to get the right exception? Or any other smart way to solve this?
(By the way, i am sure the settings work. As i tested them both and run fine.)
Thanks in advance.
Cheers!

Easiest way would be to create a handshake function,
send something with one serial handler that you know the device will respond to correctly. If the answer is jibberish then change the handler and try the other one until you succceed.

Related

Communicate with a terminal using pySerial

I have a terminal which I connect to with serial communication, and I want to read from it and write to it some commands I prepared in advance in a string array
Using pySerial, I need to write a code that will read the lines with a stop condition which is a wait from the console for input from the user, and then write the commands from the array
Just want to clarify, it's like an automatic PuTTY, and no I can't connect to the terminal through ssh, and no I can't bood the machine's terminal since it's not a pc
here is what i tried:
import serial
Baud_Rate = 9600
Ser = serial.Serial('COM4', Baud_Rate)
while Ser.isOpen():
input('Error: Ser is already open, please close it manually. if the port is
closed, press enter\n')
try:
Ser.close()
except serial.serialutil.PortNotOpenError:
pass
Ser.open()
Serial_com = [] #a str array with the relevant commands
for i in range(len(Serial_com)):
ter = Ser.readline()
while ter != 0xaf:
#print(str(ter))
print(str(ter.decode('utf-8').rstrip('\r\n')))
ter = Ser.readline()
sleep(1)
if i == 0:
print('login: root')
Ser.write(bytes("root", encoding='utf-8'))
else:
print('\n\n\n\n\nroot # Ser: ~ # ' + str(Serial_com[i]))
Ser.write(bytes(Serial_com[i], encoding='utf8'))
I realized that once the serial port is waiting for the python code (or the user) to write commands, that it sends the character 0xaf. It might be a coincidence, but still I wrote that as a stop condition for the reading from the terminal
the code can read from the serial port, but once it needs to write to the serial port it won't proceed
I can't share the rest because it's confedencial for a project

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)

pySerial: port only works the first I use it after I power it on

I have trouble reading an arbitrary port with pySerial. I can only read the port when the port hasn't been used by any program after it's turned on. Otherwise, I can open the port but ser.inWaiting() returns 0, telling me there is no data in the port buffer. Actually, I can see data in a port monitor, so why does pySerial gets no data? I am using os x 10.9.5., python 2.7.8 and pySerial 2.7
Here is the code:
def usb():
ser = serial.Serial('/dev/tty.usbmodem422651', 115200)
try:
while True:
print ser.read(1000)
except KeyboardInterrupt:
ser.close()
exit
if __name__ == "__main__":
testUSB()
Thank you for your help!
You need to understand how serial works.
If you already opened some terminal and read the data, then it's the input buffer of the serial port is now empty.
while True:
print ser.read(1000)
It's not a good practice, you can try the following using inWating:
if ser.inWaiting:
ser.read(len(ser.inWaiting()))
You cannot open the port from 2 different apps or software.
A good code will look like:
import serial
def my_usb():
s_handle = serial.Serial('/dev/tty.usbmodem422651', 115200)
# or any other end condition
while True:
try:
if s_handle.inWaiting():
print s_handle.read(s_handle.inWaiting())
except KeyboardInterrupt:
print "exiting...."
finally:
s_handle.close()
if __name__ == "__main__":
my_usb()

Can't receive reply using PySerial but hyperterminal works

I have a device (Pololu Wixel) that I'm trying to communicate with using a serial connection over USB. Hyperterminal works fine but I'm trying to use Python for more flexibility. I can send commands to the device, but when I try to receive all I get is the command I just sent. However, if I open Hyperterminal, I'll receive the reply there to the command sent from the script. My code is below. I'm at a bit of a loss and it seems like this should be fairly straightforward. I appreciate any help.
import serial
import time
'''
Go through 256 COM ports and try to open them.
'ser' will be the highest port number. Fix this later.
'''
for i in range(256):
currentPort = "COM" + str(i+1)
try:
ser = serial.Serial(currentPort,baudrate=115200,timeout=5)
print("Success!!")
print(ser.name)
except:
pass
print(ser.isOpen())
str = "batt" #Command to request battery levels.
ser.write(str.encode())
x = ser.inWaiting()
print(x)
while ser.inWaiting() > 0:
out = ser.readline()
print(out.decode())
Add a break after finding an active port,
Try passing a different eol value to readline(), "\r" or "\r\n".

Raspberry Pi is stuck when no char is received on the serial port

I am using an XBee module connected to my RPI, serial communication is established between both, the problem is my code gets stuck if there is no data present by the XBee, is there a away to solve this, I tried timeout but wasn't successful.
code:
ser = serial.Serial (
port = "/dev/ttyAMAO",
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = serial,STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 0
)
ser = serial.Serial("/dev/ttyAMAO")
for c in ser.read():
l.append(c)
ser.read()
is a blocking call it is probably better to check if there is anything there to read first
if ser.inWaiting(): #only true if there is data waiting to be read
for c in ser.read():
....
or if you want your serial thread to run in parallel to your main program (ie. dont block user interface ever at all..) you should maybe look into something like twisted or asyncio
although typically with serial you are working with some device that wants 2-way communication, usually initiated with a query to the serial device, and you do want to actually block until you get a response. I will usually make a class to handle this for me
class MySerial:
def __init__(self,port,baudrate):
self.ser = serial.Serial(port,baudrate)
def query(cmd,terminal_char="\r"):
self.ser.write(cmd)
return ''.join(iter(ser.read,terminal_char))
s = MySerial("COM9",11200)
result = s.query("get -temp\r")
print result
this will accumulate an entire response until the specified terminal character is recieved

Categories

Resources