1

I am using a NEO-8M Satellite Positioning Module on a Raspberry PI. I am trying to read data off the device using python. I am new to the Raspberry PI and Python. I can read data from the NEO-8M GPS module. My code is as follows:

import serial
gps = serial.Serial("/dev/serial0", baudrate=9600, timeout=0.5)
myRawData = gps.readline()
print(myRawData)
myOutputData = str(myRawData)
print(myOutputData)

The output data is as follows:

b'\xb5b\x01\x07\\\x00\xb0\xc7P\x00\xdf\x07\n'
b'\xb5b\x01\x07\\\x00\xb0\xc7P\x00\xdf\x07\n'

I cannot identify the format that the string is in. I am not sure how to convert the data to a string for further processing.

Any help would be appreciated.

Solved. Shout out to "Dougie". His suggestion to use gpsd has negated my problem.

6
  • 1
    Have you looked at using gpsd (rather than reading the raw device) to make everything easier? If you already have gpsd then sudo gpsctl -n resets the GPS device so that raw access works. forums.raspberrypi.com/viewtopic.php?t=331525
    – Dougie
    May 2, 2022 at 21:37
  • 1
    Serial sends/receives byte data. You need to convert to/from Unicode.
    – Milliways
    May 2, 2022 at 22:10
  • Milliways: Please excuse my ignorance. What would the PYTHON code look like to convert the data received into a useable format? May 2, 2022 at 22:19
  • Dougie. I am stuck on the PYTHON code: mport gps3. What library do I need to install? May 2, 2022 at 22:21
  • "What would the PYTHON code look like to convert the data received into a useable format?" this is a programming question - best asked on stackoverflow.com, but they expect people to do some research - there will be thousands of examples. In your case a basic python course. You ALSO need to know what the device outputs; I expect digits not strings.
    – Milliways
    May 3, 2022 at 2:02

1 Answer 1

3

I tend to use the pynmea2 library to parse the GPS data:

import serial,time,pynmea2

port = '/dev/serial0'
baud = 9600

serialPort = serial.Serial(port, baudrate = baud, timeout = 0.5)
while True:
    
    str = ''
    try:
        str = serialPort.readline().decode().strip()
    except Exception as e:
        print(e)
    #print(str)
    
    if str.find('GGA') > 0:
        try:
            msg = pynmea2.parse(str)
            print(msg.timestamp,'Lat:',round(msg.latitude,6),'Lon:',round(msg.longitude,6),'Alt:',msg.altitude,'Sats:',msg.num_sats)
        except Exception as e:
            print(e)
    time.sleep(0.1)

If using a USB GPS check the Pi has detected with dmesg:

pi@raspberrypi:~ $ dmesg
[243897.914645] usb 1-1.1: USB disconnect, device number 21
[243917.925037] usb 1-1.1: new full-speed USB device number 22 using xhci_hcd
[243918.059453] usb 1-1.1: New USB device found, idVendor=1546, idProduct=01a8, bcdDevice= 3.01
[243918.059461] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[243918.059467] usb 1-1.1: Product: u-blox GNSS receiver
[243918.059472] usb 1-1.1: Manufacturer: u-blox AG - www.u-blox.com
[243918.062126] cdc_acm 1-1.1:1.0: ttyACM0: USB ACM device

