2

I have got a GPS module connected to my Raspberry Pi and I want the program to end if the device gets disconnected at any point. If I disconnect it now, the program just hangs. Any way to solve this?

This is my code:

import serial
import time
import string
import pynmea2

while True:
    port="/dev/ttyAMA0"
    ser=serial.Serial(port, baudrate=9600, timeout=1)
    dataout = pynmea2.NMEAStreamReader()
    newdata=ser.readline()

    if newdata[0:6] == "$GPRMC":
        newmsg=pynmea2.parse(newdata)
        lat=newmsg.latitude
        lng=newmsg.longitude
        gps = str(lat) + ", " + str(lng)
        print(gps)
Benibla124
  • 25
  • 5

2 Answers2

2

That's not normally possible. The built-in serial ports do not have any way of detecting a disconnected partner. If the GPS receiver supports it, you could use the CTX wire to detect a disconnected device, but that's typically not wired for most devices. That means your Raspberry Pi won't be able to distinguish between a disconnected device and a device that just doesn't send anything (because it has no power, is broken or whatever).

Since the GPS receiver will usually send a message at least once per second, you could add a timeout that exits the program if it waits for much longer. As you already correctly found out, ser.readline() is blocking. That means if nothing is received, this will not return. You need a non-blocking variant of that, which doesn't exist out-of-the-box. Check PySerial non-blocking read loop for a possible solution.

PMF
  • 14,535
  • 3
  • 23
  • 49
0

You can use python's try-except statements to catch the error and use quit() to exit the program. Also, is the ser initialisation in loop intentional? If not, you might want to put it outside the loop to avoid unnecessary re-initialisations.

So the code would look something like this:

    import serial
    import time
    import string
    import pynmea2
    
    port = "/dev/ttyAMA0"
    ser = serial.Serial(port, baudrate=9600, timeout=1)
    dataout = pynmea2.NMEAStreamReader()

    while True:
      if ser.in_waiting:
        try: 
          newdata = ser.readline()
    
        except:
          print("Error!")
          quit()
    
        if newdata[0:6] == "$GPRMC":
          newmsg = pynmea2.parse(newdata)
          lat = newmsg.latitude
          lng = newmsg.longitude
          gps = str(lat) + ", " + str(lng)
          print(gps)

You can also specify the error type within the except statement. For reference: https://docs.python.org/3/tutorial/errors.html

  • Well the problem is that `newdata = ser.readline()` doesn't even throw an error, it just makes the program freeze if I disconnect the GPS module. – Benibla124 Jan 05 '22 at 10:58
  • Ah right, as @PMF pointed out, you can avoid the freezing by making it a non-blocking read. I've edited my response to reflect that. IIRC ser.in_waiting should throw an error if the serial connection is lost. – Akarsh Gopal Jan 05 '22 at 12:33