PySerial FileNotFoundError - python

I'm trying to use PySerial to accept inputs from an RFID Reader. As per the answers here: I've tried using WinObj and found something odd: there is no COM3 port in the GLOBAL??? folder pointing to something "more driver specific." However, when I run the command python -m serial.tools.list_ports, it does throw up COM3. When I try a simple program like:
import serial
ser = serial.Serial()
ser.port = 2
print(ser)
ser.open()
I get the following output:
Serial<id=0x45e8198, open=False>(port='COM3', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
serial.serialutil.SerialException: could not open port 'COM3': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)
So, I know that PySerial is looking for my reader in the right place, and, according to two different sources (the device manager and the command line), the device is registering. And yet I'm still getting this error. What is going on? I'm using Python 3.3 on Windows 8.1.
EDIT: That error is actually what I get from python's command line. The one I get from making and running a program like the one above is:
AttributeError: 'function' object has no attribute 'Serial.'
I'd appreciate thoughts on that too.

First thing I would check is what you have for com ports attached and what's currently in use:
import serial.tools.list_ports
import sys
list = serial.tools.list_ports.comports()
connected = []
for element in list:
connected.append(element.device)
print("Connected COM ports: " + str(connected))
# compliments of https://stackoverflow.com/questions/12090503/listing-available-com-ports-with-python#14224477
""" Lists serial port names
:raises EnvironmentError:
On unsupported or unknown platforms
:returns:
A list of the serial ports available on the system
"""
if sys.platform.startswith('win'):
# !attention assumes pyserial 3.x
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
print("Availible COM Ports: " + str(result))
Then, make sure you are calling the serial port constructor with the parameters you want:
ser = serial.Serial(
port="com2", # assumes pyserial 3.x, for 2.x use integer values
baudrate=19200,
bytesize=8,
parity="E", # options are: {N,E,O,S,M}
stopbits=1,
timeout=0.05)
When you call "serial.Serial()" without any parameters and then add the port ID, I'm not entirely sure what it's going to do, I've always explicitly referenced the port I want to use there.

Your issue lies in the fact that the serial object is looking for a string "COMXX" or else it won't work. I don't know if it need to be capitalized or not.
make sure you configure it like this.
serial.Serial(port = "COM2")

Related

Python Serial Communication script issues (in Visual Studio)

I'm currently trying to set up communication between an Arduino UNO and a PC via a serial/USB connection using Python on a Windows PC.
The goal is to start a video on a laptop when the Arduino tells it to.
I found a guide online which lead me to the code below but Visual Studio 2017 is just showing errors seemingly at random everywhere. A lot of it seemed to come from the imports and VS's IntelliSense messing up (which I believe is fixed now).
So currently when I'm running the program it's getting stuck at the ser = serial.Serial(port, 9600, timerout=0) Line with the error that "name 'port' is not defined" Any idea why that is happening?
I'm unsure if that is the core issue since every time I'm making changes a lot of "unexpected token" and "indent" errors appear for port, newline, print and ser (completely at random)
import serial, os, time, serial.tools.list_ports
cmd = '"C:\\Users\\Josef\\Desktop\\PYTHON_PlayVideo\\PYTHON_PlayVideo\\Video1.mp4" -f --fullscreen --play-and-exit'
for p in serial.tools.list_ports.comports():
sp = str(p)
#if (sp.find('COM5') != -1):
if (sp.find('Arduino') != -1):
flds = sp.split()
port = flds[0]
print(port)
ser = serial.Serial(port, 9600, timeout=0)
while 1:
try:
line = ser.readline()
if (line):
print (cmd)
os.system(cmd)
except:
pass
time.sleep(1)
It seems that you donĀ“t find any COM port, so port is never defined.
I rework your code and this version works for me (replace USB with your keyword).
import serial, os, time, serial.tools.list_ports
# Get the COM port
Ports = serial.tools.list_ports.comports()
if(len(Ports) == 0):
print("[ERROR] No COM ports found!")
exit()
TargetPort = None
for Port in Ports:
StringPort = str(Port)
print("[INFO] Port: {}".format(StringPort))
if("USB" in StringPort):
TargetPort = StringPort.split(" ")[0]
print("[INFO] Use {}...".format(TargetPort))
if(TargetPort is None):
print("[ERROR] No target COM port found!")
exit()
# Open the COM port
ser = serial.Serial(TargetPort, 9600, timeout = 0)
if(ser.isOpen() == False):
ser.open()
while(True):
try:
line = ser.readline()
if (line):
print (cmd)
#os.system(cmd)
except:
pass
time.sleep(1)

pySerial serial.open() works in interactive shell but raises exception as a script

