GNSS data

The VBOX Touch allows for the manipulation of data that you receive from the GNSS engine as well as logging this data for later analysis. Here we will talk about how you can get this data and use it in your program.

GNSS data

Initialisation

To use vbox sample data you first need to know how to get it. This is done using the vbox module. This first needs to be initialised with the correct configuration for it to start storing the data it is receiving from the GNSS engine.

import vbox
vbox.init(vbox.VBOX_SRC_GNSS_BASIC)

On startup, the initialisation flag will be vbox.VBOX_SRC_NONE which logs all data other than flags and sample_id as 0s. As we want more data you need to set its source (SRC) as the GNSS engine.

Note:

You may find you get an error of the GNSS engine not being ready yet. To fix this you need to check that its status is ready:

import gnss, vbox
while (gnss.init_status() > 0):
  pass

vbox.init(vbox.VBOX_SRC_GNSS_BASIC)

Another error you may get is “VBox source already configured”. This is because you have initialised the vbox task in this power cycle already. To check use the following:

try:
   vbox.init(vbox.VBOX_SRC_GNSS_BASIC)
except Exception as e:
   if str(e) == 'VBox source already configured': # Ignore if already configured. Should never get into this state on a built version
      pass
   else:
      raise Exception(str(e))

Getting data

When we get data from the GNSS engine we get this as a ‘Sample’. These samples are generated by the VBOX Touch at a frequency that is determined by the GNSS engine (typically 10Hz, 25Hz is for the F9 engine).

2 different functions can be used to get the samples of data. These return slightly different data depending on the GNSS engine and the function used, the full list can be found in the table below.

The first function is:

vbox.get_sample()

This returns the current sample that the data is on. However, it is an older function at the data it returns is of lower precision than the following function. It is also not advised to use this one if you are displaying data to the user. This is because if you fall behind on the processing then you lose a sample of data.

Note:

If you are still receiving only 0s then it is likely because you do not have a sats connection.

Instead we recommend you use this newer function, get_sample_hp (high-precision).

vbox.get_sample_hp()

This function stores the samples that you haven’t read in yet in a buffer and will give you the next sample in the buffer of samples. The reason that get_sample() was not updated to do this is to maintain backward compatibility.

Note:

If you are on old firmware then you may not have the get_sample_hp() function as it was only released in 1.5.

To then ensure that this doesn’t fall behind samples and then give old samples you can use this code snippet that we use frequently in a lot of our apps.

processed = 1
while processed:
   sample = vbox.get_sample_hp(False)
   if sample is not None:
      process_sample(sample)
   else:
      processed = 0

This will pass the sample to a process_sample function which you can set up to do anything you want. Here are some examples of what to do with this data.

Data callback

To make getting this data easier there is a callback for when a new GNSS sample has been received. This means that you do not have to put the loop, from the above section, in the main/run loop of your program. You should put this loop in your callback function instead.

vbox.set_new_data_callback(new_sample_cb)

It should look something like this:

def new_sample_cb():
   processed = 1
   while processed:
      sample = vbox.get_sample_hp(False)
      if sample is not None:
         process_sample(sample)
      else:
         processed = 0

Storing the data

Storing GNSS data on a .vbo file can be done automatically. This is shown in the next section. However, you can also store this data by writing it to the SD card manually.

Once you have got the data, you will need to store it to be able to process it. As sample is a named tuple it is easy to reference a term in a sample. Store the sample and then call sample.NAME where NAME is the term you want.

sample = vbox.get_sample_hp()
sats = sample.sats_used
lat = sample.lat_degE7
lng = sample.lng_degE7
velocity = sample.speed_gnd_smooth_mps
heading = sample.heading_deg
height = sample.alt_msl_m
vertical_velocity = sample.speed_up_mps

This gets the sample and stores some of the bits of the sample in new variables for ease of use later.

Before we can process this though we are likely going to need to access the data from different functions. This is done using a class attributes as this gives much better scope, context and helps to limit accessibility than a global variable.

class Data: # class which contains the attributes that will need to be accessed from multiple classes.
   sats = 0
   lat = 0
   lng = 0
   velocity = 0
   heading = 0
   height = 0
   vertical_velocity = 0

vbox.set_new_data_callback(new_sample_cb) # set the GNSS sample callback

