Pyserial read empty b'' from COM port - python-3.x

I'm testing my COM port cuz I need to read streaming data from a radar board by python.
First, I wrote a arduino code like below figure.
It generate number continuously.
And wrote the pyserial:
import serial
import time, os
ser = serial.Serial('COM6', 9600, timeout=0, parity=serial.PARITY_ODD, rtscts=0)
if (ser.isOpen() == True):
print ("Port:",ser.port)
#input = input(">> ")
#input = b"p"
ser.write(b'1\n\r')
time.sleep(1)
numOfLines = 0
while 1:
#if (ser.inWaiting()>0):
response = ser.readline()
print (response)
numOfLines +=1
if numOfLines>10:
break
ser.close()
But I got the result:
If I run the arduino serial output window before I compile my python code, I will get the output correctly.(like b'193\n', b'194\n'...), or I'll get nothing.(b'').
Can someone tell me what's wrong with my processing?

Related

Reading result from radwag wtc2000 precision scales using usb returns empty bytes

I have to read the results monitored at the screen of the Radwag wtc2000 scale.
That's it. All I need is the get the results and print it on screen. But I only get empty (b'') bytes printed on the console.
Sorry for the bad English.
import serial
ser = serial.Serial(port='COM3', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, timeout=1)
try:
ser.isOpen()
print("Serial port is open")
except:
print("ERROR")
exit()
if (ser.isOpen()):
try:
while (True):
ser.write("S CR LF")
print(ser.read())
except:
print("error")
else:
print("Cannot open serial port")
I expect to get the weights of the pen that I used for testing. On the screen of scale, it says 4.71 on the scale but I get empty byte as (b'')

How to convert python-to-arduino over serial code to python3-to-arduino over serial code?

The code below used to work in spyder to communicate over serial with an arduino. In the console window of spyder, I would see lines of data being printed out:
78.7,77.9,100,80
78.7,77.9,100,80
78.7,77.9,100,80
78.7,77.9,100,80 ...
Data is from two temperature probes, a flowmeter, and the thermostat set temp.
I upgraded my Kubuntu 18.04 system to all things python3. Now, the code runs, but the spyder3 console window shows no visible characters, but scrolls blank lines. The rest of my python code for parsing and plotting this data doesn't work.
I've spent all day trying to fix this with no luck. I'm guessing it's a simple fix for someone with more experience than me.
The only difference between the old working code and the code below is that the print statements have parentheses added to remove the syntax error.
python
""" This code was originally copied from:
Listen to serial, return most recent numeric values
Lots of help from here:
http://stackoverflow.com/questions/1093598/pyserial-how-to-read-last-line-sent-from-serial-device
"""
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 Arduino 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 = serial.Serial(
port='/dev/ttyACM0',
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1,
xonxoff=0,
rtscts=0,
interCharTimeout=None
)
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 '81.3,78.1,10.0,60.0,0' #100 #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())
return str(raw_line.strip())
except ValueError:
print('bogus data',raw_line)
time.sleep(.005)
return 0.
def __del__(self):
if self.ser:
self.ser.close()
def write(self,val):
self.ser.write(val)
if __name__=='__main__':
s = SerialData()
for i in range(500):
time.sleep(.015)
print( s.next())
One of the most significant differences between Python 2.x and 3.x is the way text strings are encoded. For Python 3.x everything is Unicode, as compared to ASCII for 2.x, so you just need to decode the raw bytes you read from the serial port:
buffer = buffer + ser.read(ser.inWaiting()).decode('utf-8')
EDIT: now you seem to have a different problem involving an exception. It looks like your port is open, to be sure you can change the way you handle the exception when you instantiate the port:
except serial.serialutil.SerialException as e:
print(e)
self.ser = None
Once you know the error you should be able to handle it. Quite likely your port was not properly closed in an earlier session.
Bingo! That last suggestion fixed the program and the python GUI interface I wrote for it is working with these corrections.
python
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()).decode('utf-8')
if '\n' in buffer:
lines = buffer.split('\n') # Guaranteed to have at least 2 entries
last_received = lines[-2]
#If the Arduino 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 = serial.Serial(
port='/dev/ttyACM1',
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1,
xonxoff=0,
rtscts=0,
interCharTimeout=None
)
except serial.serialutil.SerialException as e:
print(e)
#no serial connection
self.ser = None
else:
Thread(target=receiving, args=(self.ser,)).start()
def next(self):
# if not self.ser:
# return '81.3,78.1,10.0,60.0,0' #100 #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())
return str(raw_line.strip())
except ValueError:
print('bogus data',raw_line)
time.sleep(.005)
return 0.
def __del__(self):
if self.ser:
self.ser.close()
def write(self,val):
self.ser.write(val)
if __name__=='__main__':
s = SerialData()
for i in range(500):
time.sleep(.015)
print (s.next())

How can I improve the pyusb reading speed?

I use python3.7 pyusb1.0.2 and libusb-win32-devel-filter-1.2.6.0 in windows 10.
My FPGA send data to my computer in 10MB/s through USB interface after it received 0x1111. It lasts ten seconds. I found my python program just can receive part of data, about 4MB.
Here is the code:
import usb.core
import usb.util
filename = r'E:\FlowFluorescence\1.mywork\experiment\data\201901290000.txt'
file = open(filename,'wb')
dev = usb.core.find(idVendor=0x04b4, idProduct=0x00f1)
if dev is None:
raise ValueError('Device not found')
dev.set_configuration()
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
data = b''
dev.write(0x02, b'\x11\x11')
while True:
try:
data = data + dev.read(0x86,512,100)
except usb.core.USBError:
break
file.write(data)
file.close()
How can I improve the pyusb reading speed? I need 10MB/s at least. Hoping for your answer.
I found this way is faster.
while True:
try:
#data = data + dev.read(0x86,512,100)
data = dev.read(0x86,512,100)
file.write(data)
except usb.core.USBError:
break
In this way, it read 28MB at last.

