Pico and MicroPython to display GPS data

Thanks a lot to microcontrollerslab.com for a really good starting point by using MicroPython to get GPS data from a NEO-6M using a Raspberry PI Pico.

The things I did differently: I used different Pins on the Pico and I adjusted the code to a more pythonic style.

First the Pins. For I2C I used Pin 20 and Pin 21, the same as in my previous post. And for UART the Pins that are at the bottom of the Pico nearest to the Neo module on my breadboard, which are Pin 16 and Pin 17 for TX/RX.

The code from microcontrollerslab after some refactoring:

import machine
import utime
import ssd1306

def convert2degree(raw_degrees):
    try:
        raw_f = float(raw_degrees)
        first = int(raw_f / 100)
        result = float(first + (raw_f - float(first * 100)) / 60.0)
        return f"{result:.6f}"
    except ValueError:
        return ""

class GPS:
    def __init__(self):
        i2c = machine.I2C(0, sda=machine.Pin(20), scl=machine.Pin(21))
        self.oled = ssd1306.SSD1306_I2C(128, 32, i2c)
        self.gps = machine.UART(
            0, baudrate=9600, tx=machine.Pin(16), rx=machine.Pin(17)
        )

    def display(self, latitude, longitude, satellites, gps_time):
        self.oled.fill(0)
        self.oled.text(f"Lat: {latitude}", 0, 0)
        self.oled.text(f"Lng: {longitude}", 0, 10)
        self.oled.text(f"{satellites} -- {gps_time}", 0, 20)
        self.oled.show()

    def run(self):
        while True:
            parts = str(self.gps.readline()).split(",")

            if parts[0] == "b'$GPGGA" and len(parts) == 15:
                if (
                    parts[1] and parts[2] and parts[3] and parts[4]
                    and parts[5] and parts[6] and parts[7]
                ):
                    latitude = convert2degree(parts[2])
                    if parts[3] == "S":
                        latitude = f"-{latitude}"
                    longitude = convert2degree(parts[4])
                    if parts[5] == "W":
                        longitude = f"-{longitude}"
                    satellites = parts[7]
                    gps_time = f"{parts[1][0:2]}:{parts[1][2:4]}:{parts[1][4:6]}"

                    if latitude and longitude:
                        self.display(latitude, longitude, satellites, gps_time)

            utime.sleep_ms(500)

if __name__ == "__main__":
    g = GPS()
    g.run()

The convert2degree function failed sometimes, so I set latitude or longitude to an empty string when this happens and doesn't display the values on the OLED.

My hardware setup with a Raspberry PI Pico, a NEO-6M module and a 128x32 oled display:

img1

I removed the exact GPS coordinates. At this window I get 8 satellites, which is actually not so bad.