tomas_evatech
Posts: 3
Joined: Mon Feb 17, 2020 12:57 am

termios.error and IOError when reading UART device

Mon Feb 24, 2020 6:04 pm

I wrote a python program for continuously reading serial data from a GPS receiver (http://navspark.mybigcommerce.com/ns-hp ... -receiver/). The data is in NMEA format. Here is my code:

Code: Select all

from time import sleep
import serial
from os import system

count = 0
DELAY = 2

ser = serial.Serial('/dev/serial0', baudrate=115200)
ser.close()
while True:
	try:
		count += 1		
		ser.open()
		line = ser.readline()
		ser.close()
		data = line.split(",")

		if (data[0]=="$GPGGA"):
			utc = data[1]
			lat = data[2]
			latHem = data[3]
			lon = data[4]
			lonHem = data[5]
			gpsQual = data[6]
			nSats = data[7]
			hdop = data[8]
			alt = data[9]
			geoSep = data[10]
			agePfD = data[11]
			dgpsId = data[12]
			checksum = data[13]
			
			system('clear')
			print "UTC: ", utc
			print "Lat: ", latHem, " ", lat
			print "Lon: ", lonHem, " ", lon
			print "Altitude: ", alt
			print "Geoidal separation in meters: ", geoSep
			print "Reading Quality: ", gpsQual
			print "Number of satelites read: ", nSats
			print "Reading number: ", count

	except serial.serialutil.SerialException:
		ser.close()
		print "Communication error, retrying..."

	except IndexError:
		ser.close()
		print "Index error, retrying..."

The program works fine for several iterations, but eventually fails with either one of the following errors:

Code: Select all

Traceback (most recent call last):
  File "gpsRead.py", line 13, in <module>
    ser.open()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 272, in open
    self._reconfigure_port(force_update=True)
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 438, in _reconfigure_port
    [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
termios.error: (5, 'Input/output error')

Code: Select all

Traceback (most recent call last):
  File "gpsRead.py", line 13, in <module>
    ser.open()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 286, in open
    self._update_dtr_state()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 634, in _update_dtr_state
    fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
IOError: [Errno 5] Input/output error

The problem seems to originate from line 13 (ser.open()). I am not sure why these errors occur or how to fix them. Any help with this matter would be greatly appreciated.

User avatar
jojopi
Posts: 3237
Joined: Tue Oct 11, 2011 8:38 pm

Re: termios.error and IOError when reading UART device

Mon Feb 24, 2020 7:47 pm

"Input/output error" generally indicates that something is wrong at the hardware or driver level. After seeing that error, you should run the "dmesg" command to display the kernel logs. Check whether there is any recent mention of serial or uart, or any other errors that seem relevant.

There is no need to close and reopen the port all the time, and it may cause problems in certain circumstances. Your serial.Serial(…) call already opens once, at the start of the program, which is ideal. Remove all of the calls to ser.close() and ser.open(). Even if this does not fix the issue, it should change the behaviour and/or diagnostics. Your existing tracebacks are inside the reopen call.

tomas_evatech
Posts: 3
Joined: Mon Feb 17, 2020 12:57 am

Re: termios.error and IOError when reading UART device

Mon Feb 24, 2020 10:48 pm

OK. I disabled all instances of "ser.open()" and "ser.close()" as well as the try/except clause. After the 453rd iteration, I get the following error:

Code: Select all

Traceback (most recent call last):
  File "204.py", line 14, in <module>
    line = ser.readline()
  File "/usr/lib/python2.7/dist-packages/serial/serialposix.py", line 501, in read
    'device reports readiness to read but returned no data '
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)
Here is the latest mention of "Serial" when I run dmesg:

Code: Select all

[    0.315400] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled

User avatar
jojopi
Posts: 3237
Joined: Tue Oct 11, 2011 8:38 pm

Re: termios.error and IOError when reading UART device

Tue Feb 25, 2020 12:45 am

Looking at the relevant source code for pyserial, that exception occurs in exactly the situation it describes. "select.select()" said that the port was ready to read, but then "os.read()" returned no data.

As the message goes on to say, one possibility is that some other program had the port open, and read or flushed the incoming data between our two calls. Another is that the driver has lost contact with the hardware. I am not sure whether either of these is a good fit for your situation. If something else had the port open the whole time, I would expect it to fail before the 453rd try. If there was a hardware issue, I would expect something in dmesg.

If you go back to trapping the exception and retrying (without closing the port), does it start to return data again, or fail every time from then on?

I notice you are using "Serial: 8250/16550 driver", which I believe means you are on a model of Pi that has Bluetooth. If you add to /boot/config.txt:

Code: Select all

dtoverlay=miniuart-bt
and reboot, that should swap the two ports (Bluetooth performance will be temporarily reduced), and dmesg will show "Serial: AMBA PL011 UART driver". Now without any changes to your code or wiring, you can test with a completely different hardware block and kernel driver. Does it make a difference?

tomas_evatech
Posts: 3
Joined: Mon Feb 17, 2020 12:57 am

Re: termios.error and IOError when reading UART device

Tue Feb 25, 2020 5:49 pm

If you go back to trapping the exception and retrying (without closing the port), does it start to return data again, or fail every time from then on?
I tried that. Once It throws a serial exception, it keeps doing so until I restart the program.
I notice you are using "Serial: 8250/16550 driver", which I believe means you are on a model of Pi that has Bluetooth. If you add to /boot/config.txt:

Code: Select all

dtoverlay=miniuart-bt
and reboot, that should swap the two ports (Bluetooth performance will be temporarily reduced), and dmesg will show "Serial: AMBA PL011 UART driver". Now without any changes to your code or wiring, you can test with a completely different hardware block and kernel driver. Does it make a difference?
I followed these steps and I still have the same issue. When I ran dmesg again, here was the latest mention of serial:

Code: Select all

[    2.164478] uart-pl011 3f201000.serial: no DMA platform data

Return to “Python”