Python Serial Inwaiting Example
This page provides Python code examples for serial. Print('Waiting for. Representing the path used for connecting to the machine's serial interface Example. Dec 9, 2015 - As part of script development, I have used pyserial module for accessing the DUT. I have started using inWaiting() API for reading the data displayed on. The serial stream with minimum latency, for example when decoding.
I've got a simple program to test serial functionality. My serial device reacts to two inputs. If the user enters 'a', it responds with 'fg'. If the user enters anything other character/byte, it responds with 'z'. If I send 'b' to the serial device, it will return 'z' just fine. When I send 'a', it should return both 'f' and 'g', so two bytes instead of one.
See code below.
The output is :
inWaiting() gives the value of 0, thus it never reads the second byte. If I do a small change to the code, and manually read the two expected bytes, it works fine.
The output is as expected:
2 Answers
There are two decent solutions for this. For either, you'll need to set a timeout like jramirez already suggested:
Solution 1: Simple and effective
This will read up to 800 bytes and will take no more time than the timeout
you've set. If you've instead set an inter_byte_timeout
, read()
will wait up to that amount of time for each single byte.
This is a quick solution that will work for cases where you only receive a chunk of data of known maximum size.
Solution 2: The proper way
The code snippet above is licensed under CC0 1.0.
And then, to read:
Basically, this will read your data in chunks and wait every time to see if new characters appeared. If less characters were read in the time set by timeout
, the transmission is considered finished.
This solution will always work, even when you receive a lot of data or if you receive it very slowly.
it could be because the baudrate is really slow. You are processing the inwaiting() call before the second byte gets to the buffer. When you do ser.read(2) it waits(blocks) until 2 bytes have been received thus why it works. Try setting a timeout of 1 second, that should fix your problem.
Not the answer you're looking for? Browse other questions tagged pythonpyserial or ask your own question.
I am reading serial data like this:
The problem is that it prevents anything else from executing including bottle py web framework. Adding sleep()
won't help.
Changing 'while True' to 'while ser.readline():' doesn't print 'test', which is strange since it worked in Python 2.7. Any ideas what could be wrong?
Ideally I should be able to read serial data only when it's available. Data is being sent every 1,000 ms.
3 Answers
Put it in a separate thread, for example:
Using a separate thread is totally unnecessary. Just do this for your infinite while loop instead (Tested in Python 3.2.3):
This way you only read and print if something is there. You said, 'Ideally I should be able to read serial data only when it's available.' This is exactly what the code above does. If nothing is available to read, it skips on to the rest of your code in the while loop. Totally non-blocking.
(This answer originally posted & debugged here: Python 3 non-blocking read with pySerial (Cannot get pySerial's 'in_waiting' property to work))
pySerial documentation: http://pyserial.readthedocs.io/en/latest/pyserial_api.html
UPDATE:
- 27 Dec. 2018: added comment about
in_waiting
vsinWaiting()
. Thanks to @FurkanTürkal for pointing that out in the comments below. See documentation here: https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting. - 27 Oct. 2018: Add sleep to let other threads run.
- Documentation: https://docs.python.org/3/library/time.html#time.sleep
- Thanks to @RufusV2 for bringing this point up in the comments.
Note on multi-threading:
Even though reading serial data, as shown above, does not require using multiple threads, reading keyboard input in a non-blocking manner does. Therefore, to accomplish non-blocking keyboard input reading, I've written this answer: How to read keyboard-input?.
Use a timer driven event to test and read the serial port.Untested example: