melopero-ubx

A module to create and parse messages of the UBX protocol


License
MIT
Install
pip install melopero-ubx==0.0.1

Documentation

Melopero_SAM-M8Q_Arduino_Library

A library for interfacing the Melopero SAM-M8Q Multi GNSS breakout board with a Raspberry Pi.
If you were looking for the Arduino library click HERE

Melopero SAM M8Q

melopero logo

Pinouts

Melopero SAM-M8Q Description
3V3 Input power pin. Apply 3.3V to this pin
SCL I2C Serial CLock pin
SDA I2C Serial DAta pin
GND Ground pin
INT External Interrupt pin (INPUT)
SAF SAFEBOOT_N pin, for future service, updates and reconfiguration
RST RESET pin, INPUT, Active Low
PPS Pulse Per Second pin, OUTPUT, connected to the Blue LED
VBA V_BACKUP pin, INPUT. This pin accepts a voltage in the 3.3V-6V range. By applying a voltage to this pin, you will automatically disable the coin cell battery and avoid the installation of the optional CR1220 battery holder, while still allowing a warm start of the GNSS module.

FTDI header

At the top of the board you'll find the pinout for connecting a FTDI cable (only FTDI cables with 3.3V data and power line!)

Getting Started

Prerequisites

You will need:

Connect the sensor to the Raspberry Pi

You can find a description of the GPIO connector of the Raspberry Pi HERE
(use only 3.3V power and logic, DO NOT connect this sensor board directly to 5V)
The SAM-M8Q communicates over I2C:

Melopero SAM-M8Q Raspberry Pi
3V3 3.3V
SCL SCL
SDA SDA
GND GND

Installing

You can install the melopero-samm8q module by typing this line in the terminal:

sudo pip3 install melopero-samm8q

Module description

The module contains a class to easily access the SAM m8Q's gps functions.

Usage

First you need to import the module in your file:

import melopero_samm8q as mp #nome provvisorio

Then you can create a SAM_M8Q object and access it's methods, the gps object will be initialized with the i2c address set to 0x42 and the i2c bus to 1 alias (dev/i2c-1) which is the standard i2c bus in a Raspberry pi.

sensor = mp.SAM_M8Q()

Alternatively you can modify it's parameters by typing

sensor = mp.SAM_M8Q(i2c_addr = myaddress, i2c_bus = mybus)

UBX protocol

The module uses the UBX protocol over I2C to comunicate with the device. The NMEA messages are not disabled by default, they can be disabled by calling sensor.ubx_only(). This method causes the device to comunicate only through the UBX protocol.

The most used/useful UBX messages are implemented in the module, if someone wants to send other/custom messages to the device they can be easily crafted and parsed through the UBX_PROTOCOL module.

Features
Communication

There are several methods to send and receive messages:

#*** SENDING MESSAGES ***
device.write_message(message)

#*** RECEIVING MESSAGES ***
device.read_message()
device.wait_for_message(time_out_s = 1, interval_s = 0.01, msg_cls = None, msg_id = None)
device.wait_for_acknowledge(msg_cls, msg_id)
PVT

The results of a navigation solution are stored in a dictionary: pvt_data. The dictionary maps strings (the name of the attributes) to their respective values. For example this line returns the longitude : device.pvt_data["longitude"]. To update the data stored in pvt_data the method device.get_pvt(polling = True, time_out_s = 1) must be called. This method updates the data and returns the pvt_data dictionary, therefore this two codes are equivalent:

info = device.get_pvt()
print("We are in {}!".format(info["year"]))
device.get_pvt()
print("We are in {}".format(device.pvt_data["year"]))
Crafting messages

To use the UBX_PROTOCOL module it must be imported by typing the following line :

import UBX_PROTOCOL as ubx

Then a message can be created with the function:

ubx.compose_message(msg_cls, msg_id, length = 0, payload = None)

The function returns the message which can be sent with the method : sensor.write_message(message). If the lenght and the payload are not specified a polling message (with no payload, used to poll messages and data) is created and returned.

Example

The following example, will write to a file the coordinates and time of the device every 5 seconds for 25 minutes.

import SAM_M8Q
import ubx
import time
import sys

dev = SAM_M8Q()
dev.ubx_only()
dev.wait_for_acknowledge(ubx.CFG_CLASS, ubx.CFG_PRT)
dev.set_message_frequency(ubx.NAV_CLASS, ubx.NAV_PVT, 1)
dev.wait_for_acknowledge(ubx.CFG_CLASS ,ubx.CFG_MSG)
dev.set_measurement_freq(500, 1)
dev.wait_for_acknowledge(ubx.CFG_CLASS, ubx.CFG_RATE)

#One Measurement every 5 seconds for 300 times
#means 5 * 300 seconds = 1500 seconds = 25 minutes
log_file_name = "log_{}.txt".format(int(time.time() % 1000))
for i in range(300):
    print("Measurement {} / 300".format(i))
    try:
        info = dev.get_pvt() #returns a dictionary containing the PVT data
        if info is not None:
            with open(log_file_name, 'a') as log_file:
              log_file.write("[{}/{}/{}] {}h:{}m:{}s".format(info['year'], info['month'], info['day'],
                                 info['hour'], info['minute'], info['second']))
              log_file.write('\n')
              log_file.write("Longitude : ")
              log_file.write(str(info["longitude"]))
              log_file.write('\n')
              log_file.write("Latitude : ")
              log_file.write(str(info["latitude"]))
              log_file.write('\n')
              log_file.write('\n')
              log_file.flush()
    except:
        print("Unexpected error:", sys.exc_info()[0])

    time.sleep(5)

Connection with a Raspberry Pi