Communicate an Arduino with python - python

I am trying to communicate an Arduino using python. I was able to connect it using the serial module. This is the code:
import serial
while True:
print "Opening port"
arduinoData = serial.Serial("com7", 9600)
print "The port is open"
while (arduinoData.inWaiting()==0): #I wait for data
print "There is no data"
print "Reading data"
arduinoString = arduinoData.readline()
print arduinoString
It seems that is hanging when I want to read the data, in the line that says arduinoString = arduino.readline().
What could be the problem?

instead using the while loop inside of the main while loop you can use an if else statement. Also, to read the data you can use the read function with arduinoData.inWaiting() as the paramater like this : arduinoData.read(arduinoData.inWaiting()). I hope this code will help you:
arduinoData = serial.Serial("com7", 9600)
while True:
if arduinoData.inWaiting() > 0: # check if there is data available
print "Reading data"
arduinoString = arduinoData.read(arduinoData.inWaiting()) '''read and decode data'''
print arduinoString
else:
print "There is no data"

The structure of your code is strange. I had a similar issue by creating the Serial object in a function without making it global. Maybe you should put this line outside the loop :
arduinoData = serial.Serial("com7", 9600)
Also, your initialization seems a bit light. I usually use more parameters but it depends of your hardware.
ser = serial.Serial(
port = 'com4', \
baudrate = 19200, \
parity=serial.PARITY_NONE, \
stopbits=serial.STOPBITS_ONE, \
bytesize = serial.EIGHTBITS, \
timeout = 0.25)
A workaround for your readline() issue coud be using the read() function instead and checking if it contains data.
Hope it will help !

Alright, you are getting the AttributeError: 'Serial' object has no attribute 'ser' error because in reality ser does not exist in the arduinoData object. It's my fault because I was thinking of the class that I created in my program containing ser which is just the another serial object. To fix this just replace arduinoData.ser with arduinoData
To add on, you should probably declare arduinoData outside of the while loop. you should do this because every time the you create a serial object it takes time to connect to the Arduino. For this, your program might not be able to read the data.
I hope this answer will help you.

Related

How to use pyserial with a device connected with a USB port?

I am currently trying to use pyserial to read the values from my handheld tachometer, the specific model is the DT-2100.
I am using python 3 and my current code looks like this:
# Imports
import serial
import time
import io
# Coding section
# Setting Parameters
port = "COM3"
baud = 38400
data = []
info = 0
# Setting the port location, baudrate, and timeout value
ser = serial.Serial(port, baud, timeout=2)
# Ensuring that the port is open
if ser.isOpen():
print(ser.name + ' is open...')
# trying to read a single value from the display
#input("Ensure that the DT-2100 is turned on...")
info = ser.write(b'CSD')
ser.write(b'CSD')
info_real = ser.readlines()
print()
print("The current value on the screen is: ", info)
print()
print("The real value on the screen is: ", info_real)
This is what I get back after running the code:
COM3 is open...
The current value on the screen is: 3
The real value on the screen is: []
Process finished with exit code 0
The main issue is that I should be getting the value that is displayed by the tachometer, which for this test was 0, but between my two attempted methods I got 3 and nothing.
Any help is greatly appreciated.
The zip file you linked to contained an xls file which seemed to detail all the commands.
All the commands seem to be wrapped in: <STX> cmd <CR>, so you are missing those.
The CSD command would need to be like this: ser.write(b'\x02CSD\r')
Similarly the reply is also wrapped in the same way and you would need to remove those bytes and interpret the rest.

"write_timeout" not working in Serial() in pyserial

I am trying to make a program which constantly reads data being sent from device using serial port to computer. In addition to this whenever I enter something it is sent to device.(My main aim is to make a serial terminal emulator).
I wrote following program but it waits for any input and does not constantly read data and display on screen sent by device as thought:
ser1 = serial.Serial(com_name_to_use, auto_baud, timeout=0, write_timeout=0)
while True:
try:
# Writing Section
inp_str1 = input() # + "\n"
str1 = inp_str1.encode(encoding="ascii")
ser1.write(str1)
time.sleep(0.03)
# Reading Section
bf = ser1.readline()
print(str(bf, encoding="utf-8"), end="")
except Exception as err1:
pass
Kindly, tell how to fix it.

