Sony’s Spresense board sports many powerful features; one of them is GNSS connectivity, which provides precise satellite-fed data on the current position on the board, along with other useful information (for example, the current time).
Zerynth offers an example that can get you started with Spresense’s GNSS functionality in seconds in a few lines of Python code.
If you haven’t done that already, make sure to connect, register and virtualize your board with Zerynth Studio. You can find more info on how to get started with Sony Spresense and Zerynth in this tutorial.
Then just clone the “GNSSData” example from Zerynth’s Example Library, connect the board to your computer, and uplink the program to the board. You can find more info about the library of this driver in the official documentation.
After opening the Serial Monitor in Zerynth Studio, you should see the value acquired from the satellites:
Here is the example’s code:
import gc
import streams
from sony.cxd5602gnss import gnss
# dictionary to convert from satellite type to string
sattype2string = {
gnss.SAT_GPS: "GPS",
gnss.SAT_GLONASS: "GLONASS",
gnss.SAT_SBAS: "SBAS",
gnss.SAT_QZ_L1CA: "QZ_L1CA",
gnss.SAT_IMES: "IMES",
gnss.SAT_QZ_L1S: "QZ_L1S",
gnss.SAT_BEIDOU: "BEIDOU",
gnss.SAT_GALILEO: "GALILEO"
}
streams.serial()
print("> GNSS init")
gnss.init()
while True:
gnss.wait()
# filter data to keep only position, datetime and satellites' info
data = gnss.read(read_filter=(gnss.FILTER_RECEIVER_POSITION | gnss.FILTER_RECEIVER_DATETIME | gnss.FILTER_SATS_DATA))
if data.receiver.position.pos_dataexist:
print("> POSITION:")
print(">> latitude:", data.receiver.position.latitude)
print(">> longitude:", data.receiver.position.longitude)
print(">> altitude:", data.receiver.position.altitude)
else:
print("> POSITION not available")
print("> DATETIME:")
print(">> date.year:", data.receiver.datetime.date.year)
print(">> date.month:", data.receiver.datetime.date.month)
print(">> date.day:", data.receiver.datetime.date.day)
print(">> time.hour:", data.receiver.datetime.time.hour)
print(">> time.minute:", data.receiver.datetime.time.minute)
print(">> time.sec:", data.receiver.datetime.time.sec)
print(">> time.usec:", data.receiver.datetime.time.usec)
if data.sats:
# at least one satellite available
print("> SATS:")
for sat_i, sat in enumerate(data.sats):
print(">> sat[%i].type:" % sat_i, sattype2string[sat.type])
print(">> sat[%i].siglevel:" % sat_i, sat.siglevel)
Of course, this is just the start: you can use the data collected by the board to power an application that performs live tracking on a map!
Let’s do that with Jupyter.
First of all, we need to install Jupyter, along with gmaps and PySerial:
$ sudo pip3 install jupyterlab gmaps pyserial
$ jupyter nbextension enable --py --sys-prefix widgetsnbextension
$ jupyter nbextension enable --py --sys-prefix gmaps
Once that’s done, we can uplink the following firmware to the Spresense board:
import streams
import json
from sony.cxd5602gnss import gnss
sattype2string = {
gnss.SAT_GPS: "GPS",
gnss.SAT_GLONASS: "GLONASS",
gnss.SAT_SBAS: "SBAS",
gnss.SAT_QZ_L1CA: "QZ_L1CA",
gnss.SAT_IMES: "IMES",
gnss.SAT_QZ_L1S: "QZ_L1S",
gnss.SAT_BEIDOU: "BEIDOU",
gnss.SAT_GALILEO: "GALILEO"
}
data_ch = streams.serial(SERIAL0)
gnss.init()
while True:
gnss.wait()
gnss_data = gnss.read(read_filter=(gnss.FILTER_TIMESTAMP | gnss.FILTER_RECEIVER_POSITION_PRECISION |
gnss.FILTER_RECEIVER_DATETIME | gnss.FILTER_SATS_DATA | gnss.FILTER_RECEIVER_SATS))
data = {}
if gnss_data.sats:
data['sats'] = {}
for sat in gnss_data.sats:
#print("> sat type:", sat.type)
sat_string = sattype2string[sat.type]
if sat_string in data['sats']:
data['sats'][sat_string] += 1
else:
data['sats'][sat_string] = 1
if gnss_data.receiver.position.pos_dataexist:
data['lat'] = gnss_data.receiver.position.latitude
data['lon'] = gnss_data.receiver.position.longitude
data_ch.write(json.dumps(data))
data_ch.write("\n")
And then, by running the following Jupyter notebook, we can see the position of the Spresense on a map in real-time:
import gmaps
import gmaps.datasets
gmaps.configure(api_key="your Google Cloud API goes here")
map_fig = gmaps.figure(center=(43.72, 10.41), zoom_level=14)
map_drawing = gmaps.drawing_layer(features=[])
map_fig.add_layer(map_drawing)
map_fig
To generate a Google Cloud API key follow this tutorial.
You can change the values of the center and the zoom level to customize the display of the map:
map_fig = gmaps.figure(center=(43.72, 10.41), zoom_level=14)
For this second script you will need to ensure that the path to the serial device is the right one; in our case, it’s /dev/tty.SLAB_USBtoUART.
import json
from serial import Serial
from IPython.display import clear_output
spresense_ch = Serial("/dev/tty.SLAB_USBtoUART", 115200)
while True:
gnss_data = json.loads(spresense_ch.readline())
clear_output(wait=True)
if 'sats' in gnss_data:
print("\n> Visible satellites")
for sat_type, sat_num in gnss_data['sats'].items():
print("> %s: %i" % (sat_type, sat_num))
if 'lat' in gnss_data:
spresense_position_mark = gmaps.Marker((gnss_data['lat'], gnss_data['lon']), info_box_content='Zerynth Spresense')
map_drawing.features = [spresense_position_mark]
This is what that looks like:
Note that you might have to wait a bit for the Spresense to acquire enough satellite signals for it to be able to display the right position.
Here are some general things to be aware of when testing your GNSS application:- The receiver needs to find at least four satellites to be able to determine its position.
- Make sure you have a clear sky. The receiver will have a hard time finding a satellite if there is something blocking the way, such as a roof.
- Try to avoid obstructions around you. Satellites may be positioned low towards the horizon and e.g. buildings with lots of concrete, metal girders etc could block them from the receiver.
- Depending on the conditions and the state of the device it might take minutes to get a fix, so please be patient.
If you want to add more sensors to the mix, you can add the data you want to show to the Python dictionary that the Spresense board sends over the serial connection, and then visualize it with Jupyter.
Comments