New Ticker

News Ticker
Epstien didn't kill himself.
Epstien didn't kill himself.
Epstien didn't kill himself.
Epstien didn't kill himself.

Friday, February 18, 2022

The first fun project - GPS

 Using Python and a G-Mouse. The G-Mouse is a very poorly named device as it has the same name as an actual computer mouse by Logitech but go figure - it's likely a Chinese thing.

This mundane little device can be hooked up to a computer and used to find the location of the computer via the satellite Global Positioning System to within about 20 feet.

This project was carried out on a laptop running Linux Mint. There are some things to do first or the whole thing won't work,

First... Install Putty on Linux.

Next, in Terminal, type sudo putty -serial /dev/ttyACM0

Then REBOOT the computer so that it'll take effect.

Next type sudo usermod -a -G dialout $(whoami)

That will gain you access to the serial port.

The following software (copied) from GitHub will read your GPS...

#!/usr/bin/env python3
# Original Code: https://gist.github.com/Lauszus/5785023#file-gps-py
# Created by: Kristian Sloth Lauszus

import time
import serial

def readString():
    while 1:
        while ser.read().decode("utf-8") != '$':  # Wait for the begging of the string
            pass  # Do nothing
        line = ser.readline().decode("utf-8")  # Read the entire string
        return line


def getTime(string, format, returnFormat):
    return time.strftime(returnFormat,
                         time.strptime(string, format))  # Convert date and time to a nice printable format


def getLatLng(latString, lngString):
    lat = latString[:2].lstrip('0') + "." + "%.7s" % str(float(latString[2:]) * 1.0 / 60.0).lstrip("0.")
    lng = lngString[:3].lstrip('0') + "." + "%.7s" % str(float(lngString[3:]) * 1.0 / 60.0).lstrip("0.")
    return lat, lng


def printRMC(lines):
    print("========================================RMC========================================")
    # print(lines, '\n')
    print("Fix taken at:", getTime(lines[1] + lines[9], "%H%M%S.%f%d%m%y", "%a %b %d %H:%M:%S %Y"), "UTC")
    print("Status (A=OK,V=KO):", lines[2])
    latlng = getLatLng(lines[3], lines[5])
    print("Lat,Long: ", latlng[0], lines[4], ", ", latlng[1], lines[6], sep='')
    print("Speed (knots):", lines[7])
    print("Track angle (deg):", lines[8])
    print("Magnetic variation: ", lines[10], end='')
    if len(
            lines) == 13:  # The returned string will be either 12 or 13 - it will return 13 if NMEA standard used is above 2.3
        print(lines[11])
        print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[12].partition("*")[0])
    else:
        print(lines[11].partition("*")[0])

    return


def printGGA(lines):
    print("========================================GGA========================================")
    # print(lines, '\n')
    print("Fix taken at:", getTime(lines[1], "%H%M%S.%f", "%H:%M:%S"), "UTC")
    latlng = getLatLng(lines[2], lines[4])
    print("Lat,Long: ", latlng[0], lines[3], ", ", latlng[1], lines[5], sep='')
    print("Fix quality (0 = invalid, 1 = fix, 2..8):", lines[6])
    print("Satellites:", lines[7].lstrip("0"))
    print("Horizontal dilution:", lines[8])
    print("Altitude: ", lines[9], lines[10], sep="")
    print("Height of geoid: ", lines[11], lines[12], sep="")
    print("Time in seconds since last DGPS update:", lines[13])
    print("DGPS station ID number:", lines[14].partition("*")[0])
    return


def printGSA(lines):
    print("========================================GSA========================================")
    # print(lines, '\n')

    print("Selection of 2D or 3D fix (A=Auto,M=Manual):", lines[1])
    print("3D fix (1=No fix,2=2D fix, 3=3D fix):", lines[2])
    print("PRNs of satellites used for fix:", end='')
    for i in range(0, 12):
        prn = lines[3 + i].lstrip("0")
        if prn:
            print(" ", prn, end='')
    print("\nPDOP", lines[15])
    print("HDOP", lines[16])
    print("VDOP", lines[17].partition("*")[0])
    return