Python/Arduino Serial communication

We are trying to communicate from Python to our Arduino, but are encountering an issue when writing to the serial port from python
import serial
import time
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
time.sleep(2)
user_input = 'L'
while user_input != 'q':
user_input = input('H = on, L = off, q = quit' )
byte_command = user_input.encode()
print(byte_command)
ser.writelines(byte_command) # This line gives us the error.
time.sleep(0.5) # wait 0.5 seconds
print('q entered. Exiting the program')
ser.close()
The following is the error that we receive:
return len(data)
TypeError: object of type 'int' has no len()
Your code works on my computer. I think the function you're trying to use (writelines) was added not that long ago to pyserial so maybe you are running on an outdated version.
In any case, as far as I know, writelines is inherited from the file handling class and you don't really need to use it for what you're trying to do. Actually I don't think it's even well documented
Just change it to:
ser.write(byte_command)
If you prefer you can see what version of pyserial you have and/or update.
To check your version run: pip3 list | grep serial
If you don't have version 3.4 you can update with: pip3 install pyserial --upgrade
Considering how writelines works for files (see, for instance here) your error might actually be related to the core Python you have (for your reference I'm running Python 3.7.3).
writelines accepts a list of strings so you can't use it to send a single string. Instead use write:
import serial
import time
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
time.sleep(2)
user_input = 'L'
while user_input != 'q':
user_input = input('H = on, L = off, q = quit')
byte_command = user_input.encode()
print(byte_command)
ser.write(byte_command) # This line gives us the error.
time.sleep(0.5) # wait 0.5 seconds
print('q entered. Exiting the program')
ser.close()

Retry urllib request on exception

I have a very small and simple python script on my raspberry, it works well for as long as there is an active Wi-Fi connection. The raspberry is connected to a mobile hotspot and it's possible it will lose it's connection as it could get out of range. As soon as this happens it throws an exception and ends the request "while" loop.
I was hoping to get more information to how i can make this script pause or "ignore" the exception so it goes back into the loop as soon as the connection is restored.
import urllib
import serial
from time import sleep
link = "http://myurl/"
while True:
f = urllib.urlopen(link)
myfile = f.read()
print myfile
ser = serial.Serial('/dev/ttyUSB0', 9600)
ser.write(myfile)
sleep(3)
You can try something called, (obviously) a try statement!
Within your while loop, you can use a try: except block to make sure that even if your code does't execute (your pi loses connection or something else weird happens) you won't end the program!
This type of code would look like this:
import urllib
import serial
from time import sleep
link = "http://myurl/"
while True:
try:
f = urllib.urlopen(link)
myfile = f.read()
print myfile
ser = serial.Serial('/dev/ttyUSB0', 9600)
ser.write(myfile)
sleep(3)
except:
sleep(3) #If the code executed in the try part fails, then your program will simply sleep off 3 seconds before trying again!

Jumbled out put of RFID Tags

I am working on a project, in which I have to interface multiple RFID Readers (I'm Using EM 18, With Serial out) with Raspberry Pi. I'm using an USB to TTL Converter to connect EM 18 to Raspberry Pi. I've connected two RFID Readers using USB to TTL Adapter.
This is my code for one station
Code
import serial, time
while True:
try:
print 'station one Is Ready!! Please Show your Card'
card_dataa = serial.Serial('/dev/ttyUSB0', 9600).read(12)
print card_dataa
continue
except serial.SerialException:
print 'Station 1 is Down'
break
My Issues are
I would like to get the readings from both the RFID Readers in the same program simultaneously.
I've two Programs with the above code, station1.py and station2.py.
Station1.py is for USB0 and Station2.py is for USB1.
I am executing the programs in different Terminal simultaneously.
For example station1.py in terminal 1 and station2.py in terminal 2. The program executes fine, but the readings are jumbled. For example, 6E0009D2CC79 and 4E0070792760 are the tag id's that i'm using for testing. if I'm executing only one program i'm getting the reading properly, but if I'm executing both programs simultaneously in two terminals I'm getting the tag Id's jumbled.
I want to combine both the readings in the same program.
Thanks in Advance
I'd recommend create a new Serial object once and reading multiple times, as needed:
import serial, time
try:
station1 = serial.Serial('/dev/ttyUSB0', 9600)
print 'station one Is Ready!! Please Show your Card'
except serial.SerialException:
print 'Station 1 is Down'
while True:
card_dataa = station1.read(12)
print card_dataa
Optionally you can set a timeout of 0:
import serial, time
try:
station1 = serial.Serial('/dev/ttyUSB0', 9600,timeout=0)
print 'station one Is Ready!! Please Show your Card'
except serial.SerialException:
print 'Station 1 is Down'
while True:
card_dataa = station1.read(12)
if len(card_dataa) > 0: print card_dataa
You should also easily be able to open 2 serial connections in the same program:
import serial, time
station1 = None
station2 = None
try:
station1 = serial.Serial('/dev/ttyUSB0', 9600,timeout=0)
print 'station 1 Is Ready!! Please Show your Card'
except Exception,e:
print 'Station 1 is Down',e
try:
station2 = serial.Serial('/dev/ttyUSB1', 9600,timeout=0)
print 'station 2 Is Ready!! Please Show your Card'
except Exception,e:
print 'Station 2 is Down',e
while True:
if station1 != None:
card_dataa1 = station1.read(12)
if len(card_dataa1) > 0: print card_dataa1
if station2 != None:
card_dataa2 = station2.read(12)
if len(card_dataa2) > 0: print card_dataa2
This means the 2nd reader would wait for the 1st reader to finish before printing, which is why fingaz recommended threading.
Here's a basic commented proof of concept for threading:
import threading,time,serial
#subclass threading.Thread
class RFIDSerialThread(threading.Thread):
SLEEP_TIME = 0.001 #setup sleep time (update speed)
#constructor with 3 parameters: serial port, baud and a label for this reader so it's easy to spot
def __init__(self,port,baud,name):
threading.Thread.__init__(self) #initialize this instance as a thread
self.isAlive = False #keep track if the thread needs to run(is setup and able to go) or not
self.name = name #potentially handy for debugging
self.data = "" #a placeholder for the data read via serial
self.station = None #the serial object property/variable
try:
self.station = serial.Serial(port,baud,timeout=0) #attempt to initialize serial
self.isAlive = True #and flag the thread as running
except Exception,e:
print name + " is Down",e #in case of errors print the message, including the station/serial port
def run(self): #this gets executed when the thread is started
while self.isAlive:
if self.station != None: self.data = self.station.read(12) #read serial data
time.sleep(RFIDSerialThread.SLEEP_TIME)
if __name__ == '__main__':
#initialize the two readers
station1 = RFIDSerialThread('/dev/ttyUSB0',9600,"station #1")
station2 = RFIDSerialThread('/dev/ttyUSB1',9600,"station #2")
#start the threads
station1.start()
station2.start()
while True:#continously print the data (if any)
if len(station1.data) > 0: print station1.name,station1.data
if len(station2.data) > 0: print station2.name,station2.data
Note that I haven't attached actual hardware to test, so this may not work as is, but should provide enough info to progress.
I would also suggest trying to physically distance the readers. Depending on the readers and their capabilities they may be interfering witch each other which might result in faulty data. In case you still have issues with jumbled data, I'd try to figure out where the problem is by taking some assumptions out.(e.g. is the issue a hardware (readers interfering, broken reader, loose USB connector, etc.) or software(serial port not properly initialized/flushed/etc.), taking one thing out at a time)
To have a concurrent flow, you can use the threading module. Here's a link to the documentation:
https://docs.python.org/2/library/threading.html

Categories

Resources