Monday 8 June 2020

GPS module

We need:
  • Raspberry Pi with Raspbian - in previous articles I described the installation based on Arch Linux distribution, unfortunately there is currently Arch Linux has no installer. Sorry, but I don't have time for low-level Arch Linux installation
  • USB GPS Receiver

Raspberry Pi with GPS Receiver



From bash we can list usb devices:
$ lsusb
USB devices list

In second line is GPS receiver (U-Blox AG)


Next step, we must install python module for decoding NMEA messages:
$ sudo pip install pynmea2

And we write first code:
import io
import serial
import pynmea2

GPS_RECIVER_PORT = '/dev/ttyACM0'

ser = serial.Serial(GPS_RECIVER_PORT, 9600, timeout=5.0)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

while 1:
    try:
        line = sio.readline()
        msg = pynmea2.parse(line)
        print(repr(msg))
     
    except serial.SerialException as e:
        print('Device error: {}'.format(e))
        break
We must set valid GPS reciver port definied in variable GPS_RECIVER_PORT

If we have done everything right after running the application we should see NMEA messages. To get the correct GPS position we have to wait a few minutes.

Examples messages NMEA

We can read position from GGA and GLL NMEA messages and velocity from VTG message.

Next step we will print only position and last speed:

import io
import serial
import pynmea2

GPS_RECIVER_PORT = '/dev/ttyACM0'

global lastVTG

ser = serial.Serial(GPS_RECIVER_PORT, 9600, timeout=5.0)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

while 1:
    try:
        line = sio.readline()
        msg = pynmea2.parse(line)
       
        if isinstance(msg, pynmea2.types.talker.VTG):
           lastVTG = msg

        if isinstance(msg, pynmea2.types.talker.GGA):
           print('lat={}, lng={}, speed={}, alt={}'.format(msg.latitude, msg.longitude, lastVTG.spd_over_grnd_kmph, msg.altitude))
     
    except serial.SerialException as e:
        print('Device error: {}'.format(e))
        break

We can track device location on the map at https://pilnuj.com/
Api is described on the site https://pilnuj.com/app/swagger-ui.html, generally we must send one POST with JSON data:
import io
import serial
import pynmea2
import requests

GPS_RECIVER_PORT = '/dev/ttyACM0'
DEVICE_UID = '123456789012345'
GEOLOCATION_SERVER_API = 'https://pilnuj.com/app/open-api/position'

global lastVTG


def sendPosition(msg):
   if lastVTG:
      response = requests.post(GEOLOCATION_SERVER_API, json={"imei": DEVICE_UID, "lat" : msg.latitude, "lng" : msg.longitude, "velocity" : lastVTG.spd_over_grnd_kmph, "altitude" : msg.altitude})


ser = serial.Serial(GPS_RECIVER_PORT, 9600, timeout=5.0)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

while 1:
    try:
        line = sio.readline()
        msg = pynmea2.parse(line)
       
        if isinstance(msg, pynmea2.types.talker.VTG):
           lastVTG = msg

        if isinstance(msg, pynmea2.types.talker.GGA):
           sendPosition(msg)
     
    except serial.SerialException as e:
        print('Device error: {}'.format(e))
        break

Important note, we must set random value DEVICE_UID, this value we must write as IMEI when you added new device on https://pilnuj.com

Adding device

sources:
https://gitlab.com/sebastian_dzk/letsmakearobot


links:
https://github.com/Knio/pynmea2
https://en.wikipedia.org/wiki/NMEA_0183
https://www.gpsinformation.org/dale/nmea.htm
https://pilnuj.com/