16

I'm having a problem with serial IO under both Windows and Linux using pySerial. With this code the device never receives the command and the read times out:

import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
ser.write("get")
ser.flush()
print ser.read()

This code times out the first time through, but subsequent iterations succeed:

import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
while True:
    ser.write("get")
    ser.flush()
    print ser.read()

Can anyone tell what's going on? I tried to add a call to sync() but it wouldn't take a serial object as it's argument.

Thanks, Robert

Robert Jordan
  • 1,053
  • 1
  • 10
  • 17

4 Answers4

21

Put some delay in between write and read e.g.

import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
ser.flushInput()
ser.flushOutput()
ser.write("get") 

# sleep(1) for 100 millisecond delay
# 100ms dely
sleep(.1)
print ser.read()
beebek
  • 1,893
  • 5
  • 29
  • 33
  • 7
    Generally, adding a delay to fix a problem is a bad idea, unless a delay is physically or electrically required by some specific hardware in your setup. There is almost always a better way of doing things like this. – josh798 Aug 10 '21 at 14:15
  • Those methods are deprecated and replaced with `reset_input_buffer()` and `reset_output_buffer()`, see: [doc](https://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.reset_input_buffer) – Bruno L. Mar 27 '22 at 11:24
5

This is because pyserial returns from opening the port before it is actually ready. I've noticed that things like flushInput() don't actually clear the input buffer, for example, if called immediately after the open(). Following is code to demonstrate:

import unittest
import serial
import time
"""
1) create a virtual or real connection between COM12 and COM13
2) in a terminal connected to COM12 (at 9600, N81), enter some junk text (e.g.'sdgfdsgasdg')
3) then execute this unit test
"""

class Test_test1(unittest.TestCase):
    def test_A(self):
        with serial.Serial(port='COM13', baudrate=9600) as s:   # open serial port
            print("Read ASAP:  {}".format(s.read(s.in_waiting)))
            time.sleep(0.1)     # wait for 100 ms for pyserial port to actually be ready
            print("Read after delay:  {}".format(s.read(s.in_waiting)))

if __name__ == '__main__':
    unittest.main()

"""
output will be:
Read ASAP:  b''
Read after delay:  b'sdgfdsgasdg'
.
----------------------------------------------------------------------
Ran 1 test in 0.101s
"""

My workaround has been to implement a 100ms delay after opening before doing anything.

Jimbo1987
  • 111
  • 1
  • 16
5

Question is really old, but I feel this might be relevant addition.

Some devices (such as Agilent E3631, for example) rely on DTR. Some ultra-cheap adapters do not have DTR line (or do not have it broken out), and using those, such devices may never behave in expected manner (delays between reads and writes get ridiculously long).

If you find yourself wrestling with such a device, my recommendation is to get an adapter with DTR.

Tammi
  • 421
  • 7
  • 12
4

Sorry that this is old and obvious to some, but I didn't see this option mentioned here. I ended up calling a read_all() when flush wasn't doing anything with my hardware.

# Stopped reading for a while on the connection so things build up

# Neither of these were working
conn.flush()
conn.flushInput()

# This did the trick, return value is ignored
conn.read_all()

# Waits for next line
conn.read_line()
ataboo
  • 797
  • 1
  • 8
  • 16
  • read_all seems to be the only solution for me. I'm thinking it could also be a bug in how threads are handled in python? Either way! Very 'odd' behaviour I must say. - I had a recursive function that just kept pilig up, even though the entry reset the higher level python read streams – Jamie Nicholl-Shelley Feb 25 '23 at 18:06