def new_sample_cb(): # GNSS sample callback
   processed = 1
   while processed: # stores the data and then will loop around until there is no data left in the buffer that it hasn't previously stored.
      sample = vbox.get_sample_hp(False)
      if sample is not None:
         store_data(sample)
      else:
         processed = 0

def store_data(sample):
   Data.sats = sample.sats_used
   Data.lat = sample.lat_degE7
   Data.lng = sample.lng_degE7
   Data.velocity = sample.speed_gnd_smooth_mps
   Data.heading = sample.heading_deg
   Data.height = sample.alt_msl_m
   Data.vertical_velocity = sample.speed_up_mps

Processing sample data

Once you have received the data from the GNSS engine and stored sample data then the aim is to do something with it.

There are many things you can do with this data. Most commonly though you will want to display the data to the user of the app. However, performing some form of calculation on it so that it gives more/different information is very common too.

A combination of both is also frequent i.e changing the unit of the data you have received.

velocity_in_mph = Data.velocity * 2.23694

gui.show([
   [gui.CTRL_TEXT, 400, 240, 30, 1536, velocity_in_mph],
])

This will display the velocity in mph as supposed to in m/s. You may notice that this is not updating however when you receive new samples. This is because the variable is immutable and so cannot be dynamically changed. More about this and how to use mutable variables can be found in the Graphics section under Interactive UI

Another common example of data that needs to be processed is time. You may notice that currently, we are not storing time. This is because the time given to you by the GNSS engine is in ms and so is very difficult for a user to understand without processing it further.

The code below shows you how to convert this using the function tod_to_hmsm(). It then displays this to the user using both the clock widget and a digital clock using text.

import vbox
import gui

class Data:
   digital_time_gui_l = [
      gui.SUBLIST,
      [gui.CTRL_TEXT, 780, 160, 31, 2048, [' ']],
   ]

   clock_time_gui_l = [gui.CTRL_CLOCK, 200, 200, 100, 1, 1, 1, 100]

def process_sample(sample): # manipulates and updates the data
   Data.clock_time_gui_l[7] = int(sample.tod_ms/1000) # the clock widget takes data in seconds not ms

   time = tod_to_hmsm(sample.tod_ms) # convert to h m s ms
   Data.digital_time_gui_l[1][5][0] = '{:02d}'.format(time[0])+':'+'{:02d}'.format((time[1]))+':'+'{:02d}'.format((int(time[2])))

   gui.redraw()

def new_sample_cb(): # GNSS sample callback
   processed = 1
   while processed:
      sample = vbox.get_sample_hp(False)
      if sample is not None:
            process_sample(sample)
      else:
            processed = 0

def tod_to_hmsm(ms):
   hmsm = 4 * [None]
   hmsm[0] = ms // 3600000
   ms -= (hmsm[0] * 3600000)
   hmsm[1] = ms // 60000
   ms -= (hmsm[1] * 60000)
   hmsm[2] = ms // 1000
   ms -= (hmsm[2] * 1000)
   hmsm[3] = ms
   return hmsm

vbox.init(vbox.VBOX_SRC_GNSS_BASIC)
vbox.set_new_data_callback(new_sample_cb) # set the GNSS sample callback

gui.show([
   Data.digital_time_gui_l,
   Data.clock_time_gui_l,
])

Note that the clock will likely be the incorrect time until you get sats. Then it will be in UTC.

There are many more examples of ways to display data on the screen as can be seen in the example apps on the VBOX Touch App Store. There are frameworks for different data displays also for example the graph screen framework.

VBOX sample data

Different GNSS engines will give different data at different frequencies. If you don’t know what GNSS Engine you are using and want to find out use the unit info framework.

Data title

Type

Description

Data differences

year

int

The year.

All

month

int

The month.

All

day

int

The day.

All

tod_ms

int

The GPS time of day in ms from midnight.

All

lat_minE5

int

The latitude position.

get_sample()

lng_minE5

int

The longitude position.

get_sample()

lat_degE7

int

The latitude position.

get_sample_hp()

lng_degE7

int

The longitude position.

get_sample_hp()

lat_adj_degE9

int

The latitude position.

get_sample_hp()

lng_adj_degE9

int

The longitude position.

get_sample_hp()

alt_msl_m

int

The altitude above mean sea level in m.

All

heading_deg

int

The heading in degrees.

All

speed_gnd_mps