Check your GPS is in NMEA mode (i'm using ttyACM0). All of the GPS devices that I have used are either already in this mode or automatically switch to NMEA when I start reading serial data:

pi@raspberrypi:~ $ gpsctl
/dev/ttyACM0 identified as a NMEA0183 at 9600 baud.

Or specify port:

pi@raspberrypi:~ $ gpsctl /dev/ttyACM0
/dev/ttyACM0 identified as a NMEA0183 at 9600 baud.

Or with debug mode and specify port:

pi@raspberrypi:~ $ gpsctl -D 4 /dev/ttyACM0
libgps: gps_sock_open(localhost, 2947)
libgps: netlib_connectsock() returns socket on fd 3
libgps: gps_read() begins
libgps: gps_unpack({"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_min)r":12}
libgps: gps_unpack() segment parse '{"class":"VERSION","release":"3.17","rev":"3.17","proto_ma'or":3,"proto_minor":12}
flags: (0x10000000) {VERSION}
VERSION: release=3.17 rev=3.17 proto=3.12
libgps: final flags: (0x10000000) (null)
libgps: gps_read() -> 84 ({PACKET|VERSION})
libgps: gps_read() begins
libgps: gps_unpack({"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"2022-05-03T10:46:53.009Z","flags":1,"native":0,"bps":9600,"parity")"N","stopbits":1,"cycle":1.00}]}
libgps: gps_unpack() segment parse '{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"2022-05-03T10:46:53.009Z","flags":1,"native":0,"b's":9600,"parity":"N","stopbits":1,"cycle":1.00}]}
flags: (0x100000) {DEVICELIST}
DEVICELIST:1 devices:
1: path='/dev/ttyACM0' driver='NMEA0183'
libgps: final flags: (0x100000) (null)
libgps: gps_read() -> 204 ({DEVICELIST|PACKET})
/dev/ttyACM0 identified as a NMEA0183 at 9600 baud.
libgps: gps_close()
pi@raspberrypi:~ $ 

If your GPS is in binary/native mode you will see something like:

pi@raspberrypi:~ $ gpsctl /dev/ttyACM0
/dev/ttyACM0 identified as a u-blox SW ROM CORE 3.01 (107888),HW 00080000,FWVER=SPG 3.01,PROTVER=18 at 9600 baud.

Or with debug info:

pi@raspberrypi:~ $ gpsctl -D 4 /dev/ttyACM0
libgps: gps_sock_open(localhost, 2947)
libgps: netlib_connectsock() returns socket on fd 3
libgps: gps_read() begins
)ibgps: gps_unpack({"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_minor":12}
'ibgps: gps_unpack() segment parse '{"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_minor":12}
flags: (0x10000000) {VERSION}
VERSION: release=3.17 rev=3.17 proto=3.12
libgps: final flags: (0x10000000) (null)
libgps: gps_read() -> 84 ({PACKET|VERSION})
libgps: gps_read() begins
libgps: gps_unpack({"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"u-blox","subtype":"SW ROM CORE 3.01 (107888),HW 00080000,FWVER=SPG 3.01,PROTVER=18","activated":"2022-05-03T11:08:01.042Z","flags":1,"native":0,"bps":9600,"parity":"N",")topbits":1,"cycle":1.00,"mincycle":0.25}]}
libgps: gps_unpack() segment parse '{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"u-blox","subtype":"SW ROM CORE 3.01 (107888),HW 00080000,FWVER=SPG 3.01,PROTVER=18","activated":"2022-05-03T11:08:01.042Z","flags":1,"native":0,"bps":96'0,"parity":"N","stopbits":1,"cycle":1.00,"mincycle":0.25}]}
flags: (0x100000) {DEVICELIST}
DEVICELIST:1 devices:
1: path='/dev/ttyACM0' driver='u-blox'
libgps: final flags: (0x100000) (null)
libgps: gps_read() -> 294 ({DEVICELIST|PACKET})
/dev/ttyACM0 identified as a u-blox SW ROM CORE 3.01 (107888),HW 00080000,FWVER=SPG 3.01,PROTVER=18 at 9600 baud.
libgps: gps_close()
pi@raspberrypi:~ $ 

Switch to NMEA mode with:

pi@raspberrypi:~ $ gpsctl -n -D 4 /dev/ttyACM0
libgps: gps_sock_open(localhost, 2947)
libgps: netlib_connectsock() returns socket on fd 3
libgps: gps_read() begins
)ibgps: gps_unpack({"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_minor":12}
'ibgps: gps_unpack() segment parse '{"class":"VERSION","release":"3.17","rev":"3.17","proto_major":3,"proto_minor":12}
flags: (0x10000000) {VERSION}
VERSION: release=3.17 rev=3.17 proto=3.12
libgps: final flags: (0x10000000) (null)
libgps: gps_read() -> 84 ({PACKET|VERSION})
libgps: gps_read() begins
libgps: gps_unpack({"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"2022-05-03T11:26:54)043Z","flags":1,"native":0,"bps":9600,"parity":"N","stopbits":1,"cycle":1.00}]}
libgps: gps_unpack() segment parse '{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"20'2-05-03T11:26:54.043Z","flags":1,"native":0,"bps":9600,"parity":"N","stopbits":1,"cycle":1.00}]}
flags: (0x100000) {DEVICELIST}
DEVICELIST:1 devices:
1: path='/dev/ttyACM0' driver='NMEA0183'
libgps: final flags: (0x100000) (null)
libgps: gps_read() -> 204 ({DEVICELIST|PACKET})
libgps: gps_read() begins
libgps: gps_unpack({"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"2022-05-03T11:26:58.045Z","flags":1,"native":0,"b)s":9600,"parity":"N","stopbits":1,"cycle":1.00}
libgps: gps_unpack() segment parse '{"class":"DEVICE","path":"/dev/ttyACM0","driver":"NMEA0183","activated":"2022-05-03T11:26:58.045Z","flags':1,"native":0,"bps":9600,"parity":"N","stopbits":1,"cycle":1.00}
flags: (0x180000) {DEVICE|DEVICELIST}
DEVICE: Device is '/dev/ttyACM0', driver is 'NMEA0183'
DEVICELIST:1 devices:
1: path='/dev/ttyACM0' driver='NMEA0183'
libgps: final flags: (0x180000) (null)
libgps: gps_read() -> 172 ({DEVICE|DEVICELIST|PACKET})
libgps: gps_close()

USB port may then be held by gpsd:

pi@raspberrypi:~ $ sudo lsof /dev/ttyACM0
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
gpsd    537 gpsd    8u   CHR  166,0      0t0  472 /dev/ttyACM0

Kill that gpsd process using the PID value with:

sudo kill 537
1
  • I have implemented your code "as is". And get the following error message: 'utf-8' codec can't decode byte 0xf0 in position 4: invalid continuation byte 'utf-8' codec can't decode byte 0xb5 in position 0: invalid start byte This is my problem, I cannot read the string in a useable format. May 2, 2022 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.