EDIT: It seems like the issue might have to do with Python 3. I tried executing the script in a Anaconda Environment of Python 2.7.15 and was able to get it to work. Thinking it might be just Anaconda, I tried running it in a Anaconda Environment of Python 3.6.5 and ran into the same error. To remove the variable of Anaconda, I tried running Python 2.7.15 from a fresh install without Anaconda and was again able to get the script running properly. Note that my original problem came up when running through a non-Anaconda Python3 environment. I do not think this really answers the question but is somewhat of a solution for anyone running into the same issue.
Windows 10. Python 3.6.5
I am trying to establish/open a connection with a connected COM port through pyserial. I am able to do this just fine through a Python shell started in cmd, but receive an exception when running it through a script. The exception chain is this:
File "C:\Python\Python36-32\lib\site-packages\serial\serialwin32.py", line 62, in open
raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))
serial.serialutil.SerialException: could not open port 'COM8': OSError(22, 'Element not found.', None, 1168)
The script is this:
import serial.tools.list_ports
import time
import sys
SERIAL_CONNECTION_ATTEMPTS = 3
ports = list(serial.tools.list_ports.comports())
bluetoothPorts = []
for p in ports:
if 'Bluetooth' in p.description:
bluetoothPorts.append(p)
print("Found: ", p)
selectedPort = bluetoothPorts[0]
print("selected port: ", selectedPort.device)
ser = serial.Serial()
ser.baudrate = 9600
ser.timeout = 120
ser.port = selectedPort.device
for i in range(0, SERIAL_CONNECTION_ATTEMPTS):
try:
ser.open()
time.sleep(5)
if ser.is_open():
break
except:
print(sys.exc_info())
if i == SERIAL_CONNECTION_ATTEMPTS-1:
print("Failed to connect. Will stop trying now.")
exit()
print("Failed to connect. Retrying...")
ser.close()
time.sleep(5)
print(ser.read(32))
print("Closing out now..")
ser.close()
Successful connections using the interactive shell follow the script exactly, excluding the use of the try-except block.
One thing I have noticed is that the target device seems to recognize a connection attempt for a very brief moment. I am able to make this guess because the target device has an LED to indicate an established serial connection. When the script runs to the ser.open(), this LED flashes for a moment before quickly turning off. On the other hand, when ser.open() is attempted in the interactive shell, the shell blocks until the connection is made and the LED stays lit.
Please let me know if any additional information would help.
well you know Bluetooth, it doesn't work from the first attempt, just give it a try, one and two and three ...
def getSerialOrNone(port, conn_att):
connec_attempts = 0
ser = None
while ser is None:
try:
connec_attempts+=1
print('connect attempts to %s num %d' % (port , (connec_attempts)))
ser = serial.Serial(port, 9600,timeout=1.5, parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
if connec_attempts == conn_att:
print('Serial connection error',
'Failed to commect to port ', self.port )
return None
#time.sleep(2)
except Exception as e:
print('Serial connection error',
'Error sending message "%s" to controller:\n%s' %
(port, e))
return ser

detect the specific serial port which is conneced to FTDI chip

I'm working on a FTDI chip and want to connect this chip to the operating system Windows 10 via a serial port. I'm using this code below and the results show me the all visible ports what I don't want. what I need is to detect only the port which the chip is connected to and ignore the rest. for example Com 4, so I just want my program written in Python to detect Com4 ONLY.
I'm using Pyserial by the way.
I'm pretty thankful and grateful for your help in advance
def serial_ports():
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
print ports
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
# this excludes your current terminal "/dev/tty"
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
print ports
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result
Read about
serial.tools.list_ports
This module can be executed to get a list of ports (python -m serial.tools.list_ports).
It also contains the following functions.
serial.tools.list_ports.comports()
Returns: an iterable that yields ListPortInfo objects.
The function returns an iterable that yields tuples of three strings:
port name as it can be passed to serial.Serial or serial.serial_for_url()
description in human readable form
sort of hardware ID. E.g. may contain VID:PID of USB-serial adapters.

Pyserial: How to know if a serial port is free before open it

I use python with Pyserial to use the serial port, the code like this:
import serial
portName = 'COM5'
ser = serial.Serial(port=portName)
# Use the serial port...
But, the problem is, if the port is already open (by another application for example), I get an error when I try to open it like: "SerialException: could not open port 'COM5': WindowsError(5, 'Access is denied.')".
And I would like to know if I can open the port before trying to open it to avoid this error. I would like to use a kind of condition and open it only if I can:
import serial
portName = 'COM5'
if portIsUsable(portName):
ser = serial.Serial(port=portName)
# Use the serial port...
EDIT:
I have found a way to do it:
import serial
from serial import SerialException
portName = 'COM5'
try:
ser = serial.Serial(port=portName)
except SerialException:
print 'port already open'
# Use the serial port...
def portIsUsable(portName):
try:
ser = serial.Serial(port=portName)
return True
except:
return False
as mentioned in the comments watch out for race conditions under circumstances where you are opening and closing alot ...
also it might be better to just return the serial object or None
def getSerialOrNone(port):
try:
return serial.Serial(port)
except:
return None
[edit] I intentionally left the except as a catch-all, because I posit that the actual failure does not matter. as regardless of the error, that port is not usable ... since the function is testing the usability of a port, it does not matter why you get an exception it only matters that you got an exception.

How to check if device is connected Pyserial

I am connecting with my Arduino through a USB port and sending data to it by using PySerial module. At first I can check if the device is connected by using this code:
try:
ser = serial.Serial("COM3", 9600)
except serial.serialutil.SerialException:
print "Arduino not connected"
Now what I want to do is to check periodically if the Arduino is still connected to the computer. I tried ser.isOpen() but this returns true even if the Arduino is disconnected. I would also like to know how to reconnect the device. I mean once you disconnect the device the program can no longer send any data to Arduino.
Most of the answers propose 2 approaches:
In some point of the code, send some sort of message through serial to check if your device is still alive
Start a separate thread and continuously check if the device is alive by opening a communication
The problem with the first solution is that you are not always checking the connection, but only checking in some specific points: this solution isn't very elegant and if badly written could even be not working.
The second solution solves the problem of the first solution, but introduces a new problem: checking the connection, or worst sending a message, in a threaded loop will cause problem or may even interrupt the connection to the device from other functions.
A solution that allows you to constantly check the connection without monopolizing the communication involves the reading of the existing COM:
import serial.tools.list_ports
myports = [tuple(p) for p in list(serial.tools.list_ports.comports())]
print myports
output:
[(u'COM3', u'Arduino Due Programming Port (COM3)', u'some more data...'),
(u'COM6', u'USB Serial Port (COM6)', u'some more data...'),
(u'COM100', u'com0com - serial port emulator (COM100)', u'some more data...')]
then we save the tuple that contains our port:
arduino_port = [port for port in myports if 'COM3' in port ][0]
then we create a function that checks if this port is still present:
import time
def check_presence(correct_port, interval=0.1):
while True:
myports = [tuple(p) for p in list(serial.tools.list_ports.comports())]
if arduino_port not in myports:
print "Arduino has been disconnected!"
break
time.sleep(interval)
At last, we run this function as a daemon thread:
import threading
port_controller = threading.Thread(target=check_presence, args=(arduino_port, 0.1,))
port_controller.setDaemon(True)
port_controller.start()
in this way, you'll check each 0.1 secs if the arduino is still connected, and the thread will end when arduino is disconnected or all other activities have ended
You can set a timeout.
import serial
ser = serial
try:
ser = serial.Serial("COM3", 9600, timeout=10)
while ser.read():
print 'serial open'
print 'serial closed'
ser.close()
except serial.serialutil.SerialException:
print 'exception'
Unfortunately, the best way I can find to do this is to try some communication and see if it fails. A pretty safe way would be:
try:
ser.inWaiting()
except:
print "Lost connection!"
You'll probably still want to close the connection with a ser.close() after the connection is lost, although you may need to place that in a "try:except" block also.
import serial
import time
ser = serial.Serial()
ser.braudrate = 115200
ser.port = "/dev/ttyUSB0"
ser.open()
print(ser.name)
if ser.isOpen():
print("serial is open!")
ser.close()
For example to detect ttyUSB0:
import os
x=os.system("ls /dev/ttyUSB0")
if x==0:
print "connected"
else:
print "disconnected"
i suggest to use a python thread class to istantiate a serial connection, in the run methos put your while loop , set an var that you use for kill iy at the end, the second public var that you use for store data if have receive and load data in main method.. soon paste an example
class Arduino():
def __init__(self,Port='/dev/ttyUSB0',Boud=9600,connState=0):
self.parent=self
self.port=Port
self.boud=Boud
self.connState=connState
self.timeount=1
self.ser=None
self.connect()
def connect(self):
try:
self.ser=serial.Serial(self.port,self.boud,timeout=0.0001)
self.connState=1
return [1,'connect']
except:
self.connState=0
return [0,'no hardware found']
def loadData(self):
self.buffer=self.ser.read(1)
if (self.buffer!=''):
try:
print self.buffer
except Exception, e:
pass
ard=Arduino()
while True:
if ard.connState:
ard.loadData()
else:
print "Arduino not found"
break
and start with:
import threading
class ThController( threading.Thread ):
# Override Thread's __init__ method to accept the parameters needed:
def __init__( self,parent):
self.parent = parent
threading.Thread.__init__ ( self )
def run ( self ):
while self.parent.ctrlattive:
j=json.loads(data)
self.parent.data=j

Categories