I'm trying to create a program in python that reads the serial port, then decode the info received (which in this case is GPS coordinates and an ultrasonic sensor), then I need to create some 'if loops' to save this serial data into variables, but it seems to me that my if statement is not well, below I attach the code:
import serial
Ard = serial.Serial(port='COM5', baudrate=9600,
bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=2)
try:
Ard.isOpen()
print("Conexion con el puerto serial: COM5, establecida satisfactoriamente!\n")
except:
print("Error")
exit()
if (Ard.isOpen()):
try:
while (1):
aux = Ard.readline()
a = aux.decode('utf-8')
print(a)
if a == '1':
print("It works")
lat = float(a)
except Exception:
print("It doesn't work")
else:
print("Port is not opening")
I tried not using UTF-8, but using a = float(Ard.readline()), it was working (at least printing serial variables as float), but now it doesn't and it never enters the if loop, I tried if a != 1, and it works, so the thing is that I don't know the decoding or type of variable a is and I need it to be float. I'm reading from an arduino UNO, and I'm using pycharm as python IDE with pyserial, and 3.7 interpreter, please help me.
Related
I am trying to write a very basic script which will allow me to have full control over a device via serial. I can send data (and I know the device receives it, leaving screen open on the device allows me to see the input appearing).
But I cannot receive data, with screen open, and inputting data via screen I get the error:
Traceback (most recent call last): File "serialRec.py", line 4, in
for line in ser: File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 456, in
read
raise SerialException('device reports readiness to read but returned no data (device disconnected?)')
serial.serialutil.SerialException: device reports readiness to read
but returned no data (device disconnected?)
There is no error if I open the port waiting for a message without screen.
My application as I said sends data no problem... What can I do? How can I get this reading? I am running this script on a Ubuntu 12.04 installation... Screen works fine on the device the Ubuntu laptop is attatched to
The sys arguments are: argv[1] = device (/dev/ttyUSB0) and argv[2] = braud rate (e.g. 9600).
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
scom = raw_input("type away:" )
incli = str(scom)
time.sleep(.2)
if (incli == "exit the app"):
print ("Exiting the data send, nothing was sent from the exit command")
else:
while True:
print ser.readline()
enterdata()
print ("Welcome to the serial CLI")
enterdata()
UPDATE:
I now have it working, but limited and ugly it prints the return on multiple lines from sending one command. Though for this I am going to try a few things out. I will post and share some nice working code once i get it to a good place.
import serial
import sys
import time
def enterdata():
ser = serial.Serial(sys.argv[1], sys.argv[2])
scom = raw_input()
incli = str(scom)
if (incli == "exit the app"):
print ("Exiting the data send, nothing was sent from the exit command")
else:
ser.write(incli+"\r\n")
time.sleep(0.5)
while True:
data = ser.read(ser.inWaiting())
if (len(data) > 0):
for i in range(len(data)):
sys.stdout.write(data[i])
break
ser.close()
enterdata()
print ("Welcome to the serial CLI, hit enter to activate:")
enterdata()
This is the changes I have made, it works. Though it seems to always print double or maybe send an extra character
You might want to try with a listener first, but you have to make sure that your device is sending data to your serial port at the correct baudrate.
import serial, sys
port = your_port_name
baudrate = 9600
ser = serial.Serial(port,baudrate,timeout=0.001)
while True:
data = ser.read(1)
data+= ser.read(ser.inWaiting())
sys.stdout.write(data)
sys.stdout.flush()
I am trying to talk to a Stanford Research Systems SR760 spectrum analyzer on my mac (10.7.5) via Serial, using a Serial-to-USB adapter to connect to my laptop. I am using the Prolific USB-serial driver. Not sure which but I installed it recently. It probably is the PL2303 one.
Using Python, here's some sample code
import time
import serial
# configure the serial connections (the parameters differs on the device you
# are connecting to)
ser = serial.Serial(
port='/dev/cu.PL2303-0000201A',
baudrate=19200,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE,
rtscts=0,
dsrdtr=0,
timeout=2,
)
if ser.isOpen():
ser.flushInput()
ser.flushOutput()
print """Enter your commands below.\r\nInsert "exit" to leave the
application."""
while 1:
# get keyboard input
input = raw_input(">> ")
if input == 'exit':
ser.close()
exit()
else:
ser.write(input + '\r')
out = ''
# let's wait one second before reading output (let's give device
# time to answer)
lines = 0
while 1:
time.sleep(1)
out = out + ser.readline()
lines = lines + 1
if lines > 5:
break
print "read data: " + out
Using the SR760's manual, I send it: *IDN?, a basic "identify" command. I expect for something to pop up in my terminal, nothing does. It just times out. However, if I look at the send queue on the SR760, it will show the identity string, and in fact responds to a bunch of different commands. I'm just not getting anything on my computer and that is the problem. I know it is supposed to work that way because my colleague wrote code that words on his computer (a windows laptop).
How do I even start debugging this? I've tweaked the timeout, and confirmed the sr760 had the same parameters I was expecting.
I'm trying to write a function which continuously reads serial input. The function must be able to handle unexpected disconnections from the serial port and reconnect when possible. Despite reading several question posts on stackOverflow and looking through the pySerial documentation, I have yet to find a solution.
Here's my code:
def serialRead(serialPort, queue):
"""Adds serial port input to a queue."""
ser = serial.Serial(serialPort - 1, timeout = 2)
ser.parity = "O"
ser.bytesize = 7
while(True):
try:
if(ser == None):
ser = serial.Serial(serialPort - 1, timeout = 2)
ser.parity = "O"
ser.bytesize = 7
print("Reconnecting")
queue.put(ser.read(27))
ser.write(chr(6).encode())
print("Writing Data...")
except:
if(not(ser == None)):
ser.close()
ser = None
print("Disconnecting")
print("No Connection")
time.sleep(2)
Here's my output:
Enter a Serial Port: 7
Writing Data...
Writing Data...
Writing Data...
Writing Data...
I start with my device connected. After leaving the program run, neither "Disconnecting" or "No Connection" display and the program stops (it doesn't crash).
This code works. Batman tested the program on an Arduino connection and I found that my program had successfully reconnected with the device after a period of time. I hope this code will be useful for those struggling with something similar.
I did not find a reasonable good example of how to talk to a serial modem using pyserial. I have created a code snippet that should do the following, given an instantiated pyserial object ser:
Send an AT command to the modem
Return the modem answer as quickly as possible
Return e.g. None in the case of a timeout
Handle the communication between the script and the modem most reasonable, robust and easy.
Here is the snippet:
def send(cmd, timeout=2):
# flush all output data
ser.flushOutput()
# initialize the timer for timeout
t0 = time.time()
dt = 0
# send the command to the serial port
ser.write(cmd+'\r')
# wait until answer within the alotted time
while ser.inWaiting()==0 and time.time()-t0<timeout:
pass
n = ser.inWaiting()
if n>0:
return ser.read(n)
else:
return None
My question: Is this good, robust code, or can pieces be changed/simplified? I especially do not like the read(n) method, I would expect pyserial to offer a piece of code that just returns the whole buffer content. Also, do I / should I flush the output at the begin, to avoid having some crap in the output buffer before?
Thanks
Alex
Create the Serial object with the param timeout=2 for read timeout.
Mi recipe is:
def send(data):
try:
ser.write(data)
except Exception as e:
print "Couldn't send data to serial port: %s" % str(e)
else:
try:
data = ser.read(1)
except Exception as e:
print "Couldn't read data from serial port: %s" % str(e)
else:
if data: # If data = None, timeout occurr
n = ser.inWaiting()
if n > 0: data += ser.read(n)
return data
I think that this is a good form of manage the communications with the serial port.
I'm trying to read numerical values sent over a bluetooth modem from a serial port using Pyserial. I'm a beginner at Python, and found a good example that I'm trying to make use of.
from threading import Thread
import time
import serial
last_received = ''
def receiving(ser):
global last_received
buffer = ''
while True:
buffer = buffer + ser.read(ser.inWaiting())
if '\n' in buffer:
lines = buffer.split('\n') # Guaranteed to have at least 2 entries
last_received = lines[-2]
#If the modem sends lots of empty lines, you'll lose the
#last filled line, so you could make the above statement conditional
#like so: if lines[-2]: last_received = lines[-2]
buffer = lines[-1]
class SerialData(object):
def __init__(self, init=50):
try:
self.ser = ser = serial.Serial(
port='/dev/tty.FireFly-16CB-SPP',
baudrate=115200,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
except serial.serialutil.SerialException:
#no serial connection
self.ser = None
else:
Thread(target=receiving, args=(self.ser,)).start()
def next(self):
if not self.ser:
return 140 #return anything so we can test when Arduino isn't connected
#return a float value or try a few times until we get one
for i in range(40):
raw_line = last_received
try:
return float(raw_line.strip())
except ValueError:
print 'bogus data',raw_line
time.sleep(.005)
return 0.
def __del__(self):
if self.ser:
self.ser.close()
if __name__=='__main__':
s = SerialData()
for i in range(500):
time.sleep(.015)
print s.next()
I can open the port in another program, and can send/receive data from it. However, the code above doesn't seem to open the port, and just repeats "100" to the terminal window 500 times, but I don't know where it comes from or why the port doesn't open correctly. There isn't a delay from opening the port as it is on the other program, so I don't even know if it attempts to open.
I don't know what else to try, or where the error is so I'm asking for help. What am I doing wrong?
except serial.serialutil.SerialException:
You're catching and silencing errors in connecting. Comment out this block, and see if it produces an error message.