2
votes

In my project, there's a Raspberry Pi Zero W, linked with Arduino Pro Micro over the serial TX/RX lines (through 5 - 3.3V logic level converter). At power-on, the Arduino starts sending "are you there" command over the serial, until Pi has finished booting and launched a python program that listens on serial port, and it replies with "yes". Then Arduino proceeds with sending regular updates with sensor data.

For some reason not yet understood, the Arduino can disconnect and reboot, while the Pi is still running. And, for some reason, the connection on the Python end is severed in a way that does not raise exception if connection.in_waiting is read.

import serial
import time
ser = serial.Serial('/dev/serial0')
ser.baudrate = 9600
cmd = b''
while True:
  time.sleep(1)
  print(ser.is_open)
  while ser.in_waiting:
    ch = ser.read()
    if ch == b'\n':
      print('New command:', cmd)
      cmd = b''
      ser.write(b'OK\n')
      continue
    else:
      cmd = cmd + ch

I have tested with this simple code, but in my tests, if I disconnect the Arduino and connect it back, the ser.is_open never is False, and the old connection works just fine also with reconnected Arduino. So, unfortunately I can not exactly replicate the loss of connection scenario when the data stop coming after disconnection. However, in order to investigate further, I'd like to add some monitoring code that would log serial disconnection incidents in file. But is there a way? If connection.is_open is always true, even without Arduino connected, then how one can detect if there is no connection?

1
Have you tried setting a timeout? With no timeout read() will block until the requested number of bytes is read (the default is 1). - bromosapien
@bromosapien the ser.read() follows immediately while ser.in_waiting:. Is there any reason why read() would block in such setting? - Passiday

1 Answers

0
votes

The port remains open if there's a disconnection so your example code will loop continuously.

import serial

def connect(port):
    return serial.Serial(port, baudrate=9600, timeout=1)

ser = connect('/dev/serial0')
buf = bytearray()
while True:
    i = buf.find(b'\n')
    if i >= 0:
        buf = buf[i + 1:]
        ser.write('OK\n')

    num_bytes = max(1, min(1024, ser.in_waiting))
    data = ser.read(num_bytes)
    if data:
        buf.extend(data)
    else:
        # no data to read aka disconnection has occurred
        ser = connect('/dev/serial0')
        if ser.isOpen():
            continue
        else:
            # could not reconnect
            break