Python: Writing to and Reading from serial port - python

I've read the documentation, but can't seem to find a straight answer on this.
I have a list of all COM Ports in use by Modems connected to the computer. From this list, I try to open it, send it a command, and if it says anything back, add it to another list. I'm not entirely sure I'm using pyserial's read and write functions properly.
i=0
for modem in PortList:
for port in modem:
try:
ser = serial.Serial(port, 9600, timeout=1)
ser.close()
ser.open()
ser.write("ati")
time.sleep(3)
print ser.read(64)
if ser.read(64) is not '':
print port
except serial.SerialException:
continue
i+=1
I'm not getting anything out of ser.read(). I'm always getting blank strings.

a piece of code who work with python to read rs232
just in case somedoby else need it
ser = serial.Serial('/dev/tty.usbserial', 9600, timeout=0.5)
ser.write('*99C\r\n')
time.sleep(0.1)
ser.close()

ser.read(64) should be ser.read(size=64); ser.read uses keyword arguments, not positional.
Also, you're reading from the port twice; what you probably want to do is this:
i=0
for modem in PortList:
for port in modem:
try:
ser = serial.Serial(port, 9600, timeout=1)
ser.close()
ser.open()
ser.write("ati")
time.sleep(3)
read_val = ser.read(size=64)
print read_val
if read_val is not '':
print port
except serial.SerialException:
continue
i+=1

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)

Sending ^C over PySerial

I'm writing an automated script to reset the password on a Cisco 1800 series router. In order to begin the reset process, you must enter the ROMMON by sending a break when the ROMMON is initialized. For the life of me, I cannot send a break over PySerial, no matter how hard I try. Here is the code I've been using:
import serial, time
effinByte = '\x03'
ser = serial.Serial('/dev/ttyS0', 9600, timeout=1.0, rtscts=False)
if(ser.isOpen() == False):
ser.open()
print("Opening port")
else:
print("Port already open")
isNotResetting = True
while isNotResetting == True:
print("Waiting for ROMMON")
theOutput = ser.readline()
if ("ROMMON" in theOutput):
ser.write(effingByte.encode('ascii'))
print ('Mr. Meeseeks find!')
while True:
print ser.readline()
Basically, it waits for the 'initializing ROMMON' line and tries to send a break.
sendBreak(self) is the answer. I'm so stupid!

A timeout is missing in XBee API Python library

I have a problem with this library:
https://code.google.com/p/python-xbee/
There is the xbee.wait_read_frame() function without a timeout.
I am testing all serial ports for a signal, but if i cannot timout a try there is no way to do it.
Is there a posibility in Python to upgrade this function without editing the library?
Or with small changes inside the library?
ports_available = []
for port in range(0,20):
try:
ser = serial.Serial(port, 9600)
ports_available.append(port)
ser.close()
except:
pass
print(ports_available)
for port in ports_available:
ser = serial.Serial(port, 9600)
bee = ZigBee(ser)
bee.at(command=b"MY")
print(bee.wait_read_frame()) #<----------
ser.close()
Looks like you need to use the asynchronous mode described on page 3 of the documentation. It might be tricky unless the data frame includes a parameter for the serial port that received it. If it doesn't, you won't be able to connect the data to port that received it.
import serial
import time
from xbee import XBee
serial_port = serial.Serial('/dev/ttyUSB0', 9600)
def print_data(data): """
This method is called whenever data is received
from the associated XBee device. Its first and
only argument is the data contained within the
frame.
"""
print data
xbee = XBee(serial_port, callback=print_data)
while True:
try:
time.sleep(0.001)
except KeyboardInterrupt:
break
xbee.halt()
serial_port.close()

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

Problem opening serial port with Pyserial

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.

Categories