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.