pythonserial-portpyserial

Pyserial cannot read data but minicom works fine


I'm writing something like an SMS gate on Ubuntu. The device is a Huawei E173 Modem.

I use pyserial to write/read to and from the device. Here is my code:

import serial
import time

port = '/dev/ttyUSB0'
ser = serial.Serial(port,
        stopbits=serial.STOPBITS_ONE,
        parity=serial.PARITY_NONE,
        bytesize=serial.EIGHTBITS
        )
ser.write(b'AT\r\n')
time.sleep(0.1)
print(ser.read(ser.in_waiting))

This code works. But sometimes when I reconnect the device, I find that it cannot read anything. (ser.in_waiting=0 and nothing changes even if I set n larger).

But I can still use minicom to work with that port.

My Question: Why doesn't pyserial work but minicom can? Is there any difference between them?


Solution

  • What I guess it's happening is that the delay you are using together with the timeout you set when you open the port is conspiring with the time it takes for the modem to process the command.

    To avoid that try reading data repeatedly for a certain time with a loop:

    ... 
    ser.write(b'AT\r\n')
    timeout=time.time()+3.0 
    while ser.inWaiting() or time.time()-timeout<0.0: 
        if ser.inWaiting()>0: 
            data+=ser.read(ser.inWaiting()) 
             timeout=time.time()+3.0 print(data)
    

    With minicom or any other terminal you are always listening on the port so you always get the answer no matter how long the modem takes to process the command. In your code you send the command, wait 100 ms and then listen on the port for a time period defined by the timeout setting. Since you are not defining a timeout you have the default wait forever but that behavior is overridden by the use of the bytes in the buffer as an argument. If you happen to check the buffer before data arrives in it (because the command took longer than the 100 ms you gave it) the timeout becomes zero.

    Considering the previous paragraph, and assuming you know the number of bytes it might be better to define a finite timeout and read with a ser.read(n) with n the expected bytes.