UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Post Reply
User avatar
PierreDeQuebec
 
Posts: 61
Joined: Sun Jul 25, 2021 3:26 pm

UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by PierreDeQuebec »

Hi,
Recently, my program to read sentences on my GPS card (GPS Ultimate Logging Shield) crashes in the self.readline() routine of the GPS class in the adafruit_gps.py module. Here is the routine to which I added print commands to find the deadlock. The program never returns from the self.readline() routine.

Code: Select all

    def _read_sentence(self):
        # Parse any NMEA sentence that is available.
        # pylint: disable=len-as-condition
        # This needs to be refactored when it can be tested.

        # Only continue if we have at least 11 bytes in the input buffer
        print(f"self.in_waiting {self.in_waiting} bytes")
        if self.in_waiting < 11:
            return None

        print("Read sentence")
        sentence = self.readline()
        print("Sentence read")
        if sentence is None or sentence == b"" or len(sentence) < 1:
            return None
        try:
            sentence = str(sentence, "ascii").strip()
        except UnicodeError:
            return None
        # Look for a checksum and validate it if present.
        if len(sentence) > 7 and sentence[-3] == "*":
            # Get included checksum, then calculate it and compare.
            expected = int(sentence[-2:], 16)
            actual = 0
            for i in range(1, len(sentence) - 3):
                actual ^= ord(sentence[i])
            if actual != expected:
                return None  # Failed to validate checksum.

            # copy the raw sentence
            self._raw_sentence = sentence

            return sentence
        # At this point we don't have a valid sentence
        return None
In the end, the blockage is in the UART (busio.uart). The last thing I did before the crash was to issue a PMTK104 command to my GPS chip to force a full cold restart. I wanted to check the delay for the reboot. But I suspect the command, by forcing a factory reset, to mess something else up too!

To confirm that my program was not in question, I returned to the test program offered on the Adafruit site. I also used my second Metro M4 Airlift Lite microcontroller. But the problem remains. And here I am looking for other possible solutions to my problem.

Copy of the test program. For the needs of my project, note that for the adafruit_gps.py module, I added a 'nmea_sentence_type' property to be able to easily retrieve the type of the sentence being processed without having to put the module in 'debug' mode. This is the reason for the 'dirty' suffix to the module name used in my example.

Code: Select all

# test_serial_connexion_UART.py

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

# Simple GPS module demonstration.
# Will wait for a fix and print a message every second with the current location
# and other details.
import time
import board
import busio

from my_lib import adafruit_gps_dirty as adafruit_gps

# Create a serial connection for the GPS connection using default speed and
# a slightly higher timeout (GPS modules typically update once a second).
# These are the defaults you should use for the GPS FeatherWing.
# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)

# for a computer, use the pyserial library for uart access
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)

# If using I2C, we'll create an I2C interface to talk to using default pins
# i2c = board.I2C()

# Create a GPS module instance.
gps = adafruit_gps.GPS(uart, debug=False)  # Use UART/pyserial
# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # Use I2C interface

# Initialize the GPS module by changing what data it sends and at what rate.
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
# the GPS module behavior:
#   https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf

# Turn on the basic GGA and RMC info (what you typically want)
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
# Turn on just minimum info (RMC only, location):
# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn off everything:
# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn on everything (not all of it is parsed!)
# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')

# Set update rate to once a second (1hz) which is what you typically want.
gps.send_command(b"PMTK220,1000")
# Or decrease to once every two seconds by doubling the millisecond value.
# Be sure to also increase your UART timeout above!
# gps.send_command(b'PMTK220,2000')
# You can also speed up the rate, but don't go too fast or else you can lose
# data during parsing.  This would be twice a second (2hz, 500ms delay):
# gps.send_command(b'PMTK220,500')