read MFRD522 data using raspberry pi and send this data by http(python3)

I'm working on a project and I want to use RFID as a position reference(when raspberry pi and MFRC522 read the data, send it to server and make sure where is the position or adjust position while RFID reader is fixed)
My code is below:
import RPi.GPIO as GPIO
import MFRC522
import signal
import socket
HOST = '192.168.11.48'
PORT = 9009
continue_reading = True
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
global continue_reading
print("Ctrl+C captured, ending read.")
continue_reading = False
GPIO.cleanup()
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)
# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()
# Welcome message
print("Welcome to the MFRC522 data read example")
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sock:
sock.connect((HOST,PORT))
#print("closing client")
while True:
while continue_reading:
# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# If a card is found
if status == MIFAREReader.MI_OK:
print("Card detected")
# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()
# If we have the UID, continue
if status == MIFAREReader.MI_OK:
# Print UID
print("Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))
# This is the default key for authentication
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
# Select the scanned tag
MIFAREReader.MFRC522_SelectTag(uid)
# Authenticate
status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)
data = "str(uid[0])"
msg = data
sock.sendall(msg.encode())
data = sock.recv(128)
print('date from Echo server is [%s]'%data.decode())
# Check if authenticated
if status == MIFAREReader.MI_OK:
MIFAREReader.MFRC522_Read(8)
MIFAREReader.MFRC522_StopCrypto1()
else:
print("Authentication error")
I am using echo server to make sure that it's working
code for echo server is:
import socketserver
HOST = ''
PORT = 9009
class MyTcpHandler(socketserver.BaseRequestHandler):
def handle(self):
print("[%s]conneted"%self.client_address[0])
try:
while True:
self.data = self.request.recv(1024)
if self.data.decode() == "/quit":
print('ended by user [%s]'%self.client_address[0])
return
print('[%s]'%self.data.decode())
self.request.sendall(self.data)
except Exceptions as e:
print(e)
def runServer():
print("starting echo server")
print("if you want to close echo server, click Ctrl+C")
try:
server = socketserver.TCPServer((HOST,PORT), MyTcpHandler)
server.serve_forever()
except KeyboardInterrupt:
print("--- closing server")
runServer()
I ran fist piece of code while the second one was running, but only result I got was -
Welcome to the MFRC522 data read example
Card detected
Card read UID:178,29,209,48
size:8.
Anyone had idea what I should change to make it work?
thanks

Pygame webcam streaming client can't execute with python 3.4

I'm using pygame and python3.4 for stream a webcam in a Odroid board. The server is this (extracted of this post: using pygame to stream over sockets in python error ):
import socket
import pygame
import pygame.camera
import sys
import time
port = 5000
pygame.init()
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(("",port))
serversocket.listen(1)
pygame.camera.init()
webcam = pygame.camera.Camera("/dev/video1",(320,240))
webcam.start()
while True:
connection, address = serversocket.accept()
image = webcam.get_image() # capture image
data = pygame.image.tostring(image,"RGB") # convert captured image to string, use RGB color scheme
connection.sendall(data)
time.sleep(0.1)
connection.close()
The server works Ok in python and python 3.4.
But when I execute the client with python 3.4 I get the following error:
Traceback (most recent call last):
File "client.py", line 30, in
image = pygame.image.fromstring(dataset,(320,240),"RGB") # convert received image from string
TypeError: must be bytes, not str
The client is the following:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import socket
import pygame
import sys
host = "192.168.45.103"
port=5000
screen = pygame.display.set_mode((320,240),0)
while True:
clientsocket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect((host, port))
received = []
# loop .recv, it returns empty string when done, then transmitted data is completely received
while True:
#print("esperando receber dado")
recvd_data = clientsocket.recv(230400)
if not recvd_data:
break
else:
received.append(recvd_data)
#dataset = ''.join(received)
dataset = ','.join(str(v) for v in received)
image = pygame.image.fromstring(dataset,(320,240),"RGB") # convert received image from string
screen.blit(image,(0,0)) # "show image" on the screen
pygame.display.update()
# check for quit events
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
I changed the line dataset = ''.join(received) for dataset = ','.join(str(v) for v in received) because I read somwhere that in python3.x it mst be this.
The error line now is: image = pygame.image.fromstring(dataset,(320,240),"RGB")
Thanks!
These 2 lines appear to be plain wrong:
dataset = ','.join(received)
image = pygame.image.fromstring(dataset,(320,240),"RGB") # convert received
If dataset is to contain the binary pxel data, you should not be concatenating the bytes you receive with ",": it would simply add a lost of extraneous "," (decimal 44) bytes as garbage in your pixel data - the previous line, using "join" with an empty string would work (in Python 2.x) becuase called upon an empty string, join simply concatenates the various piece of data, which is what you want.
In Python3, handling of binary data (such as the pixel data you are receiving) has been separated from text handling - and the '""' empty string you where using is an object representing empty text - which is different from empty bytes from Python 2.x - but you can simply prefix it with a b for denoting a bytes-string (which is what you want).
All in all, try just using:
dataset = b''.join(str(v) for v in received)
image = pygame.image.fromstring(dataset,(320,240),"RGB")

Resources