int

The ground speed in metres per second.

All

speed_up_mps

int

The vertical velocity in metres per second.

All

flags

int

The active sample flags.
See flag types for details.
All

sats_used

int

The number of sats that are connected.

All

GPS

int

The amount of GPS sats that are connected.

VBOX Touch V2

Galileo

int

The amount of Galileo sats that are connected.

VBOX Touch V2

GLONASS

int

The amount of GLONASS sats that are connected.

VBOX Touch V2

BeiDou

int

The amount of BeiDou sats that are connected.

VBOX Touch V2

fix_type

int

The fix type of the sats.

All

update_period_ms

int

The last sample period in ms.

All

valid_sample_cnt

int

The number of consecutive valid samples.

All

speed_gnd_smooth_mps

int

The smoothed ground speed in metres per second.

All

speed_gnd_disp_mps

int

The display ground speed in ms.

All

lngacc_smooth_mps2

int

The lateral acceleration.

All

latacc_smooth_mps2

int

The longitudinal acceleration.

All

total_dist_m

int

The distance travelled since boot in m.

All

state_period_ms

int

The time in state (+ = moving, - = stationary) in ms.

All

x_m

int

The X offset from base point in m.

All

y_m

int

The Y offset from base point in m.

All

prev_x_m

int

The previous sample X offset from base point in m.

All

prev_y_m

int

The previous sample Y offset from base point in m.

All

lap_time_ms

int

The lap time in milliseconds.

All

plt_delta_t_ms

int

The predictive lap timing Δt in ms.

All

plt_delta_v_mps

int

The predictive lap timing Δv in ms.

All

sample_id

int

The sample id.
This is used to sync data. This will loop from 0-128.
get_sample_hp()

flag types

Flag Name

Bit Value

Definition

Bits set by the VBOX source

VBOX_FLG_VALID_DATE

0x0001

Date is valid but could have UTC/GPS offset

VBOX_FLG_VALID_TIME

0x0002

Time is valid but could have UTC/GPS offset

VBOX_FLG_VALID_TIME_FULL

0x0004

GPS to UTC offset is known

VBOX_FLG_VALID_FIX

0x0010

Fix is valid

VBOX_FLG_VALID_DIFF

0x0020

Fix has differential corrections

VBOX_FLG_VALID_HEADING

0x0100

Heading is valid

Bits set by the VBOX task

VBOX_FLG_STATIONARY

0x00010000

Below minimum speed setting

VBOX_FLG_LAP_VALID

0x00020000

A lap is in progress i.e. sample’s lap timing data is valid

VBOX_FLG_PLT_VALID

0x00040000

Prediction has started i.e. sample’s PLT data is valid

VBOX_FLG_PLT_RECORDING

0x00080000

A reference lap is being saved

VBOX_FLG_TRG0_PRESS

0x01000000

DIGIO0 pressed since last sample

VBOX_FLG_TRG0_STATE

0x02000000

DIGIO0 state during current sample processing

VBOX_FLG_TRG1_PRESS

0x04000000

DIGIO1 pressed since last sample

VBOX_FLG_TRG1_STATE

0x08000000

DIGIO1 state during current sample processing

VBOX_FLG_SYSTS_VALID

0x10000000

Set if the systs field is valid.

Bits set by the Micropython task

VBOX_FLG_UPY_READ

0x20000000

Set if the sample has been read by uPy.

Bit combinations

VBOX_FLG_VALID_DATE_TIME

(VBOX_FLG_VALID_DATE | VBOX_FLG_VALID_TIME)

Date/time status mask

VBOX_FLG_SOURCE_MASK

0x0000FFFF

VBOX_FLG_TRG0_MASK

(VBOX_FLG_VALID_DATE | VBOX_FLG_VALID_TIME)

DIGIO0 event & state mask

VBOX_FLG_TRG1_MASK

(VBOX_FLG_TRG1_PRESS | VBOX_FLG_TRG1_STATE)

DIGIO1 event & state mask

Further Examples

  • The Dashboard example - shows the use of the VBOX sample to populate a speedometer.

  • The G meter example - shows the use of the VBOX Sample to calculate g-force and display it on a g-meter

  • The Graphics example - shows the use of the VBOX Sample to print out various GNSS data to the screen

  • Event Marker App – receives data and then logs it to a .vbo file that it creates.