def printGSV(lines):
    if lines[2] == '1':  # First sentence
        print("========================================GSV========================================")
    else:
        print("===================================================================================")
    # print(lines, '\n')

    print("Number of sentences:", lines[1])
    print("Sentence:", lines[2])
    print("Satellites in view:", lines[3].lstrip("0"))
    for i in range(0, int(len(lines) / 4) - 1):
        print("Satellite PRN:", lines[4 + i * 4].lstrip("0"))
        print("Elevation (deg):", lines[5 + i * 4].lstrip("0"))
        print("Azimuth (deg):", lines[6 + i * 4].lstrip("0"))
        print("SNR (higher is better):", lines[7 + i * 4].partition("*")[0])
    return


def printGLL(lines):
    print("========================================GLL========================================")
    # print(lines, '\n')

    latlng = getLatLng(lines[1], lines[3])
    print("Lat,Long: ", latlng[0], lines[2], ", ", latlng[1], lines[4], sep='')
    print("Fix taken at:", getTime(lines[5], "%H%M%S.%f", "%H:%M:%S"), "UTC")
    print("Status (A=OK,V=KO):", lines[6])
    if lines[7].partition("*")[0]:  # Extra field since NMEA standard 2.3
        print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[7].partition("*")[0])
    return


def printVTG(lines):
    print("========================================VTG========================================")
    # print(lines, '\n')

    print("True Track made good (deg):", lines[1], lines[2])
    print("Magnetic track made good (deg):", lines[3], lines[4])
    print("Ground speed (knots):", lines[5], lines[6])
    print("Ground speed (km/h):", lines[7], lines[8].partition("*")[0])
    if lines[9].partition("*")[0]:  # Extra field since NMEA standard 2.3
        print("Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid):", lines[9].partition("*")[0])
    return


def checksum(line):
    checkString = line.partition("*")
    checksum = 0
    for c in checkString[0]:
        checksum ^= ord(c)

    try:  # Just to make sure
        inputChecksum = int(checkString[2].rstrip(), 16);
    except:
        print("Error in string")
        return False

    if checksum == inputChecksum:
        return True
    else:
        print("=====================================================================================")
        print("===================================Checksum error!===================================")
        print("=====================================================================================")
        print(hex(checksum), "!=", hex(inputChecksum))
        return False

if __name__ == '__main__':
    ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)  # Open Serial port
    try:
        while True:
            line = readString()
            lines = line.split(",")
            if checksum(line):
                if lines[0] == "GPRMC":
                    printRMC(lines)
                    pass
                elif lines[0] == "GPGGA":
                    printGGA(lines)
                    pass
                elif lines[0] == "GPGSA":
                    # printGSA(lines)
                    pass
                elif lines[0] == "GPGSV":
                    # printGSV(lines)
                    pass
                elif lines[0] == "GPGLL":
                    printGLL(lines)
                    pass
                elif lines[0] == "GPVTG":
                    printVTG(lines)
                    pass
                else:
                    print("\n\nUnknown type:", lines[0], "\n\n")
    except KeyboardInterrupt:
        print('Exiting Script') 

If that doesn't work for you then try the following...

sudo apt-get install gpsd gpsd-clients

Then

sudo cat /dev/ttyACM0

That should get you a result.

The results produced by the Python code are as follows

========================================RMC========================================

Fix taken at: Tue Feb 08 15:41:16 2022 UTC

Status (A=OK,V=KO): A

Lat,Long: 47.8076043N, 7.2157055W

Speed (knots): 0.437

Track angle (deg): 

Magnetic variation:  

Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid): A

========================================VTG========================================

True Track made good (deg):  T

Magnetic track made good (deg):  M

Ground speed (knots): 0.437 N

Ground speed (km/h): 0.809 K

Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid): A

========================================GGA========================================

Fix taken at: 15:41:16 UTC

Lat,Long: 47.8076043N, 7.2157055W

Fix quality (0 = invalid, 1 = fix, 2..8): 1

Satellites: 3

Horizontal dilution: 4.91

Altitude: 67.4M

Height of geoid: -32.3M

Time in seconds since last DGPS update: 

DGPS station ID number: 

========================================GLL========================================

Lat,Long: 47.8076043N, 7.2157055W

Fix taken at: 15:41:16 UTC

Status (A=OK,V=KO): A

Mode (A=Autonomous, D=Differential, E=Estimated, N=Data not valid): A

It can take a few minutes for the GPS mouse to lock onto satellites and produce a result so don't be upset if the Python code crashes the first few times you try to run it.