iggy1
Posts: 5
Joined: Tue Jan 31, 2017 8:34 am

How can I ignore checksum errors when using pynmea2?

Tue May 16, 2017 11:52 am

Hello world,

I am using pynmea2 with python 2 to control various flight-related things on a high-altitude balloon. However, my GPS data stream seems a bit flaky, and every so often, pynmea2 detects a checksum error and the program stops.

Here is a typical error message:

Traceback (most recent call last):
File "/home/pi/separate_gps_sms_test.py", line 145, in <module>
parseGPSGGA(string)
File "/home/pi/separate_gps_sms_test.py", line 17, in parseGPSGGA
msg = pynmea2.parse(string)
File "/usr/local/lib/python2.7/dist-packages/pynmea2/nmea.py", line 116, in parse
'checksum does not match: %02X != %02X' % (cs1, cs2), data)
ChecksumError: ('checksum does not match: 5C != 1B', ['', '112811.00', '5001.98613', 'N', '00841.70790', 'E', '1', '11', '1.12', '148.5', 'M', '47.6', 'M', '', ''])

How can I prevent this from happening? Any help appreciated, as reliability is crucial if we are going to recover the balloon.

Thanks
Ilya

Code: Select all

import serial
import time
import pynmea2


GPSDATA=0
TIME=0
LAT=0
LON=0
ALT=0
SPEED=0

time.sleep(1)

def parseGPSGGA(string):
    global GPSDATA,TIME,LAT,LON,ALT
    msg = pynmea2.parse(string)
    print "GPGGA received"
        
    if msg.gps_qual > 0 and msg.gps_qual < 6 and int(msg.num_sats) > 2:
        GPSDATA=1
        TIME = msg.timestamp
        LAT = msg.latitude
        LON = msg.longitude
        ALT = msg.altitude
    else:
        GPSDATA=0


    return

def parseGPSRMC(string):
    global SPEED
    msg = pynmea2.parse(string)
    print "GPRMC received"
    SPEED = str(msg.spd_over_grnd)
    if SPEED=="None":
        SPEED = 0
    else:
        SPEED = msg.spd_over_grnd

    SPEED = float(SPEED) * 1.852
        
    return


def sendSMS():
    global LOCATION,gsmsignal,PhoneNumber_1
    ser1 = serial.Serial("/dev/ttyUSBGSM", 9600, timeout=10)

    ser1.write('AT+CMGS=' + PhoneNumber_1 + '\r')

    time.sleep(1)
    ser1.write (LOCATION + ", GSM Signal: " + str(gsmsignal))
    ser1.write (chr(26))

    ser1.flushInput()
    ser1.close()
    return


# This section ensures that the program waits
# for the GPS and GSM module to boot and connect to the network
data = ""
previousaltitude = 0
time.sleep(10)

SMSCentre = '"+491770610000"'
PhoneNumber_1 = '"+4915201575169"'

# Open serial port (via USB) and flush all data in buffers
ser1 = serial.Serial("/dev/ttyUSBGSM", 9600, timeout = 0.5)
ser1.flushInput()
ser1.flushOutput()
time.sleep(0.5)

# The next line makes sure any "overhanging" SMS
# is sent and modem can accept commands
ser1.write(chr(26))

while True:
    ser1.write('AT\r')
    data = ser1.read(45)
    if data.find('OK') != -1:
        break
    time.sleep(1)
    
# Place SMS mode to 'text'
ser1.write("AT+CMGF=1\r")
data = ser1.read(45)

# This sets up the SMS processing centre number (network specific)
ser1.write('AT+CSCA=' + SMSCentre + '\r')
data = ser1.read(45)

time.sleep(1)

# Request GSM signal strength
csq = 'a,:b,:c'


# This inner loop ensures the data received is
# valid signal strength before parsing
while True:
    ser1.flushInput()
    ser1.write('AT+CSQ\r')
    time.sleep(0.5)
    csq = ser1.read(120)
    if csq.find('CSQ') != -1:
        break

    
print csq
csq = csq.split(":")
csq = csq[1].split(",")
gsmsignal = float(csq[0])
print 'GSM signal strength = ' + str(gsmsignal) + '\n'


#ser.close()
time.sleep(1)

ser0 = serial.Serial("/dev/ttyUSBGPS", 9600, timeout=10)
ser0.flushInput()

COUNT = 0
    
while True:
    ser0 = serial.Serial("/dev/ttyUSBGPS", 9600, timeout=10)
    ser0.flushInput()        
    string = ser0.readline()

    if string.find('RMC') > 0:
        
        parseGPSRMC(string)
        
        
    if string.find('GGA') > 0:
        
        parseGPSGGA(string)
        if GPSDATA==1:
            ser0.close()
            COUNT += 1
            print COUNT
            
            LOCATION = "Timestamp: " + str(TIME) + ", Latitude: " + str(LAT) + "N" + ", Longitude: " + str(LON) + "W" + ", Altitude: " + str(ALT) + "m, Speed: " + str(SPEED) + "km/h"
            
            print LOCATION
# SAVE DATA TO FILE GOES HERE
            time.sleep(29)

            if COUNT == 10:
                while True:
                    ser1.flushInput()
                    ser1.write('AT+CSQ\r')
                    time.sleep(0.5)
                    csq = ser1.read(120)
                    if csq.find('CSQ') != -1:
                        break
                print (csq)
                csq = csq.split(":")
                csq = csq[1].split(",")
                gsmsignal = float(csq[0])
                print 'GSM signal strength = ' + str(gsmsignal) + '\n'

                if gsmsignal > 7:    
                    sendSMS()
                COUNT = 0

User avatar
joan
Posts: 12776
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: How can I ignore checksum errors when using pynmea2?

Tue May 16, 2017 12:12 pm

Python has a try/except syntax to deal with exceptions. I suggest you wrap the parse calls with try/except. You will have to decide how you deal with the error. It might be as simple as ignoring that record or returning the last good record.

iggy1
Posts: 5
Joined: Tue Jan 31, 2017 8:34 am

Re: How can I ignore checksum errors when using pynmea2?

Tue May 16, 2017 12:39 pm

Cheers, that works a treat!

Return to “Python”

Who is online

Users browsing this forum: No registered users and 29 guests