Pico Display Pack + Waveshare GPS = garbled display when not connected to PC

Howdy Folks:

Trying to get the waveshare l76b pico gps working with a pico display pack. When connected to pc and running the code I get a Time/Lat/Long on display like in image 1 ( Imgur: The magic of the Internet ) but when I put it on battery I get display like image 2 (https://i.imgur.com/6GXFVYP.jpg)

stopping and restarting will clear and display like image 1

I think it might have to do with the serial interface but not sure. Any ideas?

Anyone know how to extract GPS altitude from the string?

I want to display time (utc), Altitude, speed and lat/long. Updated every 5 seconds.


import utime
import picodisplay as display
import random

# -*- coding:utf-8 -*-

import time
import l76x
import time
import math

'''
uart_print = UART(0,baudrate=9600,tx=Pin(0),rx=Pin(1))
#uart_print = UART(1,baudrate=9600,tx=Pin(4),rx=Pin(5))
StandBy = Pin(17,Pin.OUT)
StandBy.value(0)
ForceOn = Pin(14,Pin.OUT)
ForceOn.value(0)
rxData = bytes()

while True:
    while uart_print.any() > 0:
        rxData += uart_print.read(1)
    print(rxData.decode('utf-8'))
'''

x=l76x.L76X()
x.L76X_Set_Baudrate(9600)
x.L76X_Send_Command(x.SET_NMEA_BAUDRATE_115200)
time.sleep(2)
x.L76X_Set_Baudrate(115200)

x.L76X_Send_Command(x.SET_POS_FIX_400MS);

#Set output message
x.L76X_Send_Command(x.SET_NMEA_OUTPUT);

time.sleep(2)
x.L76X_Exit_BackupMode();
x.L76X_Send_Command(x.SET_SYNC_PPS_NMEA_ON)

#x.L76X_Send_Command(x.SET_STANDBY_MODE)
#time.sleep(10)
#x.L76X_Send_Command(x.SET_NORMAL_MODE)
#x.config.StandBy.value(1)

# Set up and initialise Pico Display
buf = bytearray(display.get_width() * display.get_height() * 2)
display.init(buf)
display.set_backlight(0.9)


while(1):
    x.L76X_Gat_GNRMC()
    if(x.Status == 1):
        print ('Already positioned')
    else:
        print ('No positioning')
    print ('Time %d: %d : %d'%(x.Time_H,x.Time_M,x.Time_S))

    print ('Lon = %f  Lat = %f'%(x.Lon,x.Lat))
    #x.L76X_Baidu_Coordinates(x.Lat, x.Lon)
    #print ('Baidu coordinate %f ,%f'%(x.Lat_Baidu,x.Lon_Baidu))
    #x.L76X_Google_Coordinates(x.Lat,x.Lon)
    #print ('Google coordinate %f ,%f'%(x.Lon_Google,x.Lat_Google))
    #time.sleep(5)

    display.set_pen(0, 0, 0)  # Set pen to black
    display.clear()           # Fill the screen with the colour
    display.set_pen(255, 255, 255)  # Set pen to white
    display.text(str('%d:'%(x.Time_H)+(str('%d:'%(x.Time_M)))+(str('%d'%(x.Time_S)))), 10, 10, 240, 5)  # Print Time
    display.text(str('LAT: %d'%(x.Lat)), 10, 50, 240, 5)  # Print Lattitude
    display.text(str('LONG: %d'%(x.Lon)), 10, 90, 240, 5)  # Print Longitude

    
    display.update()          # Update the display  
    time.sleep(5)






there is a lib or i guess a reference file called l76x that looks like this:

-- coding:utf-8 --

from machine import Pin
import l76_config
import math
import time

Temp = ‘0123456789ABCDEF*’
BUFFSIZE = 1100

pi = 3.14159265358979324
a = 6378245.0
ee = 0.00669342162296594323
x_pi = 3.14159265358979324 * 3000.0 / 180.0

class L76X(object):
Lon = 0.0
Lat = 0.0
Lon_area = ‘E’
Lat_area = ‘W’
Time_H = 0
Time_M = 0
Time_S = 0
Status = 0
Lon_Baidu = 0.0
Lat_Baidu = 0.0
Lon_Google = 0.0
Lat_Google = 0.0

GPS_Lon = 0
GPS_Lat = 0

#Startup mode
SET_HOT_START       = '$PMTK101'
SET_WARM_START      = '$PMTK102'
SET_COLD_START      = '$PMTK103'
SET_FULL_COLD_START = '$PMTK104'

#Standby mode -- Exit requires high level trigger
SET_PERPETUAL_STANDBY_MODE      = '$PMTK161'
SET_STANDBY_MODE                = '$PMTK161,0'

SET_PERIODIC_MODE               = '$PMTK225'
SET_NORMAL_MODE                 = '$PMTK225,0'
SET_PERIODIC_BACKUP_MODE        = '$PMTK225,1,1000,2000'
SET_PERIODIC_STANDBY_MODE       = '$PMTK225,2,1000,2000'
SET_PERPETUAL_BACKUP_MODE       = '$PMTK225,4'
SET_ALWAYSLOCATE_STANDBY_MODE   = '$PMTK225,8'
SET_ALWAYSLOCATE_BACKUP_MODE    = '$PMTK225,9'

#Set the message interval,100ms~10000ms
SET_POS_FIX         = '$PMTK220'
SET_POS_FIX_100MS   = '$PMTK220,100'
SET_POS_FIX_200MS   = '$PMTK220,200'
SET_POS_FIX_400MS   = '$PMTK220,400'
SET_POS_FIX_800MS   = '$PMTK220,800'
SET_POS_FIX_1S      = '$PMTK220,1000'
SET_POS_FIX_2S      = '$PMTK220,2000'
SET_POS_FIX_4S      = '$PMTK220,4000'
SET_POS_FIX_8S      = '$PMTK220,8000'
SET_POS_FIX_10S     = '$PMTK220,10000'

#Switching time output
SET_SYNC_PPS_NMEA_OFF   = '$PMTK255,0'
SET_SYNC_PPS_NMEA_ON    = '$PMTK255,1'

#To restore the system default setting
SET_REDUCTION               = '$PMTK314,-1'

#Set NMEA sentence output frequencies 
SET_NMEA_OUTPUT = '$PMTK314,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0'
#Baud rate
SET_NMEA_BAUDRATE          = '$PMTK251'
SET_NMEA_BAUDRATE_115200   = '$PMTK251,115200'
SET_NMEA_BAUDRATE_57600    = '$PMTK251,57600'
SET_NMEA_BAUDRATE_38400    = '$PMTK251,38400'
SET_NMEA_BAUDRATE_19200    = '$PMTK251,19200'
SET_NMEA_BAUDRATE_14400    = '$PMTK251,14400'
SET_NMEA_BAUDRATE_9600     = '$PMTK251,9600'
SET_NMEA_BAUDRATE_4800     = '$PMTK251,4800'

def __init__(self):
    self.config = l76_config.config(9600)

def L76X_Send_Command(self, data):
    Check = ord(data[1]) 
    for i in range(2, len(data)):
        Check = Check ^ ord(data[i]) 
    data = data + Temp[16]
    data = data + Temp[int(Check/16)]
    data = data + Temp[int(Check%16)]
    self.config.Uart_SendString(data.encode())
    self.config.Uart_SendByte('\r'.encode())
    self.config.Uart_SendByte('\n'.encode())
    print (data)
    
def L76X_Gat_GNRMC(self):
    data = self.config.Uart_ReceiveString(BUFFSIZE)
    print (data)
    print ('\n')
    add=0
    self.Status = 0
    try:
        for i in range(0, BUFFSIZE-71):
            if(ord(data[add]) == 36 and ord(data[add+1]) == 71 and (ord(data[add+2]) == 78 \
            or ord(data[add+2]) == 80) and ord(data[add+3]) == 82 and ord(data[add+4]) == 77\
            and ord(data[add+5]) == 67):
                    x = 0
                    z = 0
                    while(x < 12):
                        if(add+z >= BUFFSIZE-1):
                            return
                        if(ord(data[add+z]) == 44):#,
                            x = x + 1
                            if(x == 1):
                                Time = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if(ord(data[add+z+k+1]) == 44):#,
                                        break
                                    if(ord(data[add+z+k+1]) == 46):#.
                                        break
                                    Time = (ord(data[add+z+k+1]) - 48) + Time*10
                                self.Time_H = Time/10000 + 8
                                self.Time_M = Time/100%100
                                self.Time_S = Time%100
                                if(self.Time_H >= 24):
                                     self.Time_H =  self.Time_H - 24
                            elif(x == 2):
                                if(ord(data[add+z+1]) == 65):#A
                                    self.Status = 1
                                else:
                                    self.Status = 0
                            elif(x == 3):
                                latitude = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if(ord(data[add+z+k+1]) == 44):#,
                                        break
                                    if(ord(data[add+z+k+1]) == 46):#.
                                        continue
                                    latitude = (ord(data[add+z+k+1]) - 48) + latitude*10
                                self.Lat = latitude / 1000000.0
                            elif(x == 4):
                                self.Lat_area = data[add+z+1]
                            elif(x == 5):
                                longitude = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if(ord(data[add+z+k+1]) == 44):#,
                                        break
                                    if(ord(data[add+z+k+1]) == 46):#.
                                        continue
                                    longitude = (ord(data[add+z+k+1]) - 48) + longitude*10
                                
                                self.Lon = longitude / 1000000.0
                            elif(x == 6):
                                self.Lon_area = data[add+z+1]
                                return#Completion calculation
                        z = z + 1
            add = add + 1
    except TypeError:
        for i in range(0, BUFFSIZE-71):
            if((data[add]) == 36 and (data[add+1]) == 71 and ((data[add+2]) == 78 \
            or (data[add+2]) == 80) and (data[add+3]) == 82 and (data[add+4]) == 77\
            and (data[add+5]) == 67):
                    x = 0
                    z = 0
                    while(x < 12):
                        if(add+z >= BUFFSIZE-1):
                            return
                        if((data[add+z]) == 44):#,
                            x = x + 1
                            if(x == 1):
                                Time = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if((data[add+z+k+1]) == 44):#,
                                        break
                                    if((data[add+z+k+1]) == 46):#.
                                        break
                                    Time = ((data[add+z+k+1]) - 48) + Time*10
                                self.Time_H = Time/10000 + 8
                                self.Time_M = Time/100%100
                                self.Time_S = Time%100
                                if(self.Time_H >= 24):
                                     self.Time_H =  self.Time_H - 24
                            elif(x == 2):
                                if((data[add+z+1]) == 65):#A
                                    self.Status = 1
                                else:
                                    self.Status = 0
                            elif(x == 3):
                                latitude = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if((data[add+z+k+1]) == 44):#,
                                        break
                                    if((data[add+z+k+1]) == 46):#.
                                        continue
                                    latitude = ((data[add+z+k+1]) - 48) + latitude*10
                                self.Lat = latitude / 1000000.0
                            elif(x == 4):
                                self.Lat_area = data[add+z+1]
                            elif(x == 5):
                                longitude = 0
                                for k in range(0, BUFFSIZE-1):
                                    if(add+z+k >= BUFFSIZE-1):
                                        return
                                    if((data[add+z+k+1]) == 44):#,
                                        break
                                    if((data[add+z+k+1]) == 46):#.
                                        continue
                                    longitude = ((data[add+z+k+1]) - 48) + longitude*10
                                
                                self.Lon = longitude / 1000000.0
                            elif(x == 6):
                                self.Lon_area = data[add+z+1]
                                return#Completion calculation
                        z = z + 1
            add = add + 1
def  transformLat(self, x, y):
    ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 *math.sqrt(abs(x))
    ret += (20.0 * math.sin(6.0 * x * pi) + 20.0 * math.sin(2.0 * x * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(y * pi) + 40.0 * math.sin(y / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(y / 12.0 * pi) + 320 * math.sin(y * pi / 30.0)) * 2.0 / 3.0
    return ret

def transformLon(self, x, y):
    ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
    ret += (20.0 * math.sin(6.0 * x * pi) + 20.0 * math.sin(2.0 * x * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(x * pi) + 40.0 * math.sin(x / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(x / 12.0 * pi) + 300.0 * math.sin(x / 30.0 * pi)) * 2.0 / 3.0
    return ret

def bd_encrypt(self):
    x = self.Lon_Google
    y = self.Lat_Google
    z = math.sqrt(x * x + y * y) + 0.00002 * math.sin(y * x_pi)
    theta = math.atan2(y, x) + 0.000003 * math.cos(x * x_pi)
    self.Lon_Baidu = z * math.cos(theta) + 0.0065
    self.Lat_Baidu = z * math.sin(theta) + 0.006

def transform(self):
    dLat = self.transformLat(self.GPS_Lon - 105.0, self.GPS_Lat - 35.0)
    dLon = self.transformLon(self.GPS_Lon - 105.0, self.GPS_Lat - 35.0)
    radLat = self.GPS_Lat / 180.0 * pi
    magic = math.sin(radLat)
    magic = 1 - ee * magic * magic
    #math.sqrtMagic = math.sqrt(magic)
    #dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * math.sqrtMagic) * pi)
    #dLon = (dLon * 180.0) / (a / math.sqrtMagic * math.cos(radLat) * pi)
    sqrtMagic = math.sqrt(magic)
    dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi)
    dLon = (dLon * 180.0) / (a / sqrtMagic * math.cos(radLat) * pi)
    self.Lat_Google = self.GPS_Lat + dLat
    self.Lon_Google = self.GPS_Lon + dLon

def L76X_Baidu_Coordinates(self, U_Lat, U_Lon):
    self.GPS_Lat = U_Lat % 1 *100 / 60 + math.floor(U_Lat)
    self.GPS_Lon = U_Lon % 1 *100 / 60 + math.floor(U_Lon)
    self.transform()
    self.bd_encrypt()

def L76X_Google_Coordinates(self, U_Lat, U_Lon):
    self.GPS_Lat = U_Lat % 1 / 60 + U_Lat/1
    self.GPS_Lon = U_Lon % 1 / 60 + U_Lon/1
    self.transform()

def L76X_Set_Baudrate(self, Baudrate):
    self.config.Uart_Set_Baudrate(Baudrate)

def L76X_Exit_BackupMode(self):
    self.config.Force.value(1)
    time.sleep(1)
    self.config.Force.value(0)
    time.sleep(1)
    self.config.Force = Pin(self.config.FORCE_PIN,Pin.IN)

FYI here is info on the waveshare pico GPS https://www.waveshare.com/pico-gps-l76b.htm and their wiki: Pico-GPS-L76B - Waveshare Wiki

What are you using for a battery, and how is it connected?

I’ve got a couple 5volt 1 amp batteries and none work connected over usb power input. Doesn’t work with a wall adapter either. Works fine over usb connected to my 2013 MacBook.

Ok, I have no idea why its not working that way?

Just FYI, I have that display on the Omnibus with a PICO powered by a Pico LIPO Shim and a 750 MAH battery. The display is currently displaying the battery charge state. It works fine on battery when I press power the button on the LIPO Shim.

Thanks. Yea I can load up a different main.py and it works fine on battery. I think because the script is using serial port functionally it barfs when it doesn’t get any activity over the usb.

I bet your right. I’ve only done some very basic tinkering with my PICO’s, so far anyway.
Remark that part out? Or put in some error handling?

I have one the Adafruit GPS Breakouts. I had it wired right to a Pi’s GPIO And had it setup with a USB Serial TTL cable. Never really put it to any good proper use though. It came in a kit with a bunch of other stuff. It was fun to tinker with.