Active3 months ago
- Python Read Serial Data
- Python Serial Read Example
- Python Serial Read_until Example
- Python Pyserial Example
Feb 26, 2018 NOTE: I will be using a DHT11 temperature sensor to produce data on the Arduino end. Since this is a tutorial on reading data from the serial port using Python, not Arduino, I recommend visiting a DHT11 tutorial to learn how to print temperature data from the sensor to the serial. PS: cmd.encode ('ascii') + b'13' + b'10' is wrong. I think the best way is, to do all formatting and concatenation with strings and when you need them to send them as bytes, do it at this place directly without any additional stuff like concatenation. My code examples are always for Python 3.x. All humans together.
I am using a script in Python to collect data from a PIC microcontroller via serial port at 2Mbps.
The PIC works with perfect timing at 2Mbps, also the FTDI usb-serial port works great at 2Mbps (both verified with oscilloscope)
Im sending messages (size of about 15 chars) about 100-150x times a second and the number there increments (to check if i have messages being lost and so on)
On my laptop I have Xubuntu running as virtual machine, I can read the serial port via Putty and via my script (python 2.7 and pySerial)
The problem:
- When opening the serial port via Putty I see all messages (the counter in the message increments 1 by 1). Perfect!
- When opening the serial port via pySerial I see all messages but instead of receiving 100-150x per second i receive them at about 5 per second (still the message increments 1 by 1) but they are probably stored in some buffer as when I power off the PIC, i can go to the kitchen and come back and im still receiving messages.
Here is the code (I omitted most part of the code, but the loop is the same):
Anyone knows why pySerial takes so much time to read from the serial port till the end of the line?Any help?
I want to have this in real time.
Thank you
Vasco BaptistaVasco Baptista19822 gold badges44 silver badges1414 bronze badges
4 Answers
You can use
inWaiting()
to get the amount of bytes available at the input queue.Then you can use
read()
to read the bytes, something like that:Why not to use
readline()
at this case from Docs:You are waiting for the timeout at each reading since it waits for eol. the serial input Q remains the same it just a lot of time to get to the 'end' of the buffer, To understand it better: you are writing to the input Q like a race car, and reading like an old car :)
Kobi KKobi K5,31733 gold badges2929 silver badges6464 bronze badges
You need to set the timeout to 'None' when you open the serial port:
This is a blocking command, so you are waiting until you receive data that has newline (n or rn) at the end:line = ser.readline()
Once you have the data, it will return ASAP.
Fabian MeierFabian Meier
From the manual:
Possible values for the parameter timeout: … x set timeout to x seconds
and
readlines(sizehint=None, eol='n') Read a list of lines, until timeout. sizehint is ignored and only present for API compatibility with built-in File objects.
Note that this function only returns on a timeout.
So your
mswmswreadlines
will return at most every 2 seconds. Use read()
as Tim suggested.38.2k55 gold badges6565 silver badges104104 bronze badges
A very good solution to this can be found here:
Here's a class that serves as a wrapper to a pyserial object. It allows you to read lines without 100% CPU. It does not contain any timeout logic. If a timeout occurs,
self.s.read(i)
returns an empty string and you might want to throw an exception to indicate the timeout.It is also supposed to be fast according to the author:
The code below gives me 790 kB/sec while replacing the code with pyserial's readline method gives me just 170kB/sec.
JoeJoe2,96711 gold badge66 silver badges2222 bronze badges
Not the answer you're looking for? Browse other questions tagged pythonpython-2.7serial-portpyserial or ask your own question.
Active5 months ago
I'm having trouble to read more than one character using my program, I can't seem to figure out what went wrong with my program.
here are the results I get
actually I was expecting this
something like the above mentioned which is able read multiple characters at the same time not one by one.
brasofilo22.3k1010 gold badges7272 silver badges147147 bronze badges
user2294001user2294001
4 Answers
I see a couple of issues.
First:
ser.read() is only going to return 1 byte at a time.
If you specify a count
it will read 5 bytes (less if timeout occurrs before 5 bytes arrive.)
If you know that your input is always properly terminated with EOL characters, better way is to use
That will continue to read characters until an EOL is received.
Second:
Even if you get ser.read() or ser.readline() to return multiple bytes,since you are iterating over the return value, you willstill be handling it one byte at a time.
Get rid of the
and just say:
jwygralak67jwygralak67
Serial sends data 8 bits at a time, that translates to 1 byte and 1 byte means 1 character.
You need to implement your own method that can read characters into a buffer until some sentinel is reached. The convention is to send a message like
12431n
indicating one line. So what you need to do is to implement a buffer that will store X number of characters and as soon as you reach that
n
, perform your operation on the line and proceed to read the next line into the buffer.Note you will have to take care of buffer overflow cases i.e. when a line is received that is longer than your buffer etc...
EDIT
Joe7,14233 gold badges1919 silver badges3434 bronze badges
1337holiday1337holiday1,43911 gold badge1919 silver badges3838 bronze badges
I use this small method to read Arduino serial monitor with Python
Stephen RauchPython Read Serial Data
33.3k1515 gold badges4545 silver badges7070 bronze badges
Thushara MadushanThushara Madushan
I was reciving some date from my arduino uno (0-1023 numbers).Using code from 1337holiday, jwygralak67 and some tips from other sources:
Python Serial Read Example
DespritDespritPython Serial Read_until Example
39011 gold badge66 silver badges1919 bronze badges