# Main loop runs forever printing the location, etc. every second.
last_print = time.monotonic()
while True:
    # Make sure to call gps.update() every loop iteration and at least twice
    # as fast as data comes from the GPS unit (usually every second).
    # This returns a bool that's true if it parsed new data (you can ignore it
    # though if you don't care and instead look at the has_fix property).
    gps.update()
    # Every second print out current location details if there's a fix.
    current = time.monotonic()
    if current - last_print >= 1.0:
        last_print = current
        if not gps.has_fix:
            # Try again if we don't have a fix yet.
            print("Waiting for fix...")
            continue
        # We have a fix! (gps.has_fix is true)
        # Print out details about the fix like location, date, etc.
        print("=" * 40)  # Print a separator line.
        print(
            "Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format(
                gps.timestamp_utc.tm_mon,  # Grab parts of the time from the
                gps.timestamp_utc.tm_mday,  # struct_time object that holds
                gps.timestamp_utc.tm_year,  # the fix time.  Note you might
                gps.timestamp_utc.tm_hour,  # not get all data like year, day,
                gps.timestamp_utc.tm_min,  # month!
                gps.timestamp_utc.tm_sec,
            )
        )
        print("Latitude: {0:.6f} degrees".format(gps.latitude))
        print("Longitude: {0:.6f} degrees".format(gps.longitude))
        print(
            "Precise Latitude: {:2.}{:2.4f} degrees".format(
                gps.latitude_degrees, gps.latitude_minutes
            )
        )
        print(
            "Precise Longitude: {:2.}{:2.4f} degrees".format(
                gps.longitude_degrees, gps.longitude_minutes
            )
        )
        print("Fix quality: {}".format(gps.fix_quality))
        # Some attributes beyond latitude, longitude and timestamp are optional
        # and might not be present.  Check if they're None before trying to use!
        if gps.satellites is not None:
            print("# satellites: {}".format(gps.satellites))
        if gps.altitude_m is not None:
            print("Altitude: {} meters".format(gps.altitude_m))
        if gps.speed_knots is not None:
            print("Speed: {} knots".format(gps.speed_knots))
        if gps.track_angle_deg is not None:
            print("Track angle: {} degrees".format(gps.track_angle_deg))
        if gps.horizontal_dilution is not None:
            print("Horizontal dilution: {}".format(gps.horizontal_dilution))
        if gps.height_geoid is not None:
            print("Height geoid: {} meters".format(gps.height_geoid))


Thank you for the help you will give me.

User avatar
PierreDeQuebec
 
Posts: 61
Joined: Sun Jul 25, 2021 3:26 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by PierreDeQuebec »

Here is the output in the RPL. The traceback occurs about 10 minutes after the program starts.

Code: Select all

...
self.in_waiting 9 bytes
sentence
self.in_waiting 10 bytes
sentence
self.in_waiting 11 bytes
read sentence
Traceback (most recent call last):
  File "code.py", line 63, in <module>
  File "/home/.../Labo_Adafruit/Data_Logger/my_lib/adafruit_gps_dirty.py", line 270, in update
  File "/home/.../Labo_Adafruit/Data_Logger/my_lib/adafruit_gps_dirty.py", line 413, in _parse_sentence
  File "/home/.../Labo_Adafruit/Data_Logger/my_lib/adafruit_gps_dirty.py", line 387, in _read_sentence
  File "/home/.../Labo_Adafruit/Data_Logger/my_lib/adafruit_gps_dirty.py", line 374, in readline
MemoryError: memory allocation failed, allocating 119080 bytes

User avatar
adafruit_support_carter
 
Posts: 24423
Joined: Tue Nov 29, 2016 2:45 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by adafruit_support_carter »

Is this only happening with your modified version of the library? If you just use the original library as is, do you get the same MemoryError?

User avatar
PierreDeQuebec
 
Posts: 61
Joined: Sun Jul 25, 2021 3:26 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by PierreDeQuebec »

No. To be sure, I went back to the vanilla example. And I have the same hangup. So I tried the echo test to at least know if the module was responding in any way. And yes! He answers in Chinese! I am attaching an image of the REPL output as some characters block copying to clipboard.
Image

User avatar
PierreDeQuebec
 
Posts: 61
Joined: Sun Jul 25, 2021 3:26 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by PierreDeQuebec »

Here is a link to the image in question. I don't know why the image tag didn't work!
https://zupimages.net/viewer.php?id=22/33/qkng.png

User avatar
adafruit_support_carter
 
Posts: 24423
Joined: Tue Nov 29, 2016 2:45 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by adafruit_support_carter »

Using hardware serial with the GPS logger shield unfortunately takes some effort. There's a dedicated page dealing with it here:
https://learn.adafruit.com/adafruit-ult ... al-connect

Are you making the jumper connections shown here?
https://learn.adafruit.com/adafruit-ult ... al-3073999

User avatar
PierreDeQuebec
 
Posts: 61
Joined: Sun Jul 25, 2021 3:26 pm

Re: UART is frozen (Metro M4 Airlift Lite with GPS Ultimate Logging Shield)

Post by PierreDeQuebec »

Yes, connexions are OK. By the way, the revised documentation is much clearer with the addition of the photos. Recently, the UART line has started giving readable characters again. I don't know exactly why. But I think my problem originated from a bad configuration of the baud rate. In my program, I also increased the delay to 30 s for a first fix as proof that my GPS module is functional. Generally, I have a first fix in much less than 5 s. but sometimes it takes longer. The 30s delay fixed the problem.

Post Reply
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”