first commit
This commit is contained in:
commit
e6a42e28e9
4355 changed files with 4626605 additions and 0 deletions
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Monitor AssistNow Autonomous data collection
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 29th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to enable and monitor AssistNow Autonomous data collection by the module.
|
||||
A callback is used to monitor AssistNow Autonomous data availability for each satellite.
|
||||
A second callback is used to print the AOPSTATUS status.
|
||||
|
||||
If your GNSS board has battery-backup for the RAM - and all SparkFun boards do! - then you can:
|
||||
wait until the module has AssistNow Autonomous data for a few satellites;
|
||||
power-cycle the board;
|
||||
watch how fast it gets its first fix!
|
||||
|
||||
Note: this example will only work on boards which have plenty of RAM available.
|
||||
The UBX-NAV-SAT information occupies several kBytes.
|
||||
|
||||
Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only."
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printSATdata will be called when new NAV SAT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback
|
||||
// / _____ This _must_ be UBX_NAV_SAT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printSATdata(UBX_NAV_SAT_data_t *ubxDataStruct)
|
||||
{
|
||||
//Serial.println();
|
||||
|
||||
Serial.print(F("UBX-NAV-SAT contains data for "));
|
||||
Serial.print(ubxDataStruct->header.numSvs);
|
||||
if (ubxDataStruct->header.numSvs == 1)
|
||||
Serial.println(F(" SV"));
|
||||
else
|
||||
Serial.println(F(" SVs"));
|
||||
|
||||
uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available
|
||||
|
||||
for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV
|
||||
{
|
||||
if (ubxDataStruct->blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set
|
||||
numAopAvail++; // Increment the number of SVs
|
||||
}
|
||||
|
||||
Serial.print(F("AssistNow Autonomous data is available for "));
|
||||
Serial.print(numAopAvail);
|
||||
if (numAopAvail == 1)
|
||||
Serial.println(F(" SV"));
|
||||
else
|
||||
Serial.println(F(" SVs"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printAOPstatus will be called when new NAV AOPSTATUS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_AOPSTATUS_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVAOPSTATUScallback
|
||||
// / _____ This _must_ be UBX_NAV_AOPSTATUS_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printAOPstatus(UBX_NAV_AOPSTATUS_data_t *ubxDataStruct)
|
||||
{
|
||||
//Serial.println();
|
||||
|
||||
Serial.print(F("AOPSTATUS status is "));
|
||||
Serial.println(ubxDataStruct->status);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printPVTdata will be called when new NAV PVT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback
|
||||
// / _____ This _must_ be UBX_NAV_PVT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct)
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
Serial.println();
|
||||
|
||||
long latitude = ubxDataStruct->lat; // Print the latitude
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = ubxDataStruct->lon; // Print the longitude
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte fixType = ubxDataStruct->fixType; // Print the fix type
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
//myGNSS.enableDebugging(Serial, true); // Uncomment this line to see the 'major' debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Enable AssistNow Autonomous data collection.
|
||||
|
||||
if (myGNSS.setAopCfg(1) == true)
|
||||
{
|
||||
Serial.println(F("aopCfg enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Could not enable aopCfg. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Enable automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages and set up the callbacks
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
|
||||
myGNSS.setAutoNAVSATcallbackPtr(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata
|
||||
myGNSS.setAutoAOPSTATUScallbackPtr(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus
|
||||
myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
Read the AssistNow Autonomous database from the module
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 29th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to enable, check the status of, and read the AssistNow Autonomous data from the module.
|
||||
|
||||
Note: this example will only work on boards which have plenty of RAM available.
|
||||
The database can be several kBytes in length.
|
||||
|
||||
Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only."
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printSATdata will be called when new NAV SAT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback
|
||||
// / _____ This _must_ be UBX_NAV_SAT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printSATdata(UBX_NAV_SAT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("UBX-NAV-SAT contains data for "));
|
||||
Serial.print(ubxDataStruct->header.numSvs);
|
||||
if (ubxDataStruct->header.numSvs == 1)
|
||||
Serial.println(F(" SV"));
|
||||
else
|
||||
Serial.println(F(" SVs"));
|
||||
|
||||
uint16_t numAopAvail = 0; // Count how many SVs have AssistNow Autonomous data available
|
||||
|
||||
for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV
|
||||
{
|
||||
if (ubxDataStruct->blocks[block].flags.bits.aopAvail == 1) // If the aopAvail bit is set
|
||||
numAopAvail++; // Increment the number of SVs
|
||||
}
|
||||
|
||||
Serial.print(F("AssistNow Autonomous data is available for "));
|
||||
Serial.print(numAopAvail);
|
||||
if (numAopAvail == 1)
|
||||
Serial.println(F(" SV"));
|
||||
else
|
||||
Serial.println(F(" SVs"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printAOPstatus will be called when new NAV AOPSTATUS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_AOPSTATUS_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVAOPSTATUScallback
|
||||
// / _____ This _must_ be UBX_NAV_AOPSTATUS_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printAOPstatus(UBX_NAV_AOPSTATUS_data_t *ubxDataStruct)
|
||||
{
|
||||
//Serial.println();
|
||||
|
||||
Serial.print(F("AOPSTATUS status is "));
|
||||
Serial.println(ubxDataStruct->status);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//myGNSS.enableDebugging(Serial, true); // Uncomment this line to see helpful debug messages on Serial
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Enable AssistNow Autonomous data collection.
|
||||
|
||||
if (myGNSS.setAopCfg(1) == true)
|
||||
{
|
||||
Serial.println(F("aopCfg enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Could not enable aopCfg. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Enable automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages and set up the callbacks
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
|
||||
myGNSS.setAutoNAVSATcallbackPtr(&printSATdata); // Enable automatic NAV SAT messages with callback to printSATdata
|
||||
myGNSS.setAutoAOPSTATUScallbackPtr(&printAOPstatus); // Enable automatic NAV AOPSTATUS messages with callback to printAOPstatus
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Keep displaying NAV SAT and AOPSTATUS until the user presses a key
|
||||
|
||||
Serial.println(F("AssistNow Autonomous data collection is in progress. Press any key to quit and read the database."));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
|
||||
while (!Serial.available()) // Wait for the arrival of a keypress
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Disable the automatic UBX-NAV-SAT and UBX-NAV-AOPSTATUS messages
|
||||
|
||||
myGNSS.setAutoNAVSAT(false);
|
||||
myGNSS.setAutoAOPSTATUS(false);
|
||||
delay(1100);
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Read the AssistNow Autonomous database from the module and pretty-print it (so it can be copied and pasted into the next example)
|
||||
|
||||
#define MAX_DATABASE_LENGTH 32768 // Allocate 32kBytes to store the navigation database
|
||||
size_t maxDatabaseLen = MAX_DATABASE_LENGTH;
|
||||
uint8_t *database = new uint8_t[MAX_DATABASE_LENGTH]; // The database will be stored here
|
||||
|
||||
Serial.println(F("Storage has been allocated for the database.")); Serial.flush();
|
||||
|
||||
size_t actualDatabaseLen = myGNSS.readNavigationDatabase(database, maxDatabaseLen); // Read the database
|
||||
|
||||
Serial.print(F("The Navigation Database length was "));
|
||||
Serial.println(actualDatabaseLen);
|
||||
|
||||
if (actualDatabaseLen == maxDatabaseLen)
|
||||
Serial.println(F("There was not enough memory to store the entire database. Some data will have been lost!"));
|
||||
|
||||
// Pretty-print the database so it can be copied into the next example
|
||||
Serial.println(F("Copy and paste the following into the next example, so you can write it back to the module:"));
|
||||
Serial.println();
|
||||
Serial.print(F("size_t databaseLen = "));
|
||||
Serial.print(actualDatabaseLen);
|
||||
Serial.println(F(";"));
|
||||
Serial.print(F("const uint8_t database["));
|
||||
Serial.print(actualDatabaseLen);
|
||||
Serial.println(F("] = {"));
|
||||
size_t i;
|
||||
for(i = 0; i < actualDatabaseLen; i++)
|
||||
{
|
||||
if ((i % 32) == 0)
|
||||
Serial.print(F(" 0x"));
|
||||
if (*(database + i) < 0x10) // Print leading zero
|
||||
Serial.print(F("0"));
|
||||
Serial.print(*(database + i), HEX);
|
||||
if (i == (actualDatabaseLen - 1))
|
||||
Serial.println();
|
||||
else if ((i % 32) == 31)
|
||||
Serial.println(F(","));
|
||||
else
|
||||
Serial.print(F(", 0x"));
|
||||
}
|
||||
Serial.println(F("};"));
|
||||
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Write the AssistNow Autonomous database data to the module
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: December 1st, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to write the AssistNow Autonomous database date back to the module.
|
||||
|
||||
This example is written for the ESP32. A WiFi connection is used to get network time to pass to the module.
|
||||
(You could use an RTC instead.)
|
||||
|
||||
Copy and paste the database data from the previous example into database.h.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
|
||||
Note: this example will not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only."
|
||||
|
||||
Note: this example works best if you have the GNSS RAM battery-backup disabled.
|
||||
All SparkFun boards have battery-backup for the RAM which will means the database is retained if you disconnect the power.
|
||||
The module will use the database data from the battery-backed RAM when you turn the power back on.
|
||||
You will only see the improvement in the time-to-first-fix if you disable the battery first - or you are using a non-SparkFun
|
||||
board that does not have the backup battery.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include "database.h" // <- Copy and paste the database data from the previous example into database.h
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include "time.h"
|
||||
|
||||
const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//myGNSS.enableDebugging(Serial, true); // Uncomment this line to see helpful debug messages on Serial
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Set the RTC using network time. (Code taken from the SimpleTime example.)
|
||||
|
||||
// Request the time from the NTP server and use it to set the ESP32's RTC.
|
||||
configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time.
|
||||
|
||||
struct tm timeinfo;
|
||||
if(!getLocalTime(&timeinfo))
|
||||
{
|
||||
Serial.println("Failed to obtain time");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the RTC time to the module
|
||||
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
// setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here.
|
||||
// Have a look at the library source code for more details.
|
||||
myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
|
||||
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly.");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow Autonomous data to the module
|
||||
|
||||
size_t bytesPushed = myGNSS.pushAssistNowData(database, databaseLen);
|
||||
|
||||
Serial.print(F("Pushed "));
|
||||
Serial.print(bytesPushed);
|
||||
Serial.println(F(" bytes of AssistNow Autonomous data to the module"));
|
||||
|
||||
if (bytesPushed != databaseLen)
|
||||
Serial.println(F("Warning: bytesPushed does not match databaseLen! Maybe the database contains bad data? Or there was a communication error?"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Disconnect the WiFi as it's no longer needed
|
||||
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
Serial.println(F("WiFi disconnected"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
// Paste the AssistNow Autonomous database data from the previous example here:
|
||||
|
||||
size_t databaseLen = 5480;
|
||||
const uint8_t database[5480] = {
|
||||
0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x02, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x08, 0xC4, 0x04, 0x26, 0xFE, 0x02, 0x54, 0xBA, 0xA9,
|
||||
0xFF, 0xDA, 0x8C, 0x05, 0xA3, 0xC1, 0xCD, 0x85, 0x86, 0x0A, 0x14, 0x20, 0xAA, 0xE6, 0xB4, 0xD3, 0x4F, 0x27, 0x12, 0xE0, 0xE6, 0xC3, 0xE4, 0x79, 0x0E, 0xA1, 0xD3, 0x49, 0xF4, 0xFF, 0xAF, 0xF7,
|
||||
0x67, 0x2E, 0x93, 0xF9, 0x6A, 0x1B, 0x2D, 0x10, 0xD3, 0x49, 0xBD, 0xFF, 0x26, 0x01, 0x00, 0x1E, 0x81, 0x22, 0xA1, 0xE4, 0x2A, 0x00, 0x10, 0x50, 0x04, 0x00, 0xB7, 0xBF, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x54, 0x00, 0x01, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x1E, 0xC4, 0x44, 0x72, 0x2F, 0x02, 0x71, 0xAD, 0xA4, 0xFF, 0xE8, 0xAE, 0xFA,
|
||||
0x42, 0x25, 0xD1, 0x0F, 0x0D, 0x03, 0xCB, 0x71, 0xCF, 0x12, 0x6F, 0x89, 0x0F, 0x27, 0xF3, 0x49, 0x7B, 0x29, 0x4B, 0xF1, 0x0C, 0xA1, 0xD4, 0x49, 0xF5, 0xFF, 0xB6, 0x03, 0x98, 0x36, 0xA0, 0x03,
|
||||
0xBB, 0x0F, 0x72, 0x1D, 0xD4, 0x49, 0xEE, 0xFF, 0x17, 0x00, 0x00, 0xC0, 0x85, 0x22, 0x2F, 0xF0, 0x3D, 0x00, 0x3C, 0x50, 0x04, 0x00, 0x1A, 0x35, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00,
|
||||
0x00, 0x07, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x5B, 0xC4, 0x44, 0xD8, 0xEC, 0x02, 0x4E, 0x79, 0xAC, 0xFF, 0xE8, 0x8A, 0x1D, 0xBC, 0x9F, 0xE8, 0x86,
|
||||
0xD9, 0x07, 0x45, 0xD0, 0x05, 0x6A, 0x05, 0x06, 0xC3, 0x26, 0xB5, 0x7D, 0x4A, 0xA2, 0x86, 0xCA, 0x0D, 0xA1, 0xD4, 0x49, 0x2B, 0x00, 0x62, 0x07, 0x63, 0x2F, 0xF5, 0x05, 0x1E, 0x1A, 0x98, 0x10,
|
||||
0xD4, 0x49, 0x38, 0x00, 0xBA, 0xFF, 0x00, 0xCB, 0xBE, 0x22, 0xF4, 0x59, 0x09, 0x00, 0xB6, 0x50, 0x04, 0x00, 0x2E, 0x9B, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x09, 0x15, 0x0C,
|
||||
0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x5E, 0xC4, 0x44, 0xFA, 0x7B, 0x02, 0x4E, 0x1B, 0xA5, 0xFF, 0x03, 0x6E, 0x07, 0xF5, 0x25, 0xF3, 0xB8, 0x36, 0x01, 0xDB, 0x4F,
|
||||
0x56, 0x3E, 0x8D, 0xA6, 0xD7, 0x26, 0x82, 0xFE, 0xA8, 0x4A, 0x7A, 0x44, 0x0D, 0xA1, 0xD4, 0x49, 0x05, 0x00, 0x7A, 0xFA, 0x1C, 0x37, 0xDC, 0xFA, 0x33, 0x0E, 0x7E, 0x1E, 0xD4, 0x49, 0xE5, 0xFF,
|
||||
0xFC, 0xFF, 0x00, 0xB7, 0xBA, 0x22, 0x87, 0x2A, 0x34, 0x00, 0xBC, 0x50, 0x04, 0x00, 0xDF, 0x11, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x0B, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00,
|
||||
0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0A, 0x2F, 0xC4, 0x44, 0xC7, 0x68, 0x00, 0xF6, 0x09, 0xAA, 0xFF, 0xED, 0xB8, 0x38, 0x24, 0x1C, 0xE8, 0xC5, 0x30, 0x00, 0xD0, 0x23, 0x17, 0xEC, 0xF7, 0x92,
|
||||
0x2D, 0x27, 0x7C, 0x39, 0x2C, 0x6B, 0x66, 0xF5, 0x0D, 0xA1, 0xD4, 0x49, 0xEA, 0xFF, 0x27, 0xF9, 0x09, 0x2F, 0x2B, 0xFA, 0x6A, 0x1B, 0xFB, 0x0F, 0xD4, 0x49, 0x01, 0x00, 0x0F, 0x00, 0x00, 0xC1,
|
||||
0x82, 0x22, 0x2A, 0x8A, 0x80, 0xFF, 0x5E, 0x50, 0x04, 0x00, 0x52, 0xBB, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0x0C, 0x96, 0xC4, 0x44, 0x8E, 0xBD, 0x02, 0xE4, 0x39, 0xA6, 0xFF, 0xE8, 0x7E, 0xBE, 0x5F, 0xFE, 0xF3, 0xCA, 0xF0, 0x02, 0x5D, 0x9F, 0x84, 0x44, 0x3A, 0xC9, 0x6F, 0x27, 0xFD, 0x1B,
|
||||
0xDB, 0x27, 0x60, 0x63, 0x0D, 0xA1, 0xD4, 0x49, 0x32, 0x00, 0x4B, 0xFA, 0xA6, 0x33, 0x2C, 0xFB, 0x5C, 0x10, 0xB8, 0x1C, 0xD4, 0x49, 0x0E, 0x00, 0x1E, 0x00, 0x00, 0x0D, 0xB9, 0x22, 0x3A, 0x4D,
|
||||
0x07, 0x00, 0x2C, 0x51, 0x04, 0x00, 0x76, 0x2E, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x22,
|
||||
0xC4, 0x44, 0x47, 0xD2, 0x02, 0x47, 0xEA, 0xA3, 0xFF, 0xEA, 0x53, 0xBB, 0xBD, 0x37, 0xBE, 0x0A, 0x5B, 0x06, 0x85, 0x4F, 0x13, 0x98, 0x48, 0x33, 0x95, 0x27, 0xC8, 0x3B, 0xE7, 0x1B, 0x37, 0x8F,
|
||||
0x0C, 0xA1, 0xD4, 0x49, 0xC9, 0xFF, 0x09, 0x0C, 0x98, 0x30, 0xB3, 0x0A, 0x16, 0x09, 0x14, 0x26, 0xD4, 0x49, 0xB3, 0xFF, 0x4E, 0x00, 0x00, 0xE0, 0x81, 0x22, 0x2D, 0xCD, 0x31, 0x00, 0x44, 0x50,
|
||||
0x04, 0x00, 0x39, 0x9B, 0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x13, 0x1B, 0xC4, 0x44, 0x6A, 0xD2,
|
||||
0x02, 0xE9, 0x7C, 0xA3, 0xFF, 0xEE, 0xD1, 0x59, 0xEE, 0xE7, 0x56, 0x56, 0xCC, 0x02, 0xE4, 0x2C, 0x39, 0x0E, 0xB6, 0x13, 0x56, 0x26, 0xDF, 0xE5, 0x41, 0x7C, 0xDA, 0x86, 0x0D, 0xA1, 0xD4, 0x49,
|
||||
0xFE, 0xFF, 0x81, 0x04, 0x73, 0x3A, 0x0F, 0x04, 0x54, 0x10, 0x59, 0x1B, 0xD4, 0x49, 0x37, 0x00, 0xDF, 0xFF, 0x00, 0x21, 0x87, 0x22, 0x0B, 0xF8, 0x10, 0x00, 0x36, 0x50, 0x04, 0x00, 0x75, 0x76,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x54, 0x00, 0x01, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1C, 0x31, 0xC4, 0xC4, 0x58, 0xF9, 0x02, 0xFC, 0xD0, 0xA5,
|
||||
0xFF, 0xEA, 0x04, 0x79, 0x3B, 0x17, 0xD6, 0x48, 0xEF, 0x00, 0xB9, 0x34, 0x1C, 0xC2, 0x1E, 0x93, 0x05, 0x28, 0xA0, 0x7E, 0x9D, 0x60, 0x7C, 0x63, 0x0C, 0xA1, 0xD4, 0x49, 0xD2, 0xFF, 0x51, 0xF4,
|
||||
0xD6, 0x2D, 0xD9, 0xF5, 0x45, 0x08, 0x41, 0x27, 0xD4, 0x49, 0x23, 0x00, 0xFE, 0xFF, 0x00, 0x7C, 0xBC, 0x22, 0x15, 0x51, 0x31, 0x00, 0x62, 0x50, 0x04, 0x00, 0xEC, 0xE1, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x54, 0x00, 0x01, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x01, 0x0D, 0x3B, 0x00, 0x04, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x22, 0xC4, 0x04, 0x53, 0x24, 0x02, 0xF4, 0x99, 0xA8, 0xFF, 0x08, 0x62, 0xE5,
|
||||
0x6F, 0x9E, 0x9C, 0x48, 0xBC, 0x02, 0xB4, 0x07, 0x9B, 0x6A, 0x21, 0x82, 0x28, 0x26, 0x78, 0x77, 0x0C, 0x90, 0x2F, 0xF9, 0x0C, 0xA1, 0xD4, 0x49, 0xE5, 0xFF, 0x34, 0x08, 0x30, 0x33, 0xC0, 0x06,
|
||||
0x34, 0x1B, 0x7C, 0x0E, 0xD4, 0x49, 0xF7, 0xFF, 0xEE, 0xFF, 0x00, 0x19, 0xBE, 0x22, 0x6F, 0xC0, 0x2F, 0x00, 0x44, 0x50, 0x04, 0x00, 0x93, 0x6D, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00,
|
||||
0x06, 0x07, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xA5, 0xB9, 0xC6, 0x04, 0x16, 0x44, 0x02, 0xC6, 0xE0, 0xD9, 0x21, 0x1C, 0xC0, 0xE0, 0xF8, 0xD5, 0x3D, 0x6E,
|
||||
0x01, 0x56, 0x21, 0xC1, 0x0F, 0x39, 0xF8, 0x70, 0x2D, 0x10, 0x7F, 0xFF, 0x10, 0x38, 0xEE, 0xA5, 0x80, 0x00, 0x00, 0xE8, 0x55, 0x0C, 0x1C, 0xEB, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00,
|
||||
0x06, 0x0F, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xAD, 0xB9, 0xC6, 0x04, 0x6F, 0x28, 0x02, 0x17, 0x5C, 0xB7, 0xE5, 0xF7, 0x80, 0x1F, 0x46, 0x2A, 0xDE, 0xBE,
|
||||
0xF0, 0x59, 0x45, 0x5C, 0xCE, 0x39, 0x75, 0x99, 0xF7, 0x10, 0x1B, 0x7B, 0xFF, 0x78, 0x18, 0x5D, 0xFE, 0x00, 0x00, 0xE8, 0x55, 0x07, 0xC8, 0x8F, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00,
|
||||
0x06, 0x10, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xAE, 0xB9, 0xC6, 0x84, 0x26, 0x63, 0x02, 0x0C, 0x60, 0x9D, 0xDA, 0x44, 0x5E, 0xE2, 0x3C, 0x27, 0xDD, 0xED,
|
||||
0xF5, 0x3B, 0xDE, 0xC1, 0xDE, 0x39, 0xA7, 0xDD, 0xF9, 0x20, 0x11, 0x54, 0x2A, 0x80, 0xFB, 0x6C, 0x80, 0x00, 0xFF, 0xEF, 0x55, 0x06, 0x17, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00,
|
||||
0x06, 0x15, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xB3, 0xB9, 0xC6, 0x04, 0x6F, 0xC3, 0x02, 0xF0, 0xC6, 0x33, 0xC1, 0x45, 0x3F, 0x28, 0xC9, 0xBB, 0xBF, 0x1B,
|
||||
0x1B, 0xEC, 0x14, 0xF1, 0xF5, 0x39, 0x55, 0x25, 0x06, 0x30, 0x84, 0xAE, 0xC7, 0xA8, 0x89, 0x3D, 0x44, 0x00, 0xFD, 0xEF, 0x55, 0x0B, 0x89, 0xE0, 0xB5, 0x62, 0x13, 0x80, 0x38, 0x00, 0x01, 0x00,
|
||||
0x06, 0x17, 0x15, 0x0C, 0x01, 0x0C, 0x21, 0x00, 0x02, 0x24, 0xE0, 0x4A, 0x01, 0x03, 0xB5, 0xB9, 0xC6, 0x04, 0x34, 0xBC, 0x02, 0xF5, 0xBE, 0x0D, 0x15, 0xEA, 0x21, 0xA3, 0xC8, 0xDB, 0x1E, 0x3A,
|
||||
0x31, 0x5A, 0x38, 0xB6, 0x20, 0x39, 0x8B, 0x4A, 0xD9, 0x30, 0xDF, 0x66, 0xF8, 0xB8, 0x9D, 0x5B, 0x00, 0x02, 0xFF, 0xEF, 0x55, 0x0A, 0x20, 0x5A, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00,
|
||||
0x00, 0x01, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x00, 0x7B, 0xB0, 0x04, 0xC5, 0xE4, 0x01, 0x73, 0x47, 0x5B, 0xAE, 0x1C, 0x18, 0x0D, 0xA1, 0x00, 0x65, 0xFD,
|
||||
0x00, 0x7B, 0x41, 0x2C, 0xEA, 0x00, 0x14, 0x16, 0x24, 0x00, 0xF1, 0x02, 0x67, 0x00, 0x06, 0xEA, 0x3F, 0x8A, 0xA4, 0x7B, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x02, 0x15, 0x0C,
|
||||
0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x7B, 0xB0, 0x44, 0x66, 0x1F, 0x03, 0xC2, 0x82, 0xA8, 0x90, 0x0E, 0x1C, 0x0E, 0xA1, 0x00, 0x4E, 0xFD, 0x00, 0x7B, 0x4F, 0x99,
|
||||
0xE6, 0x00, 0xF3, 0xEB, 0xC3, 0x00, 0xE8, 0x8A, 0x6E, 0x00, 0x5C, 0x05, 0x00, 0x8A, 0xDF, 0xF9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x03, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x02, 0x7B, 0xB0, 0x04, 0x96, 0x8D, 0x01, 0xEB, 0x94, 0x1F, 0x20, 0x13, 0x6B, 0x0D, 0xA1, 0x00, 0x69, 0xFD, 0x00, 0x7B, 0xC1, 0x59, 0x14, 0x00, 0x8A, 0xAC,
|
||||
0x28, 0x00, 0xDD, 0x24, 0x37, 0x00, 0xE0, 0xEF, 0x3F, 0x8A, 0x0F, 0xED, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x04, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0x03, 0x7B, 0xB0, 0x44, 0x8F, 0x51, 0x01, 0xFF, 0xCA, 0x0C, 0xA8, 0x0B, 0xD6, 0x0C, 0xA1, 0x00, 0x44, 0xFD, 0x00, 0x7B, 0x3F, 0x67, 0x40, 0x00, 0x77, 0x26, 0x80, 0x00, 0x3A, 0x7C,
|
||||
0xB2, 0x00, 0x2E, 0x07, 0x00, 0x8A, 0xD8, 0xB6, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x00,
|
||||
0xB0, 0x14, 0xB8, 0x76, 0x03, 0xEA, 0xD0, 0x30, 0x92, 0x0A, 0xF1, 0x0C, 0xA1, 0x00, 0x25, 0xFD, 0xD4, 0x49, 0x71, 0xCF, 0x12, 0x00, 0x49, 0x7B, 0x29, 0x00, 0xFA, 0x42, 0x25, 0x00, 0xBE, 0xFF,
|
||||
0x3F, 0x8A, 0xD6, 0xA9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x06, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x05, 0x7B, 0xB0, 0x44, 0xBB, 0x76,
|
||||
0x01, 0x15, 0x1F, 0x14, 0x47, 0x1C, 0xB5, 0x0C, 0xA1, 0x00, 0x63, 0xFD, 0x00, 0x7B, 0x16, 0xD6, 0xE9, 0x00, 0xEC, 0xC2, 0xD5, 0x00, 0xAB, 0x35, 0x77, 0x00, 0x8C, 0x18, 0x80, 0x8A, 0x81, 0xB1,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x07, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x00, 0xB0, 0x14, 0x33, 0xF6, 0x03, 0x49, 0x98, 0x7D,
|
||||
0xC9, 0x05, 0xCA, 0x0D, 0xA1, 0x00, 0x63, 0xFD, 0xD4, 0x49, 0xD0, 0x05, 0x6A, 0x00, 0x7D, 0x4A, 0xA2, 0x00, 0x1D, 0xBC, 0x9F, 0x00, 0x2B, 0x09, 0x00, 0x8A, 0x4B, 0xEC, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x34, 0x00, 0x02, 0x00, 0x00, 0x08, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x07, 0x7B, 0xB0, 0x04, 0x04, 0xE8, 0x01, 0xB3, 0x40, 0x38, 0xDD, 0x0E, 0x13, 0x0D,
|
||||
0xA1, 0x00, 0x22, 0xFD, 0x00, 0x7B, 0x33, 0x39, 0xBE, 0x00, 0x60, 0x6D, 0x02, 0x00, 0xAF, 0xE0, 0xC5, 0x00, 0xCF, 0x07, 0x80, 0x8A, 0x59, 0x50, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00,
|
||||
0x00, 0x09, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x00, 0xB0, 0x14, 0x50, 0xB2, 0x03, 0x0A, 0x6B, 0x13, 0x14, 0x07, 0x44, 0x0D, 0xA1, 0x00, 0x28, 0xFD,
|
||||
0xD4, 0x49, 0x4F, 0x56, 0x3E, 0x00, 0xFE, 0xA8, 0x4A, 0x00, 0x07, 0xF5, 0x25, 0x00, 0x85, 0x06, 0x00, 0x8A, 0x09, 0xB0, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0A, 0x15, 0x0C,
|
||||
0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x09, 0x7B, 0xB0, 0x44, 0x94, 0x64, 0x01, 0x0C, 0xB3, 0x3B, 0x06, 0x13, 0x0D, 0x0D, 0xA1, 0x00, 0x6E, 0xFD, 0x00, 0x7B, 0x68, 0x3C,
|
||||
0x14, 0x00, 0x15, 0x6E, 0x97, 0x00, 0x53, 0x99, 0x16, 0x00, 0xEF, 0xF6, 0xBF, 0x8A, 0xC1, 0xA9, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0B, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0A, 0x7B, 0xB0, 0x04, 0xF5, 0x0B, 0x01, 0xDE, 0x10, 0x03, 0x70, 0x0C, 0x97, 0x0D, 0xA1, 0xFF, 0x52, 0xFD, 0x00, 0x7B, 0x7A, 0x06, 0xEC, 0x00, 0xA3, 0x44,
|
||||
0x6B, 0x00, 0xA1, 0xEB, 0xC8, 0x00, 0x11, 0xF8, 0xBF, 0x8A, 0xB4, 0x35, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0C, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0x0B, 0x7B, 0xB0, 0x04, 0xFD, 0x31, 0x01, 0x09, 0xE0, 0x44, 0xFA, 0x12, 0xD4, 0x0C, 0xA1, 0x00, 0x54, 0xFD, 0x00, 0x7B, 0xBC, 0x3F, 0x97, 0x00, 0x0C, 0x17, 0x32, 0x00, 0x5D, 0xE0,
|
||||
0x30, 0x00, 0x72, 0xF7, 0xBF, 0x8A, 0x91, 0x2E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0C, 0x00,
|
||||
0xB0, 0x14, 0x82, 0xD3, 0x03, 0x6F, 0x0C, 0x2F, 0x96, 0x10, 0x63, 0x0D, 0xA1, 0x00, 0x31, 0xFD, 0xD4, 0x49, 0x9F, 0x84, 0x44, 0x00, 0x1B, 0xDB, 0x27, 0x00, 0xBE, 0x5F, 0xFE, 0x00, 0xE9, 0x08,
|
||||
0x00, 0x8A, 0x4A, 0x74, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0E, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0D, 0x7B, 0xB0, 0x44, 0x3E, 0xB1,
|
||||
0x01, 0x66, 0xD7, 0x09, 0x30, 0x08, 0xCD, 0x0C, 0xA1, 0x00, 0x4A, 0xFD, 0x00, 0x7B, 0x72, 0x05, 0x96, 0x00, 0x85, 0x34, 0x7E, 0x00, 0xFE, 0xFB, 0x2F, 0x00, 0xCC, 0xF7, 0xBF, 0x8A, 0x3C, 0x14,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x0F, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0E, 0x7B, 0xB0, 0x44, 0x92, 0xB0, 0x01, 0xBF, 0xF2, 0x71,
|
||||
0x4F, 0xF7, 0x0E, 0x0D, 0xA1, 0x00, 0x26, 0xFD, 0x00, 0x7B, 0x66, 0x06, 0x3A, 0x00, 0xAE, 0x39, 0x2B, 0x00, 0xEF, 0x2D, 0x9C, 0x00, 0x95, 0x0F, 0x80, 0x8A, 0x3F, 0x35, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x34, 0x00, 0x02, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x00, 0xB0, 0x14, 0x96, 0x34, 0x03, 0x8E, 0xB0, 0x65, 0xEC, 0x12, 0x8F, 0x0C,
|
||||
0xA1, 0x00, 0x1F, 0xFD, 0xD4, 0x49, 0x4F, 0x13, 0x98, 0x00, 0x3B, 0xE7, 0x1B, 0x00, 0xBB, 0xBD, 0x37, 0x00, 0x39, 0xF6, 0x3F, 0x8A, 0xF3, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00,
|
||||
0x00, 0x11, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x10, 0x7B, 0xB0, 0x04, 0x5E, 0xE6, 0x01, 0xF3, 0xDF, 0x70, 0xA4, 0x18, 0x50, 0x0D, 0xA1, 0x00, 0x34, 0xFD,
|
||||
0x00, 0x7B, 0x86, 0x84, 0xC1, 0x00, 0x0F, 0xBA, 0xC1, 0x00, 0xF9, 0x59, 0xC2, 0x00, 0x39, 0x0A, 0x80, 0x8A, 0x83, 0x21, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x12, 0x15, 0x0C,
|
||||
0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x11, 0x7B, 0xB0, 0x04, 0x92, 0xB3, 0x01, 0xCD, 0x23, 0x11, 0x1A, 0x12, 0xC7, 0x0C, 0xA1, 0x00, 0x57, 0xFD, 0x00, 0x7B, 0x1B, 0x89,
|
||||
0xEA, 0x00, 0x3E, 0x35, 0x7D, 0x00, 0x7D, 0xB8, 0x6F, 0x00, 0x2B, 0xF1, 0xBF, 0x8A, 0x1F, 0x89, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x13, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x12, 0x7B, 0xB0, 0x44, 0xDE, 0x29, 0x01, 0x15, 0x35, 0x49, 0xCA, 0x17, 0xF3, 0x0C, 0xA1, 0x00, 0x30, 0xFD, 0x00, 0x7B, 0xBE, 0x59, 0xC3, 0x00, 0xEA, 0xA7,
|
||||
0x50, 0x00, 0xBF, 0x3E, 0x23, 0x00, 0x5C, 0x08, 0x80, 0x8A, 0x31, 0x50, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0x13, 0x00, 0xB0, 0x14, 0x3E, 0x72, 0x03, 0xA1, 0xC5, 0x2C, 0xFA, 0xFE, 0x86, 0x0D, 0xA1, 0x00, 0x1B, 0xFD, 0xD4, 0x49, 0x2C, 0x39, 0x0E, 0x00, 0xE5, 0x41, 0x7C, 0x00, 0x59, 0xEE,
|
||||
0xE7, 0x00, 0x1F, 0xFA, 0x3F, 0x8A, 0x05, 0x19, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x15, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x14, 0x7B,
|
||||
0xB0, 0x44, 0x9E, 0xFA, 0x01, 0xD6, 0x02, 0xC7, 0xCD, 0x0A, 0x8B, 0x0C, 0xA1, 0x00, 0x4C, 0xFD, 0x00, 0x7B, 0x38, 0x8D, 0xE6, 0x00, 0x0D, 0x36, 0xD5, 0x00, 0xBA, 0x5E, 0xC7, 0x00, 0xA0, 0x00,
|
||||
0x80, 0x8A, 0x7F, 0x6E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x16, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x15, 0x7B, 0xB0, 0x44, 0x9E, 0x17,
|
||||
0x01, 0x24, 0x81, 0x37, 0xE8, 0xFC, 0xEA, 0x0C, 0xA1, 0x00, 0x4C, 0xFD, 0x00, 0x7B, 0xDE, 0x06, 0x10, 0x00, 0xD1, 0x69, 0xDC, 0x00, 0xC5, 0x18, 0x94, 0x00, 0x28, 0x16, 0x80, 0x8A, 0xBE, 0x20,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x17, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x16, 0x7B, 0xB0, 0x44, 0x2E, 0xDB, 0x01, 0x43, 0xB7, 0x0F,
|
||||
0xCC, 0x0F, 0x25, 0x0D, 0xA1, 0x00, 0x68, 0xFD, 0x00, 0x7B, 0x32, 0x3D, 0x13, 0x00, 0x85, 0x6C, 0x73, 0x00, 0xE0, 0xD5, 0x4F, 0x00, 0x1B, 0xF8, 0xBF, 0x8A, 0x13, 0xA5, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x34, 0x00, 0x02, 0x00, 0x00, 0x18, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x17, 0x7B, 0xB0, 0x04, 0xAC, 0x23, 0x01, 0x3F, 0x2F, 0x63, 0xE2, 0xFA, 0x29, 0x0D,
|
||||
0xA1, 0x00, 0x4A, 0xFD, 0x00, 0x7B, 0x90, 0xA3, 0x66, 0x00, 0x3C, 0x04, 0x20, 0x00, 0x7B, 0x4A, 0x74, 0x00, 0x1E, 0x09, 0x80, 0x8A, 0x67, 0xDD, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00,
|
||||
0x00, 0x19, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x18, 0x7B, 0xB0, 0x04, 0xF3, 0x84, 0x01, 0x2A, 0xEE, 0x52, 0xCB, 0x0A, 0x9F, 0x0D, 0xA1, 0x00, 0x4E, 0xFD,
|
||||
0x00, 0x7B, 0xFC, 0x28, 0x94, 0x00, 0x03, 0x3B, 0x27, 0x00, 0x5D, 0xC2, 0x28, 0x00, 0x06, 0x11, 0x00, 0x8A, 0xBF, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1A, 0x15, 0x0C,
|
||||
0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x19, 0x7B, 0xB0, 0x44, 0x12, 0x8B, 0x01, 0xA4, 0xBC, 0x35, 0x56, 0xFE, 0xF0, 0x0C, 0xA1, 0x00, 0x43, 0xFD, 0x00, 0x7B, 0x47, 0x4D,
|
||||
0x92, 0x00, 0xCE, 0xEF, 0x0C, 0x00, 0x55, 0x6B, 0x0E, 0x00, 0xA9, 0x08, 0x00, 0x8A, 0x09, 0xC6, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1B, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1A, 0x7B, 0xB0, 0x44, 0x25, 0xAF, 0x01, 0xD4, 0x10, 0x50, 0x81, 0x14, 0xC4, 0x0C, 0xA1, 0x00, 0x29, 0xFD, 0x00, 0x7B, 0xA9, 0xFD, 0xBE, 0x00, 0x17, 0x91,
|
||||
0x19, 0x00, 0x63, 0x98, 0xC1, 0x00, 0x12, 0xFF, 0x3F, 0x8A, 0x9F, 0x4C, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0x1C, 0x00, 0xB0, 0x14, 0x3D, 0x4B, 0x03, 0x1C, 0xF4, 0x0E, 0xF2, 0x19, 0x63, 0x0C, 0xA1, 0x00, 0x2E, 0xFD, 0xD4, 0x49, 0x34, 0x1C, 0xC2, 0x00, 0x7E, 0x9D, 0x60, 0x00, 0x79, 0x3B,
|
||||
0x17, 0x00, 0x2A, 0xF6, 0x3F, 0x8A, 0x99, 0x1E, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x0F, 0x0C, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x00,
|
||||
0xB0, 0x14, 0x9C, 0x70, 0x03, 0x50, 0xC4, 0x2B, 0x21, 0xFC, 0xF9, 0x0C, 0xA1, 0x00, 0x44, 0xFD, 0xD4, 0x49, 0x07, 0x9B, 0x6A, 0x00, 0x77, 0x0C, 0x90, 0x00, 0xE5, 0x6F, 0x9E, 0x00, 0xF8, 0xFD,
|
||||
0x3F, 0x8A, 0x8C, 0x9F, 0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x1F, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1E, 0x7B, 0xB0, 0x04, 0x9F, 0xDA,
|
||||
0x01, 0x5F, 0x6C, 0x55, 0x80, 0x08, 0xD4, 0x0C, 0xA1, 0x00, 0x5E, 0xFD, 0x00, 0x7B, 0xCB, 0xAE, 0x6A, 0x00, 0x9B, 0x04, 0x0E, 0x00, 0x96, 0x65, 0x3A, 0x00, 0x5F, 0x07, 0x80, 0x8A, 0xAA, 0xFA,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x34, 0x00, 0x02, 0x00, 0x00, 0x20, 0x15, 0x0C, 0x11, 0x13, 0x38, 0x1C, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x1F, 0x7B, 0xB0, 0x44, 0x7E, 0x41, 0x01, 0x92, 0xEF, 0x2A,
|
||||
0x99, 0x09, 0x6C, 0x0D, 0xA1, 0x00, 0x40, 0xFD, 0x00, 0x7B, 0x3C, 0xB6, 0x3E, 0x00, 0x0C, 0xA2, 0x9E, 0x00, 0x27, 0x24, 0xDF, 0x00, 0xE0, 0xFF, 0xBF, 0x8A, 0xEB, 0xFB, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x24, 0x00, 0x02, 0x00, 0x01, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x23, 0x00, 0xB0, 0x44, 0x55, 0xF1, 0x01, 0x0A, 0x01, 0xB6, 0x8F, 0x10, 0x40, 0x8D,
|
||||
0x04, 0x00, 0x8A, 0x08, 0x0E, 0x00, 0x92, 0x02, 0xB5, 0x62, 0x13, 0x80, 0x24, 0x00, 0x02, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x30, 0x00,
|
||||
0xB0, 0x44, 0x66, 0xC5, 0x03, 0x31, 0x1B, 0xBF, 0xC2, 0x02, 0x40, 0x8D, 0x04, 0x00, 0x8A, 0x08, 0x0E, 0x00, 0x02, 0x61, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x01, 0x15, 0x0C,
|
||||
0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x9F, 0xBD, 0xD2, 0x04, 0x7B, 0x94, 0x00, 0x0C, 0xC5, 0x40, 0x6B, 0x08, 0x38, 0xC3, 0x24, 0xFD, 0xC5, 0xC3, 0xA5, 0x57, 0xE1, 0x21,
|
||||
0x3E, 0x01, 0x58, 0x1D, 0x78, 0x3A, 0x38, 0x13, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x02, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA0, 0xBD,
|
||||
0xB2, 0x04, 0x91, 0x39, 0x00, 0x56, 0xDD, 0x3F, 0x2B, 0x17, 0x59, 0xC0, 0x82, 0xEF, 0x6C, 0x9A, 0xA8, 0x57, 0x7C, 0x9D, 0x72, 0x07, 0xBA, 0x27, 0x78, 0x3A, 0xB1, 0x11, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x2C, 0x00, 0x02, 0x00, 0x06, 0x03, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA1, 0xBD, 0xD2, 0x04, 0xBE, 0x31, 0x00, 0xB5, 0xD6, 0x3F, 0x6B, 0x19, 0x87, 0xDB,
|
||||
0x80, 0xFE, 0x42, 0x0C, 0xAB, 0x57, 0xDE, 0xA0, 0x21, 0x07, 0xF9, 0x23, 0x74, 0x3A, 0x7E, 0x46, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x04, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA2, 0xBD, 0xB2, 0x04, 0x57, 0x31, 0x00, 0x4B, 0xBE, 0x3F, 0xAB, 0x21, 0x5E, 0x0B, 0x3F, 0xFC, 0x75, 0x74, 0xAD, 0x57, 0x5F, 0xB2, 0x07, 0x03, 0x1B, 0x2B,
|
||||
0x70, 0x3A, 0xBB, 0x0F, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x05, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA3, 0xBD, 0xD2, 0x04, 0x33, 0x11,
|
||||
0x00, 0x49, 0xAC, 0x3F, 0x6B, 0x28, 0xE3, 0x3A, 0x7D, 0xFD, 0x5F, 0xDB, 0xAF, 0x57, 0x9D, 0x88, 0x4D, 0x02, 0x72, 0x2B, 0x6C, 0x3A, 0x3E, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00,
|
||||
0x06, 0x06, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA4, 0xBD, 0xD2, 0x04, 0xEC, 0x1E, 0x00, 0xD0, 0xF5, 0x3F, 0x2B, 0x37, 0x2E, 0xF3, 0xBA, 0x80, 0x9A, 0xA6,
|
||||
0xB2, 0x57, 0xF7, 0x5D, 0x55, 0x03, 0xF4, 0x1C, 0x68, 0x3A, 0x19, 0x49, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x07, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0xA5, 0xBD, 0xD2, 0x84, 0xCD, 0x4A, 0x02, 0x75, 0xE1, 0x3F, 0x6B, 0x39, 0x75, 0x51, 0x48, 0x81, 0x45, 0x3F, 0xA1, 0x57, 0x5D, 0xA0, 0x16, 0x06, 0x27, 0x24, 0x84, 0x3A, 0xA8, 0x47,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x08, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA6, 0xBD, 0xD2, 0x04, 0x3F, 0xAB, 0x00, 0xC5, 0xCE, 0x3F,
|
||||
0xAB, 0x41, 0x2F, 0x8F, 0x06, 0x82, 0x68, 0x8F, 0xA3, 0x57, 0xB1, 0xB2, 0x4E, 0x07, 0x51, 0x24, 0x90, 0x3A, 0x81, 0x71, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x09, 0x15, 0x0C,
|
||||
0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA7, 0xBD, 0xD2, 0x04, 0xEF, 0x93, 0x00, 0x15, 0x7A, 0x40, 0xAB, 0x4F, 0xD9, 0xD5, 0x4F, 0xFF, 0xD6, 0x42, 0xA5, 0x57, 0xAC, 0x90,
|
||||
0x39, 0x06, 0x3F, 0x11, 0x94, 0x3B, 0xA2, 0xFC, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0A, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA8, 0xBD,
|
||||
0xD2, 0x84, 0x00, 0xC3, 0x00, 0xBA, 0x16, 0x40, 0x6B, 0x56, 0xF5, 0x1B, 0x8E, 0x82, 0xD8, 0x8B, 0xA7, 0x57, 0x1B, 0x06, 0xE9, 0x06, 0x2D, 0x21, 0x94, 0x3B, 0x71, 0x55, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x2C, 0x00, 0x02, 0x00, 0x06, 0x0B, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xA9, 0xBD, 0xD2, 0x04, 0xD3, 0x18, 0x00, 0x90, 0x2C, 0x40, 0x2B, 0x58, 0xCF, 0x2D,
|
||||
0x8C, 0x7E, 0xEF, 0x12, 0xAA, 0x57, 0xD2, 0xB1, 0xAD, 0x01, 0x45, 0x27, 0x94, 0x3B, 0x8F, 0x20, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0C, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAA, 0xBD, 0xD2, 0x04, 0x7F, 0x3D, 0x00, 0x5E, 0x7A, 0x40, 0xEB, 0x67, 0x2C, 0x45, 0xCA, 0xF6, 0x48, 0xA8, 0xAC, 0x57, 0xF8, 0xD5, 0x66, 0x04, 0x36, 0x22,
|
||||
0x94, 0x3B, 0x5B, 0x01, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0D, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAB, 0xBD, 0xD2, 0x84, 0xC1, 0x1E,
|
||||
0x00, 0xC6, 0xFF, 0x3F, 0xAB, 0x6F, 0xFE, 0x69, 0x28, 0x82, 0xE4, 0x06, 0xAF, 0x57, 0x3D, 0x34, 0x38, 0x02, 0xFB, 0x20, 0x94, 0x3B, 0xC8, 0xB3, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00,
|
||||
0x06, 0x0E, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAC, 0xBD, 0xB2, 0x04, 0x41, 0xAE, 0x00, 0xFC, 0x51, 0x40, 0x6B, 0x76, 0x2D, 0x7B, 0xA6, 0xFD, 0x9C, 0x9F,
|
||||
0xB1, 0x57, 0xDA, 0xAF, 0xDE, 0x01, 0xB5, 0x1B, 0x98, 0x3B, 0x8D, 0x75, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x0F, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0xAD, 0xBD, 0xD2, 0x04, 0x32, 0x99, 0x02, 0x17, 0x61, 0x40, 0x2B, 0x78, 0x76, 0xB4, 0xD3, 0xFC, 0x10, 0x45, 0xA0, 0x57, 0x67, 0xC7, 0xEF, 0x02, 0x93, 0x20, 0x90, 0x3B, 0xC3, 0x1E,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x10, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAE, 0xBD, 0xD2, 0x04, 0x70, 0x64, 0x02, 0x10, 0xC5, 0x40,
|
||||
0xEB, 0x87, 0x72, 0x87, 0xF1, 0x80, 0x8E, 0xF2, 0xA2, 0x57, 0x57, 0x0A, 0x76, 0x0C, 0xD9, 0x17, 0x88, 0x3B, 0x91, 0xAA, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x11, 0x15, 0x0C,
|
||||
0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xAF, 0xBD, 0xD2, 0x04, 0x95, 0xB0, 0x00, 0x24, 0x2D, 0x40, 0x2B, 0x89, 0x3B, 0x4D, 0x5B, 0xF0, 0xAB, 0x5C, 0xA4, 0x57, 0x50, 0x95,
|
||||
0x23, 0x04, 0xB1, 0x3A, 0x0C, 0x3A, 0x59, 0x64, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x12, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB0, 0xBD,
|
||||
0xD2, 0x04, 0x61, 0xBD, 0x00, 0xC7, 0x14, 0x40, 0x6B, 0x97, 0x82, 0x8D, 0xD9, 0xFC, 0xB9, 0xB4, 0xA6, 0x57, 0x71, 0xE6, 0x0F, 0x05, 0x96, 0x40, 0x10, 0x3A, 0xD3, 0x7B, 0xB5, 0x62, 0x13, 0x80,
|
||||
0x2C, 0x00, 0x02, 0x00, 0x06, 0x13, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB1, 0xBD, 0xD2, 0x04, 0x61, 0x35, 0x00, 0xC3, 0xC6, 0x3F, 0xEB, 0x98, 0x44, 0x01,
|
||||
0x98, 0x85, 0xA8, 0xE9, 0xA8, 0x57, 0xC2, 0xA4, 0x0D, 0x01, 0xFD, 0x45, 0x10, 0x3A, 0x94, 0x41, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x14, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A,
|
||||
0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB2, 0xBD, 0xD2, 0x04, 0xB1, 0x18, 0x00, 0x5D, 0x11, 0x40, 0xAB, 0xA0, 0xC8, 0xDF, 0x15, 0x82, 0xB1, 0xB9, 0xAB, 0x57, 0xF1, 0xE9, 0xC1, 0x03, 0x4A, 0x46,
|
||||
0x10, 0x3A, 0xA7, 0x43, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x15, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB3, 0xBD, 0xD2, 0x04, 0x28, 0x00,
|
||||
0x02, 0x5E, 0x5E, 0x40, 0x2B, 0xA9, 0x27, 0xA6, 0x73, 0x88, 0xE6, 0x73, 0xAE, 0x57, 0xCC, 0x8C, 0xAD, 0x02, 0x36, 0x3F, 0x14, 0x3A, 0xAF, 0x7C, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00,
|
||||
0x06, 0x16, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB4, 0xBD, 0xD2, 0x04, 0x85, 0xEC, 0x00, 0x91, 0xEE, 0x3F, 0x6B, 0xB7, 0x72, 0xF2, 0xD1, 0x84, 0x7D, 0xBE,
|
||||
0xB0, 0x57, 0xEE, 0x05, 0x09, 0x08, 0x71, 0x43, 0x18, 0x3A, 0x1D, 0x65, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x17, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A,
|
||||
0x01, 0x03, 0xB5, 0xBD, 0xD2, 0x04, 0xB1, 0x72, 0x02, 0x0E, 0xDA, 0x3E, 0xEB, 0xB8, 0xE4, 0xB4, 0xAF, 0x80, 0x21, 0xAF, 0xB3, 0x57, 0x7C, 0x50, 0x49, 0x00, 0x24, 0x43, 0x18, 0x3A, 0x26, 0xE7,
|
||||
0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x02, 0x00, 0x06, 0x18, 0x15, 0x0C, 0x15, 0x15, 0x00, 0x2A, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0xB6, 0xBD, 0xD2, 0x04, 0xE1, 0x9D, 0x00, 0xA2, 0x0C, 0x40,
|
||||
0xAB, 0xC0, 0xEA, 0x39, 0xDD, 0xFD, 0x09, 0xEC, 0xA1, 0x57, 0x92, 0xAE, 0x92, 0x03, 0x96, 0x2B, 0x08, 0x3A, 0x64, 0xD1, 0xB5, 0x62, 0x13, 0x80, 0x78, 0x00, 0x03, 0x00, 0x00, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x19, 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x07, 0x00, 0x8A, 0x08, 0x89, 0x08, 0x12, 0x07,
|
||||
0x12, 0x00, 0xC1, 0x03, 0x00, 0x00, 0x19, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x32, 0x00, 0x00, 0x80, 0xB2, 0x00, 0x00, 0x80, 0xB3, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0xEC, 0x47, 0x00, 0x00,
|
||||
0x60, 0xC8, 0x00, 0x00, 0x80, 0xC7, 0x00, 0x00, 0x50, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x22, 0xB5, 0x62, 0x13, 0x80, 0x2C, 0x00, 0x03, 0x00, 0x06, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x4A, 0x01, 0x03, 0x12, 0x00, 0x06, 0x07, 0x11, 0x00, 0x06, 0x15, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xBD, 0x3A, 0xBD, 0x02, 0x92, 0xC7,
|
||||
0x1E, 0x00, 0xBD, 0x3A, 0x00, 0x00, 0x83, 0xEB, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x02, 0x15, 0x0C, 0x04, 0x14, 0x0F, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x01, 0x5E,
|
||||
0xAD, 0x14, 0x0D, 0xD9, 0x01, 0x99, 0x8A, 0x08, 0x57, 0xFD, 0x00, 0x00, 0x00, 0xC4, 0xA0, 0xFF, 0xAF, 0x13, 0x31, 0x04, 0x00, 0xED, 0x07, 0xBB, 0xE2, 0xC1, 0xE2, 0xA6, 0xA2, 0x5F, 0x18, 0xC2,
|
||||
0x8E, 0x08, 0x42, 0xC9, 0xD5, 0x17, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x07, 0x20, 0x00, 0x50, 0xF8, 0xAB, 0xA6, 0xD0, 0xC2, 0x7C, 0xE2, 0xDC, 0x80, 0x36, 0x92, 0x07, 0x9C, 0x36, 0xA1, 0x2E,
|
||||
0x78, 0x0C, 0x91, 0xCE, 0x7E, 0xE6, 0x3E, 0x63, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x05, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x04, 0x5E,
|
||||
0xAD, 0x14, 0xBB, 0x54, 0x01, 0x85, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0xA9, 0xFF, 0xAF, 0x13, 0xEE, 0xD1, 0x3F, 0xF4, 0xE8, 0xBA, 0x02, 0x42, 0xDB, 0xA6, 0xE2, 0x4F, 0x93, 0xCC,
|
||||
0x86, 0x08, 0x5E, 0xE0, 0xFB, 0x01, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xB2, 0xC2, 0xA1, 0xA2, 0x5A, 0xF1, 0x5A, 0x67, 0xD2, 0x32, 0xCB, 0x87, 0x73, 0xEA, 0xA6, 0x22, 0x7E, 0xCE,
|
||||
0xB7, 0xF8, 0x59, 0xCB, 0x13, 0xCF, 0x90, 0x3D, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x07, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x06, 0x5E,
|
||||
0xAD, 0x14, 0x1C, 0x84, 0x01, 0x3C, 0x8A, 0x08, 0x58, 0x01, 0x00, 0x00, 0x40, 0x44, 0x5B, 0x01, 0xA0, 0x13, 0xB1, 0x77, 0x00, 0xF4, 0xE8, 0xBA, 0x02, 0x02, 0xDC, 0xA6, 0x62, 0x0D, 0x9B, 0x10,
|
||||
0x8D, 0x08, 0xE8, 0xB3, 0x12, 0x04, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xD3, 0xB5, 0xB7, 0x0A, 0x9E, 0x12, 0x42, 0xA2, 0x14, 0xB9, 0xAD, 0xE8, 0xD6, 0xBA, 0xA1, 0x04, 0xEB, 0x56,
|
||||
0xE5, 0x29, 0xD2, 0xF1, 0x3E, 0xD4, 0x51, 0xD3, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x09, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x08, 0x5E,
|
||||
0xAD, 0x14, 0xAE, 0x75, 0x01, 0xEB, 0x8A, 0x08, 0x58, 0x7D, 0x00, 0x00, 0x40, 0x44, 0x27, 0x00, 0xA0, 0x13, 0x2A, 0x09, 0x80, 0x01, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0x42, 0x7D, 0x43, 0x25,
|
||||
0x97, 0x08, 0x0E, 0x55, 0xE8, 0x19, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x34, 0x43, 0x60, 0xE2, 0x59, 0x42, 0xAE, 0xE1, 0xE5, 0x34, 0x86, 0x80, 0xA7, 0xDF, 0xA3, 0xE9, 0x4E, 0xB1,
|
||||
0xF7, 0x28, 0xB4, 0xBC, 0x8B, 0xD9, 0x5E, 0x5F, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x0D, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x0C, 0x5E,
|
||||
0xAD, 0x14, 0x79, 0x8D, 0x01, 0x81, 0x8A, 0x08, 0x58, 0x01, 0x00, 0x00, 0x40, 0x44, 0x91, 0x01, 0xA0, 0x13, 0x16, 0xD5, 0x3F, 0xF4, 0xE8, 0xBA, 0x02, 0x42, 0xDC, 0xA6, 0x62, 0x60, 0x15, 0x2D,
|
||||
0x81, 0x08, 0x74, 0x9A, 0x0E, 0x09, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x43, 0x1D, 0xEA, 0x22, 0xB7, 0x2E, 0xD8, 0x3E, 0x59, 0x3A, 0x55, 0x75, 0x09, 0xE7, 0x0A, 0x39, 0xC6, 0x02,
|
||||
0x6D, 0xFD, 0xE5, 0xF4, 0x5E, 0xEB, 0x85, 0x41, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x10, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x0F, 0x5E,
|
||||
0xAD, 0x14, 0xB3, 0xBB, 0x01, 0x4E, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0x49, 0xFE, 0xAF, 0x13, 0x9A, 0xA4, 0x3F, 0xF5, 0xE8, 0xBA, 0x02, 0x02, 0xDC, 0xA6, 0xA2, 0x33, 0xC9, 0x6D,
|
||||
0x90, 0x08, 0x5A, 0x9A, 0xE3, 0x00, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x0D, 0xDD, 0x6D, 0xCD, 0xC2, 0x40, 0x3A, 0x97, 0x5C, 0x01, 0x02, 0x3D, 0x12, 0x48, 0x55, 0xDE, 0xBA, 0x35,
|
||||
0x8E, 0xFB, 0xE1, 0xF2, 0x92, 0xCE, 0x5C, 0xFB, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x14, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x13, 0x5E,
|
||||
0xAD, 0x14, 0x31, 0xC2, 0x01, 0x0F, 0x8A, 0x08, 0x58, 0x81, 0x00, 0x00, 0x40, 0x44, 0xF0, 0xFF, 0xAF, 0x13, 0x98, 0x87, 0x3F, 0xF7, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0x42, 0x50, 0xFF, 0x9B,
|
||||
0x8B, 0x08, 0x16, 0xF0, 0x21, 0x1C, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x93, 0x50, 0xE6, 0x06, 0xCF, 0xB8, 0x8C, 0x20, 0xB6, 0x0C, 0x26, 0x4A, 0xC1, 0xC6, 0x7E, 0x22, 0xAC, 0xC6,
|
||||
0x13, 0x14, 0x27, 0xFF, 0x18, 0xD2, 0xBA, 0xBA, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x1D, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x1C, 0x5E,
|
||||
0xAD, 0x14, 0x13, 0x8D, 0x01, 0xBC, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0xC4, 0x8F, 0xFE, 0xAF, 0x13, 0x52, 0xDC, 0x00, 0xF5, 0xE8, 0xBA, 0x02, 0xC2, 0xDC, 0xA6, 0xC2, 0x76, 0x7B, 0x55,
|
||||
0x91, 0x08, 0x2A, 0xA2, 0xE2, 0x18, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0x0F, 0xB0, 0x0B, 0x57, 0x2E, 0x66, 0x57, 0xE9, 0x32, 0x5E, 0x4E, 0x14, 0x13, 0x5E, 0xFF, 0x22, 0xFA, 0x2A,
|
||||
0x77, 0xDB, 0x2C, 0xC6, 0xC6, 0xDE, 0x74, 0x97, 0xB5, 0x62, 0x13, 0x80, 0x58, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x15, 0x0C, 0x04, 0x14, 0x1E, 0x03, 0x06, 0x1E, 0xE0, 0x4A, 0x01, 0x03, 0x1D, 0x5E,
|
||||
0xAD, 0x14, 0x8D, 0x68, 0x01, 0xBB, 0x8A, 0x08, 0x58, 0xFD, 0x00, 0x00, 0x40, 0x44, 0x28, 0xFF, 0xAF, 0x13, 0x5F, 0x5B, 0x00, 0x04, 0xE8, 0xBA, 0x02, 0x42, 0xDC, 0xA6, 0x22, 0x7D, 0x16, 0x76,
|
||||
0x89, 0x08, 0xDE, 0x80, 0xDF, 0x08, 0x7A, 0x3A, 0x00, 0x00, 0xAA, 0x6C, 0x08, 0x20, 0xE3, 0x37, 0xB1, 0x7F, 0xE8, 0xDA, 0x6C, 0x66, 0x21, 0x07, 0x1F, 0x55, 0x27, 0x27, 0x42, 0x1B, 0x68, 0x58,
|
||||
0x2E, 0x2E, 0x19, 0xA5, 0xC5, 0xE3, 0xBB, 0x38
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Offline data from u-blox Thingstream
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 26th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Offline data from u-blox Thingstream over WiFi
|
||||
and push it over I2C to a u-blox module.
|
||||
|
||||
The module still needs to be given time assistance to achieve a fast fix. This example
|
||||
uses network time to do that. If you don't have a WiFi connection, you may have to use
|
||||
a separate RTC to provide the time.
|
||||
|
||||
Note: AssistNow Offline is not supported by the ZED-F9P! "The ZED-F9P supports AssistNow Online only."
|
||||
|
||||
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
- AssistNow token string
|
||||
|
||||
Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the
|
||||
UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
const char assistNowServer[] = "https://offline-live1.services.u-blox.com";
|
||||
//const char assistNowServer[] = "https://offline-live2.services.u-blox.com"; // Alternate server
|
||||
|
||||
const char getQuery[] = "GetOfflineData.ashx?";
|
||||
const char tokenPrefix[] = "token=";
|
||||
const char tokenSuffix[] = ";";
|
||||
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
|
||||
const char getFormat[] = "format=mga;"; // Data format. Leave set to mga for M8 onwards. Can be aid.
|
||||
const char getPeriod[] = "period=1;"; // Optional. The number of weeks into the future that the data will be valid. Can be 1-5. Default = 4.
|
||||
const char getMgaResolution[] = "resolution=1;"; // Optional. Data resolution: 1 = every day; 2 = every other day; 3 = every 3rd day.
|
||||
//Note: always use resolution=1. findMGAANOForDate does not yet support finding the 'closest' date. It needs an exact match.
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include "time.h"
|
||||
|
||||
const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Set the RTC using network time. (Code taken from the SimpleTime example.)
|
||||
|
||||
// Request the time from the NTP server and use it to set the ESP32's RTC.
|
||||
configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time.
|
||||
|
||||
struct tm timeinfo;
|
||||
if(!getLocalTime(&timeinfo))
|
||||
{
|
||||
Serial.println("Failed to obtain time");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Use HTTP GET to receive the AssistNow_Online data
|
||||
|
||||
const int URL_BUFFER_SIZE = 256;
|
||||
char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
|
||||
int payloadSize = 0; // This will be updated with the length of the data we get from the server
|
||||
String payload; // This will store the data we get from the server
|
||||
|
||||
// Assemble the URL
|
||||
// Note the slash after the first %s (assistNowServer)
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getFormat,
|
||||
getPeriod,
|
||||
getMgaResolution
|
||||
);
|
||||
|
||||
Serial.print(F("HTTP URL is: "));
|
||||
Serial.println(theURL);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
http.begin(theURL);
|
||||
|
||||
int httpCode = http.GET(); // HTTP GET
|
||||
|
||||
// httpCode will be negative on error
|
||||
if(httpCode > 0)
|
||||
{
|
||||
// HTTP header has been sent and Server response header has been handled
|
||||
Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
|
||||
|
||||
// If the GET was successful, read the data
|
||||
if(httpCode == HTTP_CODE_OK) // Check for code 200
|
||||
{
|
||||
payloadSize = http.getSize();
|
||||
Serial.printf("Server returned %d bytes\r\n", payloadSize);
|
||||
|
||||
payload = http.getString(); // Get the payload
|
||||
|
||||
// Pretty-print the payload as HEX
|
||||
/*
|
||||
int i;
|
||||
for(i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (payload[i] < 0x10) // Print leading zero
|
||||
Serial.print("0");
|
||||
Serial.print(payload[i], HEX);
|
||||
Serial.print(" ");
|
||||
if ((i % 16) == 15)
|
||||
Serial.println();
|
||||
}
|
||||
if ((i % 16) != 15)
|
||||
Serial.println();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Find where the AssistNow data for today starts and ends
|
||||
|
||||
size_t todayStart = 0; // Default to sending all the data
|
||||
size_t tomorrowStart = (size_t)payloadSize;
|
||||
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
// Find the start of today's data
|
||||
todayStart = myGNSS.findMGAANOForDate(payload, (size_t)payloadSize, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
|
||||
if (todayStart < (size_t)payloadSize)
|
||||
{
|
||||
Serial.print(F("Found the data for today starting at location "));
|
||||
Serial.println(todayStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Could not find the data for today. This will not work well. The GNSS needs help to start up quickly.");
|
||||
}
|
||||
|
||||
// Find the start of tomorrow's data
|
||||
tomorrowStart = myGNSS.findMGAANOForDate(payload, (size_t)payloadSize, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, 1);
|
||||
if (tomorrowStart < (size_t)payloadSize)
|
||||
{
|
||||
Serial.print(F("Found the data for tomorrow starting at location "));
|
||||
Serial.println(tomorrowStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Could not find the data for tomorrow. (Today's data may be the last?)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly.");
|
||||
}
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the RTC time to the module
|
||||
|
||||
if(getLocalTime(&timeinfo)) // Get the local time again, just to make sure we are using the most accurate time
|
||||
{
|
||||
// setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here.
|
||||
// Have a look at the library source code for more details.
|
||||
myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
|
||||
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly.");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow data for today to the module - without the time
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
|
||||
#ifndef USE_MGA_ACKs
|
||||
|
||||
// ***** Don't use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Push the AssistNow data for today. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages.
|
||||
myGNSS.pushAssistNowData(todayStart, true, payload, tomorrowStart - todayStart);
|
||||
|
||||
#else
|
||||
|
||||
// ***** Use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data
|
||||
myGNSS.setAckAiding(1);
|
||||
|
||||
// Speed things up by setting setI2CpollingWait to 1ms
|
||||
myGNSS.setI2CpollingWait(1);
|
||||
|
||||
// Push the AssistNow data for today.
|
||||
myGNSS.pushAssistNowData(todayStart, true, payload, tomorrowStart - todayStart, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100);
|
||||
|
||||
// Set setI2CpollingWait to 125ms to avoid pounding the I2C bus
|
||||
myGNSS.setI2CpollingWait(125);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Disconnect the WiFi as it's no longer needed
|
||||
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
Serial.println(F("WiFi disconnected"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 24th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi
|
||||
and push it over I2C to a u-blox module.
|
||||
|
||||
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
- AssistNow token string
|
||||
|
||||
Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the
|
||||
UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
const char assistNowServer[] = "https://online-live1.services.u-blox.com";
|
||||
//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server
|
||||
|
||||
const char getQuery[] = "GetOnlineData.ashx?";
|
||||
const char tokenPrefix[] = "token=";
|
||||
const char tokenSuffix[] = ";";
|
||||
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
|
||||
const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Use HTTP GET to receive the AssistNow_Online data
|
||||
|
||||
const int URL_BUFFER_SIZE = 256;
|
||||
char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
|
||||
int payloadSize = 0; // This will be updated with the length of the data we get from the server
|
||||
String payload; // This will store the data we get from the server
|
||||
|
||||
// Assemble the URL
|
||||
// Note the slash after the first %s (assistNowServer)
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getDataType);
|
||||
|
||||
Serial.print(F("HTTP URL is: "));
|
||||
Serial.println(theURL);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
http.begin(theURL);
|
||||
|
||||
int httpCode = http.GET(); // HTTP GET
|
||||
|
||||
// httpCode will be negative on error
|
||||
if(httpCode > 0)
|
||||
{
|
||||
// HTTP header has been sent and Server response header has been handled
|
||||
Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
|
||||
|
||||
// If the GET was successful, read the data
|
||||
if(httpCode == HTTP_CODE_OK) // Check for code 200
|
||||
{
|
||||
payloadSize = http.getSize();
|
||||
Serial.printf("Server returned %d bytes\r\n", payloadSize);
|
||||
|
||||
payload = http.getString(); // Get the payload
|
||||
|
||||
// Pretty-print the payload as HEX
|
||||
/*
|
||||
int i;
|
||||
for(i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (payload[i] < 0x10) // Print leading zero
|
||||
Serial.print("0");
|
||||
Serial.print(payload[i], HEX);
|
||||
Serial.print(" ");
|
||||
if ((i % 16) == 15)
|
||||
Serial.println();
|
||||
}
|
||||
if ((i % 16) != 15)
|
||||
Serial.println();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow data to the module
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
#ifndef USE_MGA_ACKs
|
||||
|
||||
// ***** Don't use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Push all the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages.
|
||||
myGNSS.pushAssistNowData(payload, (size_t)payloadSize);
|
||||
|
||||
#else
|
||||
|
||||
// ***** Use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data
|
||||
myGNSS.setAckAiding(1);
|
||||
|
||||
// Speed things up by setting setI2CpollingWait to 1ms
|
||||
myGNSS.setI2CpollingWait(1);
|
||||
|
||||
// Push all the AssistNow data.
|
||||
// We have called setAckAiding(1) to instruct the module to return MGA-ACK messages.
|
||||
// So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES.
|
||||
// But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the
|
||||
// MGA-ACK messages are actually enabled.
|
||||
// Wait for up to 100ms for each ACK to arrive! 100ms is a bit excessive... 7ms is nearer the mark.
|
||||
myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 100);
|
||||
|
||||
// Set setI2CpollingWait to 125ms to avoid pounding the I2C bus
|
||||
myGNSS.setI2CpollingWait(125);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Serial.println(F("Here we go!"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 24th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi
|
||||
and push it over I2C to a u-blox module.
|
||||
|
||||
The AssistNow Online data is valid for 2-4 hours, so it can be re-used.
|
||||
BUT you need to provide the time assistance separately.
|
||||
This example shows how to do that.
|
||||
The ESP32's RTC is set from network time.
|
||||
The RTC time is pushed to the module using setUTCTimeAssistance,
|
||||
followed by the AssistNow data (without time).
|
||||
|
||||
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
- AssistNow token string
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
const char assistNowServer[] = "https://online-live1.services.u-blox.com";
|
||||
//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server
|
||||
|
||||
const char getQuery[] = "GetOnlineData.ashx?";
|
||||
const char tokenPrefix[] = "token=";
|
||||
const char tokenSuffix[] = ";";
|
||||
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
|
||||
const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include "time.h"
|
||||
|
||||
const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Set the RTC using network time. (Code taken from the SimpleTime example.)
|
||||
|
||||
// Request the time from the NTP server and use it to set the ESP32's RTC.
|
||||
configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time.
|
||||
|
||||
struct tm timeinfo;
|
||||
if(!getLocalTime(&timeinfo))
|
||||
{
|
||||
Serial.println("Failed to obtain time");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Use HTTP GET to receive the AssistNow_Online data
|
||||
|
||||
const int URL_BUFFER_SIZE = 256;
|
||||
char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
|
||||
int payloadSize = 0; // This will be updated with the length of the data we get from the server
|
||||
String payload; // This will store the data we get from the server
|
||||
|
||||
// Assemble the URL
|
||||
// Note the slash after the first %s (assistNowServer)
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getDataType);
|
||||
|
||||
Serial.print(F("HTTP URL is: "));
|
||||
Serial.println(theURL);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
http.begin(theURL);
|
||||
|
||||
int httpCode = http.GET(); // HTTP GET
|
||||
|
||||
// httpCode will be negative on error
|
||||
if(httpCode > 0)
|
||||
{
|
||||
// HTTP header has been sent and Server response header has been handled
|
||||
Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
|
||||
|
||||
// If the GET was successful, read the data
|
||||
if(httpCode == HTTP_CODE_OK) // Check for code 200
|
||||
{
|
||||
payloadSize = http.getSize();
|
||||
Serial.printf("Server returned %d bytes\r\n", payloadSize);
|
||||
|
||||
payload = http.getString(); // Get the payload
|
||||
|
||||
// Pretty-print the payload as HEX
|
||||
/*
|
||||
int i;
|
||||
for(i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (payload[i] < 0x10) // Print leading zero
|
||||
Serial.print("0");
|
||||
Serial.print(payload[i], HEX);
|
||||
Serial.print(" ");
|
||||
if ((i % 16) == 15)
|
||||
Serial.println();
|
||||
}
|
||||
if ((i % 16) != 15)
|
||||
Serial.println();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the RTC time to the module
|
||||
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
// setUTCTimeAssistance uses a default time accuracy of 2 seconds which should be OK here.
|
||||
// Have a look at the library source code for more details.
|
||||
myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
|
||||
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly.");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow data to the module - WITHOUT THE TIME
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
// Push the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages.
|
||||
// The 'true' parameter tells pushAssistNowData not to push any time data from the payload.
|
||||
myGNSS.pushAssistNowData(true, payload, (size_t)payloadSize);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Disconnect the WiFi as it's no longer needed
|
||||
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
Serial.println(F("WiFi disconnected"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 24th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi
|
||||
and push it over I2C to a u-blox module.
|
||||
|
||||
This example shows how to provide initial position assistance. Uncomment #define USE_SERVER_ASSISTANCE
|
||||
below to include the position in the AssistNow data request, instead of using setPositionAssistanceLLH.
|
||||
|
||||
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
- AssistNow token string
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
//#define USE_SERVER_ASSISTANCE // Uncomment this line to include the position in the AssistNow data request
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
const char assistNowServer[] = "https://online-live1.services.u-blox.com";
|
||||
//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server
|
||||
|
||||
const char getQuery[] = "GetOnlineData.ashx?";
|
||||
const char tokenPrefix[] = "token=";
|
||||
const char tokenSuffix[] = ";";
|
||||
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
|
||||
const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos
|
||||
|
||||
#ifdef USE_SERVER_ASSISTANCE
|
||||
const char useLatitude[] = "lat=55.0;"; // Use an approximate latitude of 55 degrees north. Replace this with your latitude.
|
||||
const char useLongitude[] = "lon=-1.0;"; // Use an approximate longitude of 1 degree west. Replace this with your longitude.
|
||||
const char useAlt[] = "alt=100;"; // Use an approximate latitude of 100m above WGS84. Replace this with your altitude.
|
||||
const char usePosAcc[] = "pacc=100000;"; // Use a position accuracy of 100000m (100km)
|
||||
#endif
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include "time.h"
|
||||
|
||||
const char* ntpServer = "pool.ntp.org"; // The Network Time Protocol Server
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Start I2C. Connect to the GNSS.
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Set the RTC using network time. (Code taken from the SimpleTime example.)
|
||||
|
||||
// Request the time from the NTP server and use it to set the ESP32's RTC.
|
||||
configTime(0, 0, ntpServer); // Set the GMT and daylight offsets to zero. We need UTC, not local time.
|
||||
|
||||
struct tm timeinfo;
|
||||
if(!getLocalTime(&timeinfo))
|
||||
{
|
||||
Serial.println("Failed to obtain time");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(&timeinfo, "Time is: %A, %B %d %Y %H:%M:%S");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Use HTTP GET to receive the AssistNow_Online data
|
||||
|
||||
const int URL_BUFFER_SIZE = 256;
|
||||
char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
|
||||
int payloadSize = 0; // This will be updated with the length of the data we get from the server
|
||||
String payload; // This will store the data we get from the server
|
||||
|
||||
// Assemble the URL
|
||||
// Note the slash after the first %s (assistNowServer)
|
||||
#ifdef USE_SERVER_ASSISTANCE
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getDataType,
|
||||
useLatitude,
|
||||
useLongitude,
|
||||
useAlt,
|
||||
usePosAcc);
|
||||
#else
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getDataType);
|
||||
#endif
|
||||
|
||||
Serial.print(F("HTTP URL is: "));
|
||||
Serial.println(theURL);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
http.begin(theURL);
|
||||
|
||||
int httpCode = http.GET(); // HTTP GET
|
||||
|
||||
// httpCode will be negative on error
|
||||
if(httpCode > 0)
|
||||
{
|
||||
// HTTP header has been sent and Server response header has been handled
|
||||
Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
|
||||
|
||||
// If the GET was successful, read the data
|
||||
if(httpCode == HTTP_CODE_OK) // Check for code 200
|
||||
{
|
||||
payloadSize = http.getSize();
|
||||
Serial.printf("Server returned %d bytes\r\n", payloadSize);
|
||||
|
||||
payload = http.getString(); // Get the payload
|
||||
|
||||
// Pretty-print the payload as HEX
|
||||
/*
|
||||
int i;
|
||||
for(i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (payload[i] < 0x10) // Print leading zero
|
||||
Serial.print("0");
|
||||
Serial.print(payload[i], HEX);
|
||||
Serial.print(" ");
|
||||
if ((i % 16) == 15)
|
||||
Serial.println();
|
||||
}
|
||||
if ((i % 16) != 15)
|
||||
Serial.println();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Speed things up by setting setI2CpollingWait to 1ms
|
||||
myGNSS.setI2CpollingWait(1);
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data
|
||||
myGNSS.setAckAiding(1);
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the RTC time to the module
|
||||
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
if(getLocalTime(&timeinfo))
|
||||
{
|
||||
// Provide time assistance. Use the UBX_MGA_ACK_DATA0 acknowledgements. Set tAccS to 2 seconds.
|
||||
myGNSS.setUTCTimeAssistance(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
|
||||
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, 0, 2, 0, 0, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Failed to obtain time. This will not work well. The GNSS needs accurate time to start up quickly.");
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// If desired - push initial position assistance to the module
|
||||
|
||||
#ifndef USE_SERVER_ASSISTANCE
|
||||
|
||||
// Use 55 degrees (*10^7) north, 1 degree (*10^7) west, 100m (10000cm) altitude, 100km (10000000cm) accuracy. Replace these with your position.
|
||||
// The units for lat and lon are degrees * 1e-7 (WGS84)
|
||||
// The units for alt (WGS84) and posAcc (stddev) are cm.
|
||||
myGNSS.setPositionAssistanceLLH(550000000, -10000000, 10000, 10000000, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100);
|
||||
|
||||
// We could use setPositionAssistanceXYZ instead if needed.
|
||||
|
||||
#endif
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow data to the module - WITHOUT THE TIME
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
// Push the AssistNow data. Use the UBX_MGA_ACK_DATA0 acknowledgements.
|
||||
// The 'true' parameter tells pushAssistNowData not to push any time data from the payload.
|
||||
myGNSS.pushAssistNowData(true, payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_YES, 100);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Disconnect the WiFi as it's no longer needed
|
||||
|
||||
WiFi.disconnect(true);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
Serial.println(F("WiFi disconnected"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Avoid pounding the I2C bus by setting setI2CpollingWait to 125ms
|
||||
myGNSS.setI2CpollingWait(125);
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Online data from u-blox Thingstream
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: November 24th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Online data from u-blox Thingstream over WiFi
|
||||
and push it to a u-blox module using Serial.
|
||||
|
||||
You will need to have a token to be able to access Thingstream. See the AssistNow README for more details.
|
||||
|
||||
Update secrets.h with your:
|
||||
- WiFi credentials
|
||||
- AssistNow token string
|
||||
|
||||
Uncomment the "#define USE_MGA_ACKs" below to test the more robust method of using the
|
||||
UBX_MGA_ACK_DATA0 acknowledgements to confirm that each MGA message has been accepted.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
//#define USE_MGA_ACKs // Uncomment this line to use the UBX_MGA_ACK_DATA0 acknowledgements
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "secrets.h"
|
||||
|
||||
const char assistNowServer[] = "https://online-live1.services.u-blox.com";
|
||||
//const char assistNowServer[] = "https://online-live2.services.u-blox.com"; // Alternate server
|
||||
|
||||
const char getQuery[] = "GetOnlineData.ashx?";
|
||||
const char tokenPrefix[] = "token=";
|
||||
const char tokenSuffix[] = ";";
|
||||
const char getGNSS[] = "gnss=gps,glo;"; // GNSS can be: gps,qzss,glo,bds,gal
|
||||
const char getDataType[] = "datatype=eph,alm,aux;"; // Data type can be: eph,alm,aux,pos
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#define mySerial Serial1 // Use Serial1 to communicate with the GNSS module
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("AssistNow Example"));
|
||||
|
||||
while (Serial.available()) Serial.read(); // Empty the serial buffer
|
||||
Serial.println(F("Press any key to begin..."));
|
||||
while (!Serial.available()); // Wait for a keypress
|
||||
|
||||
mySerial.begin(9600); // Use 9600 baud (for u-blox M8)
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to the GNSS.
|
||||
|
||||
if (myGNSS.begin(mySerial) == false) //Connect to the Ublox module using mySerial
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("u-blox module connected"));
|
||||
|
||||
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Connect to WiFi.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.println(F("WiFi connected!"));
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Use HTTP GET to receive the AssistNow_Online data
|
||||
|
||||
const int URL_BUFFER_SIZE = 256;
|
||||
char theURL[URL_BUFFER_SIZE]; // This will contain the HTTP URL
|
||||
int payloadSize = 0; // This will be updated with the length of the data we get from the server
|
||||
String payload; // This will store the data we get from the server
|
||||
|
||||
// Assemble the URL
|
||||
// Note the slash after the first %s (assistNowServer)
|
||||
snprintf(theURL, URL_BUFFER_SIZE, "%s/%s%s%s%s%s%s",
|
||||
assistNowServer,
|
||||
getQuery,
|
||||
tokenPrefix,
|
||||
myAssistNowToken,
|
||||
tokenSuffix,
|
||||
getGNSS,
|
||||
getDataType);
|
||||
|
||||
Serial.print(F("HTTP URL is: "));
|
||||
Serial.println(theURL);
|
||||
|
||||
HTTPClient http;
|
||||
|
||||
http.begin(theURL);
|
||||
|
||||
int httpCode = http.GET(); // HTTP GET
|
||||
|
||||
// httpCode will be negative on error
|
||||
if(httpCode > 0)
|
||||
{
|
||||
// HTTP header has been sent and Server response header has been handled
|
||||
Serial.printf("[HTTP] GET... code: %d\r\n", httpCode);
|
||||
|
||||
// If the GET was successful, read the data
|
||||
if(httpCode == HTTP_CODE_OK) // Check for code 200
|
||||
{
|
||||
payloadSize = http.getSize();
|
||||
Serial.printf("Server returned %d bytes\r\n", payloadSize);
|
||||
|
||||
payload = http.getString(); // Get the payload
|
||||
|
||||
// Pretty-print the payload as HEX
|
||||
/*
|
||||
int i;
|
||||
for(i = 0; i < payloadSize; i++)
|
||||
{
|
||||
if (payload[i] < 0x10) // Print leading zero
|
||||
Serial.print("0");
|
||||
Serial.print(payload[i], HEX);
|
||||
Serial.print(" ");
|
||||
if ((i % 16) == 15)
|
||||
Serial.println();
|
||||
}
|
||||
if ((i % 16) != 15)
|
||||
Serial.println();
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf("[HTTP] GET... failed, error: %s\r\n", http.errorToString(httpCode).c_str());
|
||||
}
|
||||
|
||||
http.end();
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Push the AssistNow data to the module
|
||||
|
||||
if (payloadSize > 0)
|
||||
{
|
||||
// Uncomment the next line to enable the 'major' debug messages on Serial so you can see what AssistNow data is being sent
|
||||
//myGNSS.enableDebugging(Serial, true);
|
||||
|
||||
#ifndef USE_MGA_ACKs
|
||||
|
||||
// ***** Don't use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Push all the AssistNow data. Don't use UBX_MGA_ACK_DATA0's. Use the default delay of 7ms between messages.
|
||||
myGNSS.pushAssistNowData(payload, (size_t)payloadSize);
|
||||
|
||||
#else
|
||||
|
||||
// ***** Use the UBX_MGA_ACK_DATA0 messages *****
|
||||
|
||||
// Tell the module to return UBX_MGA_ACK_DATA0 messages when we push the AssistNow data
|
||||
myGNSS.setAckAiding(1);
|
||||
|
||||
// Push all the AssistNow data.
|
||||
// We have called setAckAiding(1) to instruct the module to return MGA-ACK messages.
|
||||
// So, we could set the pushAssistNowData mgaAck parameter to SFE_UBLOX_MGA_ASSIST_ACK_YES.
|
||||
// But, just for giggles, let's use SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE just to confirm that the
|
||||
// MGA-ACK messages are actually enabled.
|
||||
// Wait for up to 100ms for each ACK to arrive! 100ms is a bit excessive... 7ms is nearer the mark.
|
||||
myGNSS.pushAssistNowData(payload, (size_t)payloadSize, SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE, 100);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Serial.println(F("Here we go!"));
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Print the UBX-NAV-PVT data so we can see how quickly the fixType goes to 3D
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "TRex";
|
||||
const char password[] = "hasBigTeeth";
|
||||
|
||||
//Your AssistNow token
|
||||
const char myAssistNowToken[] = "58XXXXXXXXXXXXXXXXXXYQ";
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
Use ESP32 WiFi to get AssistNow Online (MGA) data from PointPerfect (broker) as a Client using MQTT
|
||||
By: Paul Clark / SparkFun
|
||||
Date: March 9th, 2022
|
||||
Based on original code by: u-blox AG / Michael Ammann
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to obtain AssistNow Online (MGA) data from a PointPerfect Broker over WiFi
|
||||
and push it over I2C to a ZED-F9x.
|
||||
It's confusing, but the Arduino is acting as a 'client' to the PointPerfect service.
|
||||
|
||||
You will need to have a valid u-blox Thingstream account and have a PointPerfect Thing and payed plan.
|
||||
To sign up, go to: https://portal.thingstream.io/app/location-services/things
|
||||
|
||||
This is a proof of concept to show how to connect via MQTT to get AssistNow MGA data.
|
||||
|
||||
For more information about MQTT, SPARTN and PointPerfect Correction Services
|
||||
please see: https://www.u-blox.com/en/product/pointperfect
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <ArduinoMqttClient.h> // Click here to get the library: http://librarymanager/All#ArduinoMqttClient
|
||||
#include "secrets.h"
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
//Global variables
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
long lastReceived_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps
|
||||
int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(F("PointPerfect AssistNow testing"));
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.println(F("u-blox module connected"));
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
|
||||
myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN);
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Set output in Hz.
|
||||
|
||||
Serial.print(F("Connecting to local WiFi"));
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("WiFi connected with IP: "));
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
while (Serial.available()) Serial.read();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available())
|
||||
{
|
||||
beginClient();
|
||||
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start MQTT Client."));
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
WiFiClientSecure wifiClient = WiFiClientSecure();
|
||||
MqttClient mqttClient(wifiClient);
|
||||
|
||||
void mqttMessageHandler(int messageSize)
|
||||
{
|
||||
const uint16_t mqttLimit = 512;
|
||||
uint8_t *mqttData = new uint8_t[mqttLimit]; // Allocate memory to hold the MQTT data
|
||||
if (mqttData == NULL)
|
||||
{
|
||||
Serial.println(F("Memory allocation for mqttData failed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print(F("Pushing data from "));
|
||||
Serial.print(mqttClient.messageTopic());
|
||||
Serial.println(F(" topic to ZED"));
|
||||
|
||||
while (mqttClient.available())
|
||||
{
|
||||
uint16_t mqttCount = 0;
|
||||
|
||||
while (mqttClient.available())
|
||||
{
|
||||
char ch = mqttClient.read();
|
||||
//Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data
|
||||
mqttData[mqttCount++] = ch;
|
||||
|
||||
if (mqttCount == mqttLimit)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mqttCount > 0)
|
||||
{
|
||||
//Push KEYS or SPARTN data to GNSS module over I2C
|
||||
myGNSS.pushRawData(mqttData, mqttCount, false);
|
||||
lastReceived_ms = millis();
|
||||
}
|
||||
}
|
||||
|
||||
delete[] mqttData;
|
||||
}
|
||||
|
||||
//Connect to MQTT broker, receive MGA, and push to ZED module over I2C
|
||||
void beginClient()
|
||||
{
|
||||
Serial.println(F("Subscribing to Broker. Press key to stop"));
|
||||
delay(10); //Wait for any serial to arrive
|
||||
while (Serial.available()) Serial.read(); //Flush
|
||||
|
||||
while (Serial.available() == 0)
|
||||
{
|
||||
//Connect if we are not already
|
||||
if (wifiClient.connected() == false)
|
||||
{
|
||||
// Connect to AWS IoT
|
||||
wifiClient.setCACert(AWS_CERT_CA);
|
||||
wifiClient.setCertificate(AWS_CERT_CRT);
|
||||
wifiClient.setPrivateKey(AWS_CERT_PRIVATE);
|
||||
mqttClient.setId(MQTT_CLIENT_ID);
|
||||
mqttClient.setKeepAliveInterval(60*1000);
|
||||
mqttClient.setConnectionTimeout( 5*1000);
|
||||
if (!mqttClient.connect(AWS_IOT_ENDPOINT, AWS_IOT_PORT)) {
|
||||
Serial.print(F("MQTT connection failed! Error code = "));
|
||||
Serial.println(mqttClient.connectError());
|
||||
return;
|
||||
} else {
|
||||
Serial.println(F("You're connected to the PointPerfect MQTT broker: "));
|
||||
Serial.println(AWS_IOT_ENDPOINT);
|
||||
// Subscribe to MQTT and register a callback
|
||||
Serial.println(F("Subscribe to Topics"));
|
||||
mqttClient.onMessage(mqttMessageHandler);
|
||||
mqttClient.subscribe(MQTT_TOPIC_ASSISTNOW);
|
||||
lastReceived_ms = millis();
|
||||
} //End attempt to connect
|
||||
} //End connected == false
|
||||
else {
|
||||
mqttClient.poll();
|
||||
}
|
||||
//Close socket if we don't have new data for 10s
|
||||
if (millis() - lastReceived_ms > maxTimeBeforeHangup_ms)
|
||||
{
|
||||
Serial.println(F("Timeout. Disconnecting..."));
|
||||
if (mqttClient.connected() == true)
|
||||
mqttClient.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
delay(10);
|
||||
}
|
||||
|
||||
Serial.println(F("User pressed a key"));
|
||||
Serial.println(F("Disconnecting..."));
|
||||
wifiClient.stop();
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//Your WiFi credentials
|
||||
const char ssid[] = "<YOUR SSID>";
|
||||
const char password[] = "<YOUR PASSWORD>";
|
||||
|
||||
// Below infomation you can set after signing up with u-blox Thingstream portal
|
||||
// and after add a new New PointPerfect Thing
|
||||
// https://portal.thingstream.io/app/location-services/things
|
||||
// in the new PointPerfect Thing you go to the credentials page and copy past the values and certificate into this.
|
||||
|
||||
// <Your PointPerfect Thing> -> Credentials -> Hostname
|
||||
const char AWS_IOT_ENDPOINT[] = "pp.services.u-blox.com";
|
||||
const unsigned short AWS_IOT_PORT = 8883;
|
||||
// <Your PointPerfect Thing> -> Credentials -> AssistNow (MGA) topic
|
||||
const char MQTT_TOPIC_ASSISTNOW[] = "/pp/ubx/mga";
|
||||
|
||||
// <Your PointPerfect Thing> -> Credentials -> Client Id
|
||||
static const char MQTT_CLIENT_ID[] = "<ADD YOUR CLIENT ID HERE>";
|
||||
|
||||
// <Your PointPerfect Thing> -> Credentials -> Amazon Root Certificate
|
||||
static const char AWS_CERT_CA[] PROGMEM = R"EOF(
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<ADD YOUR CERTICICATE HERE>
|
||||
-----END CERTIFICATE-----
|
||||
)EOF";
|
||||
|
||||
// <Your PointPerfect Thing> -> Credentials -> Client Certificate
|
||||
static const char AWS_CERT_CRT[] PROGMEM = R"KEY(
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<ADD YOUR CERTICICATE HERE>
|
||||
-----END CERTIFICATE-----
|
||||
)KEY";
|
||||
|
||||
// Get this from Thingstream Portal
|
||||
// <Your PointPerfect Thing> -> Credentials -> Client Key
|
||||
static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY(
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
<ADD YOUR KEY HERE>
|
||||
-----END RSA PRIVATE KEY-----
|
||||
)KEY";
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
# SparkFun u-blox Arduino GNSS Library - AssistNow<sup>TM</sup>
|
||||
|
||||
v2.1.0 of the library adds support for u-blox [AssistNow<sup>TM</sup> Assisted GNSS (A-GNSS)](https://www.u-blox.com/en/product/assistnow) which can dramatically reduce the time-to-first-fix.
|
||||
|
||||
To use AssistNow Online or AssistNow Offline, you will need a token to access the u-blox Thingstream server. See [below](#AssistNow-Service-Token) for details.
|
||||
|
||||
## AssistNow<sup>TM</sup> Online
|
||||
|
||||
With AssistNow Online, an Internet connected host downloads assistance data from the u-blox AssistNow Online service to the receiver at system start-up. AssistNow Online data is valid for 2 - 4 hours; beyond that fresh data must be downloaded.
|
||||
|
||||
Please see the [AssistNow_Online](./AssistNow_Online) examples for more details. These examples were written for the ESP32, but will run on other platforms too.
|
||||
|
||||
The new functions we've added to the library to support AssistNow Online are described [Support for AssistNow below](#Support-for-AssistNow).
|
||||
|
||||
## AssistNow<sup>TM</sup> Offline
|
||||
|
||||
With the AssistNow Offline service, users can download long-term orbit data over the Internet at their convenience. The orbit data can be stored in the memory of the application processor. The function requires no connectivity at system start-up, enabling a position fix within seconds, even when no network is available. AssistNow Offline offers augmentation for up to 35 days.
|
||||
|
||||
Please see the [AssistNow_Offline](./AssistNow_Offline) examples for more details. These examples were written for the ESP32, but will run on other platforms too.
|
||||
|
||||
**Note: AssistNow Offline is not supported by the ZED-F9P. "The ZED-F9P supports AssistNow Online only."**
|
||||
|
||||
The new functions we've added to the library to support AssistNow Offline are described [Support for AssistNow](#Support-for-AssistNow) and [Additional Support for AssistNow Offline](#Additional-Support-for-AssistNow-Offline).
|
||||
|
||||
## AssistNow<sup>TM</sup> Autonomous
|
||||
|
||||
AssistNow Autonomous provides aiding information without the need for a host or external network connection. Based on previous broadcast satellite ephemeris data downloaded to and stored by the GNSS receiver, AssistNow Autonomous automatically generates accurate predictions of satellite orbital data (“AssistNow Autonomous data”) that is usable for future GNSS position fixes.
|
||||
|
||||
The benefits of AssistNow Autonomous are:
|
||||
|
||||
* Faster fix in situations where GNSS satellite signals are weak
|
||||
* No connectivity required
|
||||
* Compatible with AssistNow Online (can work stand-alone, or in tandem with AssistNow Online service)
|
||||
* No integration effort; calculations are done in the background, transparent to the user
|
||||
|
||||
AssistNow Autonomous offers augmentation for up to 6 days.
|
||||
|
||||
Please see the [AssistNow_Autonomous](./AssistNow_Autonomous) examples for more details.
|
||||
|
||||
**Note: AssistNow Autonomous does not work on the ZED-F9P. "The ZED-F9P supports AssistNow Online only."**
|
||||
|
||||
The new functions we've added to the library to support AssistNow Autonomous are described [Support for AssistNow Autonomous below](#Support-for-AssistNow-Autonomous).
|
||||
|
||||
## AssistNow Service Token
|
||||
|
||||
To be able to use AssistNow Online or AssistNow Offline, you will need a token to access the u-blox Thingstream server.
|
||||
|
||||
The following u-blox resources contain useful information:
|
||||
|
||||
* [AssistNow - u-blox A-GNSS services](https://www.u-blox.com/en/product/assistnow)
|
||||
* [AssistNow Product Summary](https://www.u-blox.com/sites/default/files/products/documents/AssistNow_ProductSummary_UBX-13003352.pdf)
|
||||
* [AssistNow User Guide](https://www.u-blox.com/sites/default/files/products/documents/MultiGNSS-Assistance_UserGuide_%28UBX-13004360%29.pdf)
|
||||
* [Thingstream Pricing](https://portal.thingstream.io/pricing)
|
||||
|
||||
You can apply for a _free_ AssistNow Service Evaluation Token by completing the request form:
|
||||
|
||||
* [AssistNow Service evaluation token request form](https://www.u-blox.com/en/assistnow-service-evaluation-token-request-form)
|
||||
|
||||
The _free_ AssistNow Developer token entitles you to:
|
||||
|
||||
* AssistNow Online Developer: 100K free location requests per month. Capped.
|
||||
* AssistNow Offline Developer: 20K free location requests per month. Capped.
|
||||
* CellLocate Developer: 5K free location requests per month. Capped.
|
||||
|
||||
The free token will expire after 90 days, but you can continue to use it beyond that by registering it on [Thingstream](https://portal.thingstream.io/).
|
||||
|
||||
## Initial Position Assistance
|
||||
|
||||
You can further decrease the time-to-first-fix by providing the receiver's approximate position - if known. There are two ways to do this:
|
||||
|
||||
* The position can be specified when requesting AssistNow Online data from the server:
|
||||
* include the key name ```lat``` with the approximate user latitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -90 to 90. Example: ```lat=47.2;```
|
||||
* include the key name ```lon``` with the approximate user longitude in WGS 84 expressed in degrees and fractional degrees. Must be in range -180 to 180. Example: ```lon=8.55;```
|
||||
* include the key name ```alt``` with the approximate user altitude above WGS 84 Ellipsoid in meters. If this value is not provided, the server assumes an altitude of 0 meters. Must be in range -1000 to 50000
|
||||
* include the key name ```pacc``` with the approximate accuracy of submitted position in meters. If this value is not provided, the server assumes an accuracy of 300 km. Must be in range 0 to 6000000
|
||||
* the position assistance data will then be automatically included in the AssistNow Online data
|
||||
* Provide initial position assistance data by calling one of:
|
||||
* <b>bool setPositionAssistanceXYZ(int32_t ecefX, int32_t ecefY, int32_t ecefZ, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* The units for ```ecefX/Y/Z``` and ```posAcc``` (stddev) are cm
|
||||
* <b>bool setPositionAssistanceLLH(int32_t lat, int32_t lon, int32_t alt, uint32_t posAcc, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* The units for ```lat``` and ```lon``` are degrees * 1e-7 (WGS84). The units for ```alt``` (WGS84) and ```posAcc``` (stddev) are cm (not m)
|
||||
|
||||
## Support for AssistNow
|
||||
|
||||
```pushAssistNowData``` allows AssistNow Online, Offline or Autonomous data to be pushed to the module. As the ESP32 HTTP GET function returns a ```String```, we've included overloaded functions which allow you to pass the data as a ```String``` or as ```const uint8_t *```.
|
||||
|
||||
The String-based function declarations are:
|
||||
|
||||
* <b>size_t pushAssistNowData(const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* <b>size_t pushAssistNowData(bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* <b>size_t pushAssistNowData(size_t offset, bool skipTime, const String &dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
|
||||
The const uint8_t * function declarations are:
|
||||
|
||||
* <b>size_t pushAssistNowData(const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* <b>size_t pushAssistNowData(bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
* <b>size_t pushAssistNowData(size_t offset, bool skipTime, const uint8_t *dataBytes, size_t numDataBytes, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
|
||||
```dataBytes``` is a pointer to the AssistNow data.
|
||||
<br>
|
||||
```numDataBytes``` is the length of the AssistNow data.
|
||||
<br>
|
||||
|
||||
```pushAssistNowData``` pushes individual packets of data to the u-blox module. Sending all of the data contiguously would overload the module, so ```pushAssistNowData``` can either:
|
||||
|
||||
* insert a small delay between each packet (the default is 7ms)
|
||||
* or use the ```UBX-MGA-ACK-DATA0``` acknowledgement message to acknowledge each packet
|
||||
|
||||
```mgaAck``` controls which method is used.
|
||||
|
||||
* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_NO``` (**default**), a delay of ```maxWait``` milliseconds is inserted between each packet. ```maxWait``` defaults to 7ms.
|
||||
* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_YES```, acknowledgement messages will be expected with a _timeout_ of ```maxWait``` milliseconds. The default timeout is again 7ms, but you can change this if required by passing a different value.
|
||||
* if ```mgaAck``` is ```SFE_UBLOX_MGA_ASSIST_ACK_ENQUIRE```, the code will poll the module to enquire if the acknowledgement messages are enabled. If they are, they will be used. If not, a delay is used.
|
||||
|
||||
```setAckAiding``` enables or disables the acknowledgement messages. By default they are disabled. ```setAckAiding(1)``` will enable them. ```setAckAiding(0)``` will disable them again.
|
||||
|
||||
* <b>bool setAckAiding(uint8_t ackAiding, uint16_t maxWait);</b>
|
||||
|
||||
```getAckAiding``` returns 1 if the acknowledgement messages are enabled, 0 if they are disabled. 255 indicates an error or timeout.
|
||||
|
||||
* <b>uint8_t getAckAiding(uint16_t maxWait);</b>
|
||||
|
||||
```pushAssistNowData``` returns the number of _bytes_ pushed (not the number of _packets_). The return value should be equal to ```numDataBytes``` if all data was valid and pushed successfully.
|
||||
|
||||
AssistNow Online data is valid for 2-4 hours. 'Stale' data can be re-used but:
|
||||
|
||||
* ```pushAssistNowData``` needs to be told to skip the time information contained in the AssistNow data
|
||||
* the user needs to provide the module with UTC time separately
|
||||
|
||||
The ```skipTime``` parameter tells ```pushAssistNowData``` to skip any time information in the data. ```skipTime``` is bool. Set it to ```true``` to skip the time information.
|
||||
<br>
|
||||
|
||||
UTC time can be pushed to the module first by calling ```setUTCTimeAssistance```:
|
||||
|
||||
* <b>bool setUTCTimeAssistance(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t nanos, uint16_t tAccS, uint32_t tAccNs, uint8_t source, sfe_ublox_mga_assist_ack_e mgaAck, uint16_t maxWait);</b>
|
||||
|
||||
Only the ```year```, ```month```, ```day```, ```hour```, ```minute``` and ```second``` parameters are mandatory. The others default to sensible values. Again ```mgaAck``` and ```maxWait``` control if a delay is used when configuring the time, or if an acknowledgement message will be expected.
|
||||
<br>
|
||||
|
||||
```nanos``` (nanoseconds), ```tAccS``` (time accuracy estimate (seconds)), ```tAccNs``` (time accuracy estimate (nanoseconds)) and ```source``` (if a clock signal will be provided on EXT_INT) are optional, but are available for advanced users.
|
||||
<br>
|
||||
|
||||
```year``` numbering starts at 0; 2021 is 2021, not 121 (years since 1900). ```month``` and ```day``` numbering starts at 1, not 0.
|
||||
<br>
|
||||
|
||||
Call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```.
|
||||
|
||||
## Additional Support for AssistNow Offline
|
||||
|
||||
AssistNow Offline data downloaded from the u-blox server can contain 1-5 weeks of data. However, only the data for _today_ should be pushed the module. Sending data for past or future days will confuse the module.
|
||||
```findMGAANOForDate``` can be used to find the location of the start of the UBX-MGA-ANO data for the specified date within the offline data. That location can then be passed to ```pushAssistNowData``` using the ```offset``` parameter.
|
||||
|
||||
* <b>size_t findMGAANOForDate(const uint8_t *dataBytes, size_t numDataBytes, uint16_t year, uint8_t month, uint8_t day, uint8_t daysIntoFuture);</b>
|
||||
|
||||
The sequence of events is:
|
||||
|
||||
* call ```findMGAANOForDate``` passing the ```year```, ```month``` and ```day``` for today. ```findMGAANOForDate``` will return the location / offset of the data for today within the offline data.
|
||||
* call ```findMGAANOForDate``` again passing the ```year```, ```month``` and ```day``` for _today_ but also set ```daysIntoFuture``` to 1. ```findMGAANOForDate``` will then return the location / offset of the data for _tomorrow_ (one day into the future).
|
||||
* call ```pushAssistNowData``` setting:
|
||||
* ```offset``` to the location (offset) of today's data within the offline data
|
||||
* ```skipTime``` to ```true```
|
||||
* ```numDataBytes``` to ((tomorrow's location) - (today's location)). Only the offline data for today will be pushed.
|
||||
|
||||
```findMGAANOForDate``` will return a value of numDataBytes if the data for the chosen day cannot be found.
|
||||
<br>
|
||||
|
||||
Again, call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```.
|
||||
|
||||
## Support for AssistNow Autonomous
|
||||
|
||||
AssistNow Autonomous is disabled by default. You can enable it by calling ```setAopCfg``` and check if it is enabled by calling ```getAopCfg```:
|
||||
|
||||
* <b>uint8_t getAopCfg(uint16_t maxWait);</b>
|
||||
* <b>bool SFE_UBLOX_GNSS::setAopCfg(uint8_t aopCfg, uint16_t aopOrbMaxErr, uint16_t maxWait)</b>
|
||||
|
||||
```getAopCfg``` will return 1 if AssistNow Autonomous is enabled, 0 if disabled. 255 indicates an error or timeout.
|
||||
|
||||
```setAopCfg``` has two parameters:
|
||||
|
||||
* set ```aopCfg``` to 1 to enable AssistNow Autonomous, or 0 to disable it
|
||||
* ```aopOrbMaxErr``` is used to set the 'lifetime' of the AssistNow data. It is recommended to set aopOrbMaxErr to 0 (the default value). This instructs the module to use the firmware default value that corresponds to a default orbit data validity of approximately three days (for GPS satellites observed once) and up to six days (for GPS and GLONASS satellites observed multiple times over a period of at least half a day).
|
||||
|
||||
Once AssistNow Autonomous is enabled, you can monitor its status via the ```status``` field in the UBX-NAV-AOPSTATUS message. You can read the ```status``` by calling the helper function ```getAOPSTATUSstatus```. It will return zero when the AssistNow Autonomous data collection is idle. Non-zero values indicate that data collection is in progress. Only power-off the receiver when the subsystem is idle (that is, when the status shows a steady zero).
|
||||
|
||||
* <b>uint8_t getAOPSTATUSstatus(uint16_t maxWait);</b>
|
||||
* <b>uint8_t getAOPSTATUSuseAOP(uint16_t maxWait);</b>
|
||||
|
||||
We have included full 'auto' support for UBX-NAV-AOPSTATUS, so you can have the message delivered periodically, add a callback for it, and/or log it to the file buffer:
|
||||
|
||||
* <b>bool getAOPSTATUS(uint16_t maxWait);</b>
|
||||
* <b>bool setAutoAOPSTATUS(bool enabled, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoAOPSTATUS(bool enabled, bool implicitUpdate, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoAOPSTATUSrate(uint8_t rate, bool implicitUpdate, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoAOPSTATUScallback(void (*callbackPointer)(UBX_NAV_AOPSTATUS_data_t), uint16_t maxWait);</b>
|
||||
* <b>bool assumeAutoAOPSTATUS(bool enabled, bool implicitUpdate);</b>
|
||||
* <b>void flushAOPSTATUS();</b>
|
||||
* <b>void logAOPSTATUS(bool enabled);</b>
|
||||
|
||||
You can also monitor the AssistNow Autonomous satellite information via the UBX-NAV-SAT message. Again, we have included full 'auto' support for UBX-NAV-SAT. UBX-NAV-SAT contains useful information for each individual satellite which the module has acquired: carrier to noise ratio (signal strength); elevation; azimuth; pseudorange residual; quality indication, health; ephemeris available; almanac available; **AssistNow Offline data availability**; and more. The data can be analyzed using a callback. Please see the AssistNowAutonomous examples for more details.
|
||||
|
||||
* <b>bool getNAVSAT(uint16_t maxWait);</b>
|
||||
* <b>bool setAutoNAVSAT(bool enabled, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoNAVSAT(bool enabled, bool implicitUpdate, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoNAVSATrate(uint8_t rate, bool implicitUpdate = true, uint16_t maxWait);</b>
|
||||
* <b>bool setAutoNAVSATcallback(void (*callbackPointer)(UBX_NAV_NAVSAT_data_t), uint16_t maxWait);</b>
|
||||
* <b>bool assumeAutoNAVSAT(bool enabled, bool implicitUpdate);</b>
|
||||
* <b>void flushNAVSAT();</b>
|
||||
* <b>void logNAVSAT(bool enabled);</b>
|
||||
|
||||
The AssistNow Autonomous data is stored in the module's RAM memory. If that RAM is Battery-Backed - all SparkFun GNSS boards include battery back-up - then the data will be available after the module is powered down and powered back up again. However, you can also read (poll) the navigation database and store the contents in processor memory. ```readNavigationDatabase``` allows you to do that:
|
||||
|
||||
* <b>size_t readNavigationDatabase(uint8_t *dataBytes, size_t maxNumDataBytes, uint16_t maxWait);</b>
|
||||
|
||||
Data is written to ```dataBytes```. Set ```maxNumDataBytes``` to the (maximum) size of dataBytes. If the database exceeds maxNumDataBytes, the excess bytes will be lost.
|
||||
|
||||
```readNavigationDatabase``` returns the number of database bytes written to ```dataBytes```. The return value will be equal to ```maxNumDataBytes``` if excess data was received.
|
||||
|
||||
```readNavigationDatabase``` will timeout after ```maxWait``` milliseconds - in case the final UBX-MGA-ACK was missed.
|
||||
|
||||
You can then write the database back into the module using ```pushAssistNowData```. Don't forget to call ```setUTCTimeAssistance``` _before_ ```pushAssistNowData```.
|
||||
|
||||
Note: UBX-MGA-DBD messages are only intended to be sent back to the same receiver that generated them. They are firmware-specific.
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
Get the GPGGA NMEA sentence using getLatestNMEAGPGGA
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: January 12th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
** Please note: this example will not run on Arduino Uno. See https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/README.md#memory-usage
|
||||
|
||||
This example shows how to turn on/off the NMEA sentences being output over I2C.
|
||||
It then demonstrates how to use the new getLatestNMEAGPGGA function to retrieve the latest GPGGA message.
|
||||
getLatestNMEAGPGGA returns immediately - it is not blocking.
|
||||
It returns:
|
||||
0 if no data is available
|
||||
1 if the data is valid but is stale (you have read it before)
|
||||
2 if the data is valid and fresh
|
||||
|
||||
If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP".
|
||||
The library includes a getLatestNMEAGNGGA function too.
|
||||
This example shows how to use both functions - and how to change the Talker ID so the GNGGA messages become GPGGA.
|
||||
|
||||
This example turns off all sentences except for GGA.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("SparkFun u-blox GNSS Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
//Disable or enable various NMEA sentences over the I2C interface
|
||||
myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN)
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C); // Several of these are on by default on ublox board so let's disable them
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate
|
||||
|
||||
// Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
|
||||
myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
|
||||
//myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID
|
||||
|
||||
myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages
|
||||
|
||||
//myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM
|
||||
|
||||
Serial.println(F("Messages configured"));
|
||||
|
||||
//myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// getLatestNMEAGPGGA calls checkUblox for us. We don't need to do it here
|
||||
|
||||
NMEA_GGA_data_t data; // Storage for the GPGGA data
|
||||
uint8_t result = myGNSS.getLatestNMEAGPGGA(&data); // Get the latest GPGGA data (if any)
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
Serial.println(F("No GPGGA data available"));
|
||||
}
|
||||
else if (result == 1)
|
||||
{
|
||||
Serial.println(F("GPGGA data is available but is stale"));
|
||||
}
|
||||
else // if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GPGGA: Length: "));
|
||||
Serial.print(data.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
result = myGNSS.getLatestNMEAGNGGA(&data); // Get the latest GNGGA data (if any)
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
Serial.println(F("No GNGGA data available"));
|
||||
}
|
||||
else if (result == 1)
|
||||
{
|
||||
Serial.println(F("GNGGA data is available but is stale"));
|
||||
}
|
||||
else // if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GNGGA: Length: "));
|
||||
Serial.print(data.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.println((const char *)data.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Get the latest GPGGA / GNGGA NMEA sentence using callbacks
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: January 12th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
** Please note: this example will not run on Arduino Uno. See https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/README.md#memory-usage
|
||||
|
||||
This example shows how to turn on/off the NMEA sentences being output over I2C.
|
||||
It then demonstrates how to get the latest GPGGA or GNGGA message autonomously using callbacks.
|
||||
|
||||
If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP".
|
||||
This example shows how to change the Talker ID so the GNGGA messages become GPGGA.
|
||||
It also shows how to enable "high precision mode" to include extra decimal places in the GGA messages.
|
||||
|
||||
This example turns off all sentences except for GGA.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printGPGGA will be called when new GPGGA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_GGA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPGGAcallback
|
||||
// / _____ This _must_ be NMEA_GGA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGPGGA(NMEA_GGA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGPGGA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGNGGA will be called if new GNGGA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_GGA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNGGAcallback
|
||||
// / _____ This _must_ be NMEA_GGA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGNGGA(NMEA_GGA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGNGGA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("SparkFun u-blox GNSS Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Disable or enable various NMEA sentences over the I2C interface
|
||||
myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN)
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C); // Several of these are on by default on ublox board so let's disable them
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C); // Leave only GGA enabled at current navigation rate
|
||||
|
||||
// Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
|
||||
myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
|
||||
//myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID
|
||||
|
||||
myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages
|
||||
|
||||
//myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM
|
||||
|
||||
Serial.println(F("Messages configured"));
|
||||
|
||||
//myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging
|
||||
|
||||
// Set up the callback for GPGGA
|
||||
myGNSS.setNMEAGPGGAcallbackPtr(&printGPGGA);
|
||||
|
||||
// Set up the callback for GNGGA
|
||||
myGNSS.setNMEAGNGGAcallbackPtr(&printGNGGA);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
Get the NMEA sentence using getLatestNMEAGPxxx (GGA, VTG, RMC, ZDA)
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 2nd, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
** Please note: this example will not run on Arduino Uno. See https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/README.md#memory-usage
|
||||
|
||||
This example shows how to turn on/off the NMEA sentences being output over I2C.
|
||||
It then demonstrates how to use the new getLatestNMEAGPxxx function to retrieve the latest GPGGA message.
|
||||
getLatestNMEAGPxxx returns immediately - it is not blocking.
|
||||
It returns:
|
||||
0 if no data is available
|
||||
1 if the data is valid but is stale (you have read it before)
|
||||
2 if the data is valid and fresh
|
||||
|
||||
If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP".
|
||||
The library includes getLatestNMEAGNxxx functions too.
|
||||
This example shows how to use both functions - and how to change the Talker ID so the GNGGA messages become GPGGA etc..
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("SparkFun u-blox GNSS Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
//Disable or enable various NMEA sentences over the I2C interface
|
||||
myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN)
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_ZDA, COM_PORT_I2C);
|
||||
|
||||
// Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
|
||||
myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
|
||||
//myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID
|
||||
|
||||
myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages
|
||||
|
||||
//myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM
|
||||
|
||||
Serial.println(F("Messages configured"));
|
||||
|
||||
//myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// getLatestNMEAGPGGA calls checkUblox for us. We don't need to do it here
|
||||
|
||||
NMEA_GGA_data_t dataGGA; // Storage for the GPGGA data
|
||||
uint8_t result = myGNSS.getLatestNMEAGPGGA(&dataGGA); // Get the latest GPGGA data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GPGGA: Length: "));
|
||||
Serial.print(dataGGA.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataGGA.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
result = myGNSS.getLatestNMEAGNGGA(&dataGGA); // Get the latest GNGGA data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GNGGA: Length: "));
|
||||
Serial.print(dataGGA.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataGGA.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
// getLatestNMEAGPVTG calls checkUblox for us. We don't need to do it here
|
||||
|
||||
NMEA_VTG_data_t dataVTG; // Storage for the GPVTG data
|
||||
result = myGNSS.getLatestNMEAGPVTG(&dataVTG); // Get the latest GPVTG data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GPVTG: Length: "));
|
||||
Serial.print(dataVTG.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataVTG.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
result = myGNSS.getLatestNMEAGNVTG(&dataVTG); // Get the latest GNVTG data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GNVTG: Length: "));
|
||||
Serial.print(dataVTG.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataVTG.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
// getLatestNMEAGPRMC calls checkUblox for us. We don't need to do it here
|
||||
|
||||
NMEA_RMC_data_t dataRMC; // Storage for the GPRMC data
|
||||
result = myGNSS.getLatestNMEAGPRMC(&dataRMC); // Get the latest GPRMC data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GPRMC: Length: "));
|
||||
Serial.print(dataRMC.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataRMC.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
result = myGNSS.getLatestNMEAGNRMC(&dataRMC); // Get the latest GNRMC data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GNRMC: Length: "));
|
||||
Serial.print(dataRMC.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataRMC.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
// getLatestNMEAGPZDA calls checkUblox for us. We don't need to do it here
|
||||
|
||||
NMEA_ZDA_data_t dataZDA; // Storage for the GPZDA data
|
||||
result = myGNSS.getLatestNMEAGPZDA(&dataZDA); // Get the latest GPZDA data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GPZDA: Length: "));
|
||||
Serial.print(dataZDA.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataZDA.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
result = myGNSS.getLatestNMEAGNZDA(&dataZDA); // Get the latest GNZDA data (if any)
|
||||
|
||||
if (result == 2)
|
||||
{
|
||||
// Data contains .length and .nmea
|
||||
Serial.print(F("Latest GNZDA: Length: "));
|
||||
Serial.print(dataZDA.length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)dataZDA.nmea); // .nmea is printable (NULL-terminated)
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
Get the latest GGA, VTG, RMC, ZDA NMEA sentence using callbacks
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 2nd, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
** Please note: this example will not run on Arduino Uno. See https://github.com/sparkfun/SparkFun_u-blox_GNSS_Arduino_Library/blob/main/README.md#memory-usage
|
||||
|
||||
This example shows how to turn on/off the NMEA sentences being output over I2C.
|
||||
It then demonstrates how to get the latest GGA, VTG, RMC or ZDA message autonomously using callbacks.
|
||||
|
||||
If the module is using multiple GNSS constellations, the GGA message will be prefixed with Talker ID "GN" instead of "GP".
|
||||
This example shows how to change the Talker ID so the GNGGA messages become GPGGA.
|
||||
It also shows how to enable "high precision mode" to include extra decimal places in the GGA messages.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printGPGGA will be called when new GPGGA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_GGA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPGGAcallback
|
||||
// / _____ This _must_ be NMEA_GGA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGPGGA(NMEA_GGA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGPGGA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGNGGA will be called if new GNGGA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_GGA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNGGAcallback
|
||||
// / _____ This _must_ be NMEA_GGA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGNGGA(NMEA_GGA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGNGGA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGPVTG will be called when new GPVTG NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_VTG_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPVTGcallback
|
||||
// / _____ This _must_ be NMEA_VTG_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGPVTG(NMEA_VTG_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGPVTG: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGNVTG will be called if new GNVTG NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_VTG_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNVTGcallback
|
||||
// / _____ This _must_ be NMEA_VTG_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGNVTG(NMEA_VTG_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGNVTG: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGPRMC will be called when new GPRMC NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_RMC_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPRMCcallback
|
||||
// / _____ This _must_ be NMEA_RMC_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGPRMC(NMEA_RMC_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGPRMC: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGNRMC will be called if new GNRMC NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_RMC_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNRMCcallback
|
||||
// / _____ This _must_ be NMEA_RMC_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGNRMC(NMEA_RMC_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGNRMC: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGPZDA will be called when new GPZDA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_ZDA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGPZDAcallback
|
||||
// / _____ This _must_ be NMEA_ZDA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGPZDA(NMEA_ZDA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGPZDA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
// Callback: printGNZDA will be called if new GNZDA NMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of NMEA_ZDA_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setNMEAGNZDAcallback
|
||||
// / _____ This _must_ be NMEA_ZDA_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printGNZDA(NMEA_ZDA_data_t *nmeaData)
|
||||
{
|
||||
Serial.print(F("\r\nGNZDA: Length: "));
|
||||
Serial.print(nmeaData->length);
|
||||
Serial.print(F("\tData: "));
|
||||
Serial.print((const char *)nmeaData->nmea); // .nmea is printable (NULL-terminated) and already has \r\n on the end
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("SparkFun u-blox GNSS Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Disable or enable various NMEA sentences over the I2C interface
|
||||
myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX); // Turn on both UBX and NMEA sentences on I2C. (Turn off RTCM and SPARTN)
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_VTG, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_ZDA, COM_PORT_I2C);
|
||||
|
||||
// Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA
|
||||
myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
|
||||
//myGNSS.setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_DEFAULT); // Uncomment this line to restore the default main talker ID
|
||||
|
||||
myGNSS.setHighPrecisionMode(true); // Enable High Precision Mode - include extra decimal places in the GGA messages
|
||||
|
||||
//myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM
|
||||
|
||||
Serial.println(F("Messages configured"));
|
||||
|
||||
//myGNSS.setNMEAOutputPort(Serial); // Uncomment this line to echo all NMEA data to Serial for debugging
|
||||
|
||||
// Set up the callback for GPGGA
|
||||
myGNSS.setNMEAGPGGAcallbackPtr(&printGPGGA);
|
||||
|
||||
// Set up the callback for GNGGA
|
||||
myGNSS.setNMEAGNGGAcallbackPtr(&printGNGGA);
|
||||
|
||||
// Set up the callback for GPVTG
|
||||
myGNSS.setNMEAGPVTGcallbackPtr(&printGPVTG);
|
||||
|
||||
// Set up the callback for GNVTG
|
||||
myGNSS.setNMEAGNVTGcallbackPtr(&printGNVTG);
|
||||
|
||||
// Set up the callback for GPRMC
|
||||
myGNSS.setNMEAGPRMCcallbackPtr(&printGPRMC);
|
||||
|
||||
// Set up the callback for GNRMC
|
||||
myGNSS.setNMEAGNRMCcallbackPtr(&printGNRMC);
|
||||
|
||||
// Set up the callback for GPZDA
|
||||
myGNSS.setNMEAGPZDAcallbackPtr(&printGPZDA);
|
||||
|
||||
// Set up the callback for GNZDA
|
||||
myGNSS.setNMEAGNZDAcallbackPtr(&printGNZDA);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
Callback Example: ESF RAW (100Hz!)
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: September 8th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the External Sensor Fusion RAW IMU sensor messages on the NEO-M8U / ZED-F9R and
|
||||
uses callbacks to process and display the ESF data automatically.
|
||||
|
||||
Notes:
|
||||
On the ZED-F9R, each ESF RAW message contains _one_ set of IMU sensor data: seven readings in total (3 x Accel, 3 x Gyro, 1 x Temperature).
|
||||
However, on the NEO-M8U, each message contains _ten_ sets of IMU sensor data, seventy readings in total.
|
||||
The NEO-M8U data is all timestamped and it is possible to reconstruct the full data stream, you just need to do it
|
||||
ten samples at a time...
|
||||
Also, note that the sensor data is 24-bit signed (two's complement). You need to be careful when converting to int32_t.
|
||||
Data will arrive at 100Hz! (10Hz x 10 on the NEO-M8U)
|
||||
400kHz I2C is essential...
|
||||
Serial printing needs to be kept short and the baud rate needs to be at least 230400.
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printESFRAWdata will be called when new ESF RAW data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_RAW_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFRAWcallback
|
||||
// / _____ This _must_ be UBX_ESF_RAW_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printESFRAWdata(UBX_ESF_RAW_data_t *ubxDataStruct)
|
||||
{
|
||||
// ubxDataStruct->numEsfRawBlocks indicates how many sensor readings the UBX_ESF_RAW_data_t contains.
|
||||
// On the ZED-F9R, numEsfRawBlocks will be 7: 3 x Accel, 3 x Gyro, 1 x Temperature.
|
||||
// On the NEO-M8U, numEsfRawBlocks will be 70: 10 sets of sensor data. The sensor time tag (sTag)
|
||||
// indicates the timing of each sample.
|
||||
// Serial output will be approx. 110 bytes depending on how many digits are in the sensor readings.
|
||||
// To keep up, Serial needs to be running at 100k baud minimum. 230400 is recommended.
|
||||
|
||||
uint32_t sTag = 0xFFFFFFFF; // Sensor time tag
|
||||
|
||||
// Only print the first seven sensor readings (on the NEO-M8U)
|
||||
for (uint8_t i = 0; (i < ubxDataStruct->numEsfRawBlocks) && (i < 7); i++)
|
||||
// For fun, and to prove it works, uncomment use this line instead to get the full 100Hz data on the NEO-M8U
|
||||
//for (uint8_t i = 0; i < ubxDataStruct->numEsfRawBlocks; i++)
|
||||
{
|
||||
// Print sTag the first time - and also if it changes
|
||||
if (sTag != ubxDataStruct->data[i].sTag)
|
||||
{
|
||||
sTag = ubxDataStruct->data[i].sTag;
|
||||
Serial.print(F("Time:"));
|
||||
Serial.println(sTag);
|
||||
}
|
||||
|
||||
// Print the sensor data type
|
||||
// From the M8 interface description:
|
||||
// 0: None
|
||||
// 1-4: Reserved
|
||||
// 5: z-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 6: front-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 7: front-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 8: rear-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 9: rear-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 10: speed ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 11: speed m/s * 1e-3 signed
|
||||
// 12: gyroscope temperature deg Celsius * 1e-2 signed
|
||||
// 13: y-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 14: x-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 16: x-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 17: y-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 18: z-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
switch (ubxDataStruct->data[i].data.bits.dataType)
|
||||
{
|
||||
case 5:
|
||||
Serial.print(F("Zgyr:"));
|
||||
break;
|
||||
case 12:
|
||||
Serial.print(F("Temp:"));
|
||||
break;
|
||||
case 13:
|
||||
Serial.print(F("Ygyr:"));
|
||||
break;
|
||||
case 14:
|
||||
Serial.print(F("Xgyr:"));
|
||||
break;
|
||||
case 16:
|
||||
Serial.print(F("Xacc:"));
|
||||
break;
|
||||
case 17:
|
||||
Serial.print(F("Yacc:"));
|
||||
break;
|
||||
case 18:
|
||||
Serial.print(F("Zacc:"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Gyro data
|
||||
if ((ubxDataStruct->data[i].data.bits.dataType == 5) || (ubxDataStruct->data[i].data.bits.dataType == 13) || (ubxDataStruct->data[i].data.bits.dataType == 14))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float rate = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
rate /= 256.0; // Divide by 256 to undo the shift
|
||||
rate *= 0.000244140625; // Convert from deg/s * 2^-12 to deg/s
|
||||
Serial.println(rate);
|
||||
}
|
||||
// Accelerometer data
|
||||
else if ((ubxDataStruct->data[i].data.bits.dataType == 16) || (ubxDataStruct->data[i].data.bits.dataType == 17) || (ubxDataStruct->data[i].data.bits.dataType == 18))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float force = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
force /= 256.0; // Divide by 256 to undo the shift
|
||||
force *= 0.0009765625; // Convert from m/s^2 * 2^-10 to m/s^2
|
||||
Serial.println(force);
|
||||
}
|
||||
// Gyro Temperature
|
||||
else if (ubxDataStruct->data[i].data.bits.dataType == 12)
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = ubxDataStruct->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float temperature = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
temperature /= 256.0; // Divide by 256 to undo the shift
|
||||
temperature *= 0.01; // Convert from C * 1e-2 to C
|
||||
Serial.println(temperature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(230400); // <--- Use >> 100k baud (see notes above)
|
||||
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // <-- Use 400kHz I2C (ESSENTIAL)
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setI2CpollingWait(5); //Allow checkUblox to poll I2C data every 5ms to keep up with the ESF RAW messages
|
||||
|
||||
if (myGNSS.setAutoESFRAWcallbackPtr(&printESFRAWdata) == true) // Enable automatic ESF RAW messages with callback to printESFRAWdata
|
||||
Serial.println(F("setAutoESFRAWcallback successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
}
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
u-blox Example: ESF RAW (100Hz!)
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: September 8th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the External Sensor Fusion RAW IMU sensor messages on the NEO-M8U / ZED-F9R and
|
||||
shows how to access the ESF data in the loop - without using the callback.
|
||||
|
||||
Notes:
|
||||
On the ZED-F9R, each ESF RAW message contains _one_ set of IMU sensor data: seven readings in total (3 x Accel, 3 x Gyro, 1 x Temperature).
|
||||
However, on the NEO-M8U, each message contains _ten_ sets of IMU sensor data, seventy readings in total.
|
||||
The NEO-M8U data is all timestamped and it is possible to reconstruct the full data stream, you just need to do it
|
||||
ten samples at a time...
|
||||
Also, note that the sensor data is 24-bit signed (two's complement). You need to be careful when converting to int32_t.
|
||||
Data will arrive at 100Hz! (10Hz x 10 on the NEO-M8U)
|
||||
400kHz I2C is essential...
|
||||
Serial printing needs to be kept short and the baud rate needs to be at least 230400.
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printESFRAWdata will be called when new ESF RAW data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_RAW_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFRAWcallback
|
||||
// / _____ This _must_ be UBX_ESF_RAW_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printESFRAWdata(UBX_ESF_RAW_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println(F("Hey! The ESF RAW callback has been called!"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(230400); // <--- Use >> 100k baud (see notes above)
|
||||
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // <-- Use 400kHz I2C (ESSENTIAL)
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setI2CpollingWait(5); //Allow checkUblox to poll I2C data every 5ms to keep up with the ESF RAW messages
|
||||
|
||||
if (myGNSS.setAutoESFRAWcallbackPtr(&printESFRAWdata) == true) // Enable automatic ESF RAW messages with callback to printESFRAWdata
|
||||
Serial.println(F("setAutoESFRAWcallback successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// Check if new ESF RAW data has arrived:
|
||||
// If myGNSS.packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid is true, it indicates new ESF RAW data has been received and has been copied.
|
||||
// automaticFlags.flags.bits.callbackCopyValid will be cleared automatically when the callback is called.
|
||||
|
||||
if (myGNSS.packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid == true)
|
||||
{
|
||||
// But, we can manually clear the callback flag too. This will prevent the callback from being called!
|
||||
myGNSS.packetUBXESFRAW->automaticFlags.flags.bits.callbackCopyValid = false; // Comment this line if you still want the callback to be called
|
||||
|
||||
// myGNSS.packetUBXESFRAW->callbackData->numEsfRawBlocks indicates how many sensor readings the UBX_ESF_RAW_data_t contains.
|
||||
// On the ZED-F9R, numEsfRawBlocks will be 7: 3 x Accel, 3 x Gyro, 1 x Temperature.
|
||||
// On the NEO-M8U, numEsfRawBlocks will be 70: 10 sets of sensor data. The sensor time tag (sTag)
|
||||
// indicates the timing of each sample.
|
||||
// Serial output will be approx. 110 bytes depending on how many digits are in the sensor readings.
|
||||
// To keep up, Serial needs to be running at 100k baud minimum. 230400 is recommended.
|
||||
|
||||
uint32_t sTag = 0xFFFFFFFF; // Sensor time tag
|
||||
|
||||
// Only print the first seven sensor readings (on the NEO-M8U)
|
||||
for (uint8_t i = 0; (i < myGNSS.packetUBXESFRAW->callbackData->numEsfRawBlocks) && (i < 7); i++)
|
||||
// For fun, and to prove it works, uncomment use this line instead to get the full 100Hz data on the NEO-M8U
|
||||
//for (uint8_t i = 0; i < myGNSS.packetUBXESFRAW->callbackData->numEsfRawBlocks; i++)
|
||||
{
|
||||
// Print sTag the first time - and also if it changes
|
||||
if (sTag != myGNSS.packetUBXESFRAW->callbackData->data[i].sTag)
|
||||
{
|
||||
sTag = myGNSS.packetUBXESFRAW->callbackData->data[i].sTag;
|
||||
Serial.print(F("Time:"));
|
||||
Serial.println(sTag);
|
||||
}
|
||||
|
||||
// Print the sensor data type
|
||||
// From the M8 interface description:
|
||||
// 0: None
|
||||
// 1-4: Reserved
|
||||
// 5: z-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 6: front-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 7: front-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 8: rear-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 9: rear-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 10: speed ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 11: speed m/s * 1e-3 signed
|
||||
// 12: gyroscope temperature deg Celsius * 1e-2 signed
|
||||
// 13: y-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 14: x-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 16: x-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 17: y-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 18: z-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
switch (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType)
|
||||
{
|
||||
case 5:
|
||||
Serial.print(F("Zgyr:"));
|
||||
break;
|
||||
case 12:
|
||||
Serial.print(F("Temp:"));
|
||||
break;
|
||||
case 13:
|
||||
Serial.print(F("Ygyr:"));
|
||||
break;
|
||||
case 14:
|
||||
Serial.print(F("Xgyr:"));
|
||||
break;
|
||||
case 16:
|
||||
Serial.print(F("Xacc:"));
|
||||
break;
|
||||
case 17:
|
||||
Serial.print(F("Yacc:"));
|
||||
break;
|
||||
case 18:
|
||||
Serial.print(F("Zacc:"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Gyro data
|
||||
if ((myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 5) || (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 13) || (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 14))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float rate = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
rate /= 256.0; // Divide by 256 to undo the shift
|
||||
rate *= 0.000244140625; // Convert from deg/s * 2^-12 to deg/s
|
||||
Serial.println(rate);
|
||||
}
|
||||
// Accelerometer data
|
||||
else if ((myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 16) || (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 17) || (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 18))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float force = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
force /= 256.0; // Divide by 256 to undo the shift
|
||||
force *= 0.0009765625; // Convert from m/s^2 * 2^-10 to m/s^2
|
||||
Serial.println(force);
|
||||
}
|
||||
// Gyro Temperature
|
||||
else if (myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataType == 12)
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFRAW->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float temperature = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
temperature /= 256.0; // Divide by 256 to undo the shift
|
||||
temperature *= 0.01; // Convert from C * 1e-2 to C
|
||||
Serial.println(temperature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. There will not be any in this example, unless you commented the line above
|
||||
}
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
u-blox Example: ESF MEAS (Wheel Ticks)
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: September 8th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the External Sensor Fusion MEAS sensor messages on the NEO-M8U / ZED-F9R and
|
||||
shows how to access the ESF data in the loop - without using the callback.
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printESFMEASdata will be called when new ESF MEAS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_MEAS_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFMEAScallback
|
||||
// / _____ This _must_ be UBX_ESF_MEAS_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printESFMEASdata(UBX_ESF_MEAS_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println(F("Hey! The ESF MEAS callback has been called!"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(230400); // <-- Use a fast baud rate to avoid the Serial prints slowing the code
|
||||
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // <-- Use 400kHz I2C
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
if (myGNSS.setAutoESFMEAScallbackPtr(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata
|
||||
Serial.println(F("setAutoESFMEAScallback successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// Check if new ESF MEAS data has arrived:
|
||||
// If myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid is true, it indicates new ESF MEAS data has been received and has been copied.
|
||||
// automaticFlags.flags.bits.callbackCopyValid will be cleared automatically when the callback is called.
|
||||
|
||||
if (myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid == true)
|
||||
{
|
||||
// But, we can manually clear the callback flag too. This will prevent the callback from being called!
|
||||
myGNSS.packetUBXESFMEAS->automaticFlags.flags.bits.callbackCopyValid = false; // Comment this line if you still want the callback to be called
|
||||
|
||||
// Print the timeTag
|
||||
Serial.print(F("Time: "));
|
||||
Serial.println(myGNSS.packetUBXESFMEAS->callbackData->timeTag);
|
||||
|
||||
// myGNSS.packetUBXESFMEAS->callbackData->flags.bits.numMeas indicates how many sensor groups the UBX_ESF_MEAS_data_t contains.
|
||||
for (uint8_t i = 0; i < myGNSS.packetUBXESFMEAS->callbackData->flags.bits.numMeas; i++)
|
||||
{
|
||||
// Print the sensor data type
|
||||
// From the M8 interface description:
|
||||
// 0: None
|
||||
// 1-4: Reserved
|
||||
// 5: z-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 6: front-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 7: front-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 8: rear-left wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 9: rear-right wheel ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 10: speed ticks: Bits 0-22: unsigned tick value. Bit 23: direction indicator (0=forward, 1=backward)
|
||||
// 11: speed m/s * 1e-3 signed
|
||||
// 12: gyroscope temperature deg Celsius * 1e-2 signed
|
||||
// 13: y-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 14: x-axis gyroscope angular rate deg/s * 2^-12 signed
|
||||
// 16: x-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 17: y-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
// 18: z-axis accelerometer specific force m/s^2 * 2^-10 signed
|
||||
switch (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType)
|
||||
{
|
||||
case 5:
|
||||
Serial.print(F("Z Gyro: "));
|
||||
break;
|
||||
case 6:
|
||||
Serial.print(F("Front Left: "));
|
||||
break;
|
||||
case 7:
|
||||
Serial.print(F("Front Right: "));
|
||||
break;
|
||||
case 8:
|
||||
Serial.print(F("Rear Left: "));
|
||||
break;
|
||||
case 9:
|
||||
Serial.print(F("Rear Right: "));
|
||||
break;
|
||||
case 10:
|
||||
Serial.print(F("Speed Ticks: "));
|
||||
break;
|
||||
case 11:
|
||||
Serial.print(F("Speed: "));
|
||||
break;
|
||||
case 12:
|
||||
Serial.print(F("Temp: "));
|
||||
break;
|
||||
case 13:
|
||||
Serial.print(F("Y Gyro: "));
|
||||
break;
|
||||
case 14:
|
||||
Serial.print(F("X Gyro: "));
|
||||
break;
|
||||
case 16:
|
||||
Serial.print(F("X Accel: "));
|
||||
break;
|
||||
case 17:
|
||||
Serial.print(F("Y Accel: "));
|
||||
break;
|
||||
case 18:
|
||||
Serial.print(F("Z Accel: "));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Tick data
|
||||
if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType >= 6) && (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType <= 10))
|
||||
{
|
||||
if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField & (1 << 23)) > 0)
|
||||
Serial.print(F("-")); // Backward
|
||||
else
|
||||
Serial.print(F("+")); // Forward
|
||||
Serial.println(myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField & 0x007FFFFF);
|
||||
}
|
||||
// Speed
|
||||
else if (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 11)
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float speed = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
speed /= 256.0; // Divide by 256 to undo the shift
|
||||
speed *= 0.001; // Convert from m/s * 1e-3 to m/s
|
||||
Serial.println(speed, 3);
|
||||
}
|
||||
// Gyro data
|
||||
else if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 5) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 13) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 14))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float rate = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
rate /= 256.0; // Divide by 256 to undo the shift
|
||||
rate *= 0.000244140625; // Convert from deg/s * 2^-12 to deg/s
|
||||
Serial.println(rate);
|
||||
}
|
||||
// Accelerometer data
|
||||
else if ((myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 16) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 17) || (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 18))
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float force = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
force /= 256.0; // Divide by 256 to undo the shift
|
||||
force *= 0.0009765625; // Convert from m/s^2 * 2^-10 to m/s^2
|
||||
Serial.println(force);
|
||||
}
|
||||
// Gyro Temperature
|
||||
else if (myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataType == 12)
|
||||
{
|
||||
union
|
||||
{
|
||||
int32_t signed32;
|
||||
uint32_t unsigned32;
|
||||
} signedUnsigned; // Avoid any ambiguity casting uint32_t to int32_t
|
||||
// The dataField is 24-bit signed, stored in the 24 LSBs of a uint32_t
|
||||
signedUnsigned.unsigned32 = myGNSS.packetUBXESFMEAS->callbackData->data[i].data.bits.dataField << 8; // Shift left by 8 bits to correctly align the data
|
||||
float temperature = signedUnsigned.signed32; // Extract the signed data. Convert to float
|
||||
temperature /= 256.0; // Divide by 256 to undo the shift
|
||||
temperature *= 0.01; // Convert from C * 1e-2 to C
|
||||
Serial.println(temperature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. There will not be any in this example, unless you commented the line above
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over I2C and display them using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December 30th, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send navigation reports automatically
|
||||
and access the data via a callback. No more polling!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printPVTdata will be called when new NAV PVT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback
|
||||
// / _____ This _must_ be UBX_NAV_PVT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Time: ")); // Print the time
|
||||
uint8_t hms = ubxDataStruct->hour; // Print the hours
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = ubxDataStruct->min; // Print the minutes
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = ubxDataStruct->sec; // Print the seconds
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F("."));
|
||||
unsigned long millisecs = ubxDataStruct->iTOW % 1000; // Print the milliseconds
|
||||
if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly
|
||||
if (millisecs < 10) Serial.print(F("0"));
|
||||
Serial.print(millisecs);
|
||||
|
||||
long latitude = ubxDataStruct->lat; // Print the latitude
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = ubxDataStruct->lon; // Print the longitude
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level
|
||||
Serial.print(F(" Height above MSL: "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(" (mm)"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
|
||||
myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send odometer reports over I2C and display the data using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 20th, 2023
|
||||
License: MIT. See license file for more information.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send odometer reports automatically
|
||||
and display the data via a callback. No more polling!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printODOdata will be called when new NAV ODO data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_ODO_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVODOcallback
|
||||
// / _____ This _must_ be UBX_NAV_ODO_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printODOdata(UBX_NAV_ODO_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("TOW: ")); // Print the Time Of Week
|
||||
unsigned long iTOW = ubxDataStruct->iTOW; // iTOW is in milliseconds
|
||||
Serial.print(iTOW);
|
||||
Serial.print(F(" (ms)"));
|
||||
|
||||
Serial.print(F(" Distance: "));
|
||||
unsigned long distance = ubxDataStruct->distance; // Print the distance
|
||||
Serial.print(distance);
|
||||
Serial.print(F(" (m)"));
|
||||
|
||||
Serial.print(F(" Total Distance: "));
|
||||
unsigned long totalDistance = ubxDataStruct->totalDistance; // Print the total distance
|
||||
Serial.print(totalDistance);
|
||||
Serial.println(F(" (m)"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
while (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring."));
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
|
||||
//By default, the odometer is disabled. We need to enable it.
|
||||
//We can enable it using the default settings:
|
||||
myGNSS.enableOdometer();
|
||||
|
||||
//Or we can configure it using our own settings, by performing a read-modify-write:
|
||||
uint8_t flags; // Odometer/Low-speed COG filter flags
|
||||
uint8_t odoCfg; // Odometer filter settings
|
||||
uint8_t cogMaxSpeed; // Speed below which course-over-ground (COG) is computed with the low-speed COG filter : m/s * 0.1
|
||||
uint8_t cogMaxPosAcc; // Maximum acceptable position accuracy for computing COG with the low-speed COG filter
|
||||
uint8_t velLpGain; // Velocity low-pass filter level
|
||||
uint8_t cogLpGain; // COG low-pass filter level
|
||||
|
||||
if (myGNSS.getOdometerConfig(&flags, &odoCfg, &cogMaxSpeed, &cogMaxPosAcc, &velLpGain, &cogLpGain))
|
||||
{
|
||||
flags = UBX_CFG_ODO_USE_ODO; // Enable the odometer
|
||||
odoCfg = UBX_CFG_ODO_CAR; // Use the car profile (others are RUN, CYCLE, SWIM, CUSTOM)
|
||||
myGNSS.setOdometerConfig(flags, odoCfg, cogMaxSpeed, cogMaxPosAcc, velLpGain, cogLpGain); // Set the configuration
|
||||
}
|
||||
else
|
||||
Serial.println("Could not read odometer config!");
|
||||
|
||||
//myGNSS.resetOdometer(); //Uncomment this line to reset the odometer
|
||||
|
||||
myGNSS.setAutoNAVODOcallbackPtr(&printODOdata); // Enable automatic NAV ODO messages with callback to printODOdata
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send TIM TM2 reports over I2C and display the data using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December 30th, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send TIM TM2 reports automatically
|
||||
and display the data via a callback. No more polling!
|
||||
|
||||
Connecting the PPS (Pulse Per Second) breakout pin to the INT (Interrupt) pin with a jumper wire
|
||||
will cause a TIM TM2 message to be produced once per second. You can then study the timing of the
|
||||
pulse edges with nanosecond resolution!
|
||||
|
||||
Note: TIM TM2 can only capture the timing of one rising edge and one falling edge per
|
||||
navigation solution. So with setNavigationFrequency set to 1Hz, we can only see the timing
|
||||
of one rising and one falling edge per second. If the frequency of the signal on the INT pin
|
||||
is higher than 1Hz, we will only be able to see the timing of the most recent edges.
|
||||
However, the module can count the number of rising edges too, at rates faster than the navigation rate.
|
||||
|
||||
TIM TM2 messages are only produced when a rising or falling edge is detected on the INT pin.
|
||||
If you disconnect your PPS to INT jumper wire, the messages will stop.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
NEO-M9N: https://www.sparkfun.com/products/17285
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
int dotsPrinted = 0; // Print dots in rows of 50 while waiting for a TIM TM2 message
|
||||
|
||||
// Callback: printTIMTM2data will be called when new TIM TM2 data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_TIM_TM2_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoTIMTM2callback
|
||||
// / _____ This _must_ be UBX_TIM_TM2_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printTIMTM2data(UBX_TIM_TM2_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("newFallingEdge: ")); // 1 if a new falling edge was detected
|
||||
Serial.print(ubxDataStruct->flags.bits.newFallingEdge);
|
||||
|
||||
Serial.print(F(" newRisingEdge: ")); // 1 if a new rising edge was detected
|
||||
Serial.print(ubxDataStruct->flags.bits.newRisingEdge);
|
||||
|
||||
Serial.print(F(" Rising Edge Counter: ")); // Rising edge counter
|
||||
Serial.print(ubxDataStruct->count);
|
||||
|
||||
Serial.print(F(" towMsR: ")); // Time Of Week of rising edge (ms)
|
||||
Serial.print(ubxDataStruct->towMsR);
|
||||
|
||||
Serial.print(F(" towSubMsR: ")); // Millisecond fraction of Time Of Week of rising edge in nanoseconds
|
||||
Serial.print(ubxDataStruct->towSubMsR);
|
||||
|
||||
Serial.print(F(" towMsF: ")); // Time Of Week of falling edge (ms)
|
||||
Serial.print(ubxDataStruct->towMsF);
|
||||
|
||||
Serial.print(F(" towSubMsF: ")); // Millisecond fraction of Time Of Week of falling edge in nanoseconds
|
||||
Serial.println(ubxDataStruct->towSubMsF);
|
||||
|
||||
dotsPrinted = 0; // Reset dotsPrinted
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
|
||||
myGNSS.setAutoTIMTM2callbackPtr(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
if (++dotsPrinted > 50)
|
||||
{
|
||||
Serial.println();
|
||||
dotsPrinted = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the High Navigation Rate on the NEO-M8U and then
|
||||
reads and displays the attitude solution, vehicle dynamics information
|
||||
and high rate position, velocity and time.
|
||||
|
||||
This example uses callbacks to process the HNR data automatically. No more polling!
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printHNRATTdata will be called when new HNR ATT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_HNR_ATT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoHNRATTcallback
|
||||
// / _____ This _must_ be UBX_HNR_ATT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printHNRATTdata(UBX_HNR_ATT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
Serial.print(F("Roll: ")); // Print selected data
|
||||
Serial.print((float)ubxDataStruct->roll / 100000.0, 2); // Convert roll to degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print((float)ubxDataStruct->pitch / 100000.0, 2); // Convert pitch to degrees
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.println((float)ubxDataStruct->heading / 100000.0, 2); // Convert heading to degrees
|
||||
}
|
||||
|
||||
// Callback: printHNRINSdata will be called when new HNR INS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_HNR_INS_data_t
|
||||
void printHNRINSdata(UBX_HNR_INS_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.print(F("xAccel: ")); // Print selected data
|
||||
Serial.print(ubxDataStruct->xAccel);
|
||||
Serial.print(F(" yAccel: "));
|
||||
Serial.print(ubxDataStruct->yAccel);
|
||||
Serial.print(F(" zAccel: "));
|
||||
Serial.println(ubxDataStruct->zAccel);
|
||||
}
|
||||
|
||||
// Callback: printHNRPVTdata will be called when new HNR PVT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_HNR_PVT_data_t
|
||||
void printHNRPVTdata(UBX_HNR_PVT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.print(F("ns: ")); // Print selected data
|
||||
Serial.print(ubxDataStruct->nano);
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(ubxDataStruct->lat);
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.println(ubxDataStruct->lon);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
if (myGNSS.setHNRNavigationRate(10) == true) //Set the High Navigation Rate to 10Hz
|
||||
Serial.println(F("setHNRNavigationRate was successful"));
|
||||
else
|
||||
Serial.println(F("setHNRNavigationRate was NOT successful"));
|
||||
|
||||
if (myGNSS.setAutoHNRATTcallbackPtr(&printHNRATTdata) == true) // Enable automatic HNR ATT messages with callback to printHNRATTdata
|
||||
Serial.println(F("setAutoHNRATTcallback successful"));
|
||||
|
||||
if (myGNSS.setAutoHNRINScallbackPtr(&printHNRINSdata) == true) // Enable automatic HNR INS messages with callback to printHNRINSdata
|
||||
Serial.println(F("setAutoHNRINScallback successful"));
|
||||
|
||||
if (myGNSS.setAutoHNRPVTcallbackPtr(&printHNRPVTdata) == true) // Enable automatic HNR PVT messages with callback to printHNRPVTdata
|
||||
Serial.println(F("setAutoHNRPVTcallback successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(25);
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the External Sensor Fusion messages on the NEO-M8U and
|
||||
uses callbacks to process and display the ESF data automatically. No more polling!
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: printESFALGdata will be called when new ESF ALG data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_ALG_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoESFALGcallback
|
||||
// / _____ This _must_ be UBX_ESF_ALG_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printESFALGdata(UBX_ESF_ALG_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("TOW: ")); // Print the Time Of Week
|
||||
unsigned long iTOW = ubxDataStruct->iTOW; // iTOW is in milliseconds
|
||||
Serial.print(iTOW);
|
||||
Serial.print(F(" (ms)"));
|
||||
|
||||
Serial.print(F(" Roll: ")); // Print selected data
|
||||
Serial.print((float)ubxDataStruct->roll / 100.0, 2); // Convert roll to degrees
|
||||
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print((float)ubxDataStruct->pitch / 100.0, 2); // Convert pitch to degrees
|
||||
|
||||
Serial.print(F(" Yaw: "));
|
||||
Serial.print((float)ubxDataStruct->yaw / 100.0, 2); // Convert yaw to degrees
|
||||
|
||||
Serial.println(F(" (Degrees)"));
|
||||
}
|
||||
|
||||
// Callback: printESFINSdata will be called when new ESF INS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_INS_data_t
|
||||
void printESFINSdata(UBX_ESF_INS_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.print(F("xAccel: ")); // Print selected data
|
||||
Serial.print(ubxDataStruct->xAccel);
|
||||
|
||||
Serial.print(F(" yAccel: "));
|
||||
Serial.print(ubxDataStruct->yAccel);
|
||||
|
||||
Serial.print(F(" zAccel: "));
|
||||
Serial.print(ubxDataStruct->zAccel);
|
||||
|
||||
Serial.println(F(" (m/s^2)"));
|
||||
}
|
||||
|
||||
// Callback: printESFMEASdata will be called when new ESF MEAS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_MEAS_data_t
|
||||
// and UBX_ESF_MEAS_sensorData_t
|
||||
void printESFMEASdata(UBX_ESF_MEAS_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("id: ")); // Print selected data
|
||||
Serial.print(ubxDataStruct->id);
|
||||
|
||||
Serial.print(F(" numMeas: "));
|
||||
Serial.println(ubxDataStruct->flags.bits.numMeas);
|
||||
|
||||
for (uint8_t num = 0; num < ubxDataStruct->flags.bits.numMeas; num++) // For each sensor
|
||||
{
|
||||
Serial.print(F("Sensor "));
|
||||
Serial.print(num);
|
||||
|
||||
UBX_ESF_MEAS_sensorData_t sensorData;
|
||||
myGNSS.getSensorFusionMeasurement(&sensorData, *ubxDataStruct, num); // Extract the data for one sensor
|
||||
|
||||
Serial.print(F(": Type: "));
|
||||
Serial.print(sensorData.data.bits.dataType);
|
||||
Serial.print(F(" Data: "));
|
||||
Serial.println(sensorData.data.bits.dataField);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback: printESFSTATUSdata will be called when new ESF STATUS data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_ESF_STATUS_data_t
|
||||
// and UBX_ESF_STATUS_sensorStatus_t
|
||||
void printESFSTATUSdata(UBX_ESF_STATUS_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.print(F("fusionMode: ")); // Print selected data
|
||||
Serial.print(ubxDataStruct->fusionMode);
|
||||
|
||||
Serial.print(F(" numSens: "));
|
||||
Serial.println(ubxDataStruct->numSens);
|
||||
|
||||
for (uint8_t num = 0; num < ubxDataStruct->numSens; num++) // For each sensor
|
||||
{
|
||||
Serial.print(F("Sensor "));
|
||||
Serial.print(num);
|
||||
|
||||
UBX_ESF_STATUS_sensorStatus_t sensorStatus;
|
||||
myGNSS.getSensorFusionStatus(&sensorStatus, *ubxDataStruct, num); // Extract the data for one sensor
|
||||
|
||||
Serial.print(F(": Type: "));
|
||||
Serial.print(sensorStatus.sensStatus1.bits.type);
|
||||
Serial.print(F(" Used: "));
|
||||
Serial.print(sensorStatus.sensStatus1.bits.used);
|
||||
Serial.print(F(" Ready: "));
|
||||
Serial.print(sensorStatus.sensStatus1.bits.ready);
|
||||
Serial.print(F(" Calib Status: "));
|
||||
Serial.print(sensorStatus.sensStatus2.bits.calibStatus);
|
||||
Serial.print(F(" Noisy: "));
|
||||
Serial.println(sensorStatus.faults.bits.noisyMeas);
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
myGNSS.setHNRNavigationRate(1); //Set the High Navigation Rate to 1Hz
|
||||
|
||||
myGNSS.setI2CpollingWait(50); //Allow checkUblox to poll I2C data every 50ms to keep up with the ESF MEAS messages
|
||||
|
||||
if (myGNSS.setAutoESFALGcallbackPtr(&printESFALGdata) == true) // Enable automatic ESF ALG messages with callback to printESFALGdata
|
||||
Serial.println(F("setAutoESFALGcallback successful"));
|
||||
|
||||
if (myGNSS.setAutoESFINScallbackPtr(&printESFINSdata) == true) // Enable automatic ESF INS messages with callback to printESFINSdata
|
||||
Serial.println(F("setAutoESFINScallback successful"));
|
||||
|
||||
if (myGNSS.setAutoESFMEAScallbackPtr(&printESFMEASdata) == true) // Enable automatic ESF MEAS messages with callback to printESFMEASdata
|
||||
Serial.println(F("setAutoESFMEAScallback successful"));
|
||||
|
||||
if (myGNSS.setAutoESFSTATUScallbackPtr(&printESFSTATUSdata) == true) // Enable automatic ESF STATUS messages with callback to printESFSTATUSdata
|
||||
Serial.println(F("setAutoESFSTATUScallback successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(25);
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send RXM RZWX reports over I2C and display them using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 11th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send RXM RAWX reports automatically
|
||||
and access the data via a callback. No more polling!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: newRAWX will be called when new RXM RAWX data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback
|
||||
// / _____ This _must_ be UBX_RXM_RAWX_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("New RAWX data received. It contains "));
|
||||
Serial.print(ubxDataStruct->header.numMeas); // Print numMeas (Number of measurements / blocks)
|
||||
Serial.println(F(" data blocks:"));
|
||||
|
||||
for (uint8_t block = 0; block < ubxDataStruct->header.numMeas; block++) // For each block
|
||||
{
|
||||
Serial.print(F("GNSS ID: "));
|
||||
if (ubxDataStruct->blocks[block].gnssId < 100) Serial.print(F(" ")); // Align the gnssId
|
||||
if (ubxDataStruct->blocks[block].gnssId < 10) Serial.print(F(" ")); // Align the gnssId
|
||||
Serial.print(ubxDataStruct->blocks[block].gnssId);
|
||||
Serial.print(F(" SV ID: "));
|
||||
if (ubxDataStruct->blocks[block].svId < 100) Serial.print(F(" ")); // Align the svId
|
||||
if (ubxDataStruct->blocks[block].svId < 10) Serial.print(F(" ")); // Align the svId
|
||||
Serial.print(ubxDataStruct->blocks[block].svId);
|
||||
|
||||
if (sizeof(double) == 8) // Check if our processor supports 64-bit double
|
||||
{
|
||||
// Convert prMes from uint8_t[8] to 64-bit double
|
||||
// prMes is little-endian
|
||||
double pseudorange;
|
||||
memcpy(&pseudorange, &ubxDataStruct->blocks[block].prMes, 8);
|
||||
Serial.print(F(" PR: "));
|
||||
Serial.print(pseudorange, 3);
|
||||
|
||||
// Convert cpMes from uint8_t[8] to 64-bit double
|
||||
// cpMes is little-endian
|
||||
double carrierPhase;
|
||||
memcpy(&carrierPhase, &ubxDataStruct->blocks[block].cpMes, 8);
|
||||
Serial.print(F(" m CP: "));
|
||||
Serial.print(carrierPhase, 3);
|
||||
Serial.print(F(" cycles"));
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
myGNSS.disableUBX7Fcheck(); // RAWX data can legitimately contain 0x7F, so we need to disable the "7F" check in checkUbloxI2C
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second (RAWX produces a _lot_ of data!)
|
||||
|
||||
myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send NAV SAT reports over I2C and display them using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December 1st, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send NAV SAT reports automatically
|
||||
and access the data via a callback. No more polling!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: newNAVSAT will be called when new NAV SAT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_SAT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSATcallback
|
||||
// / _____ This _must_ be UBX_NAV_SAT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newNAVSAT(UBX_NAV_SAT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("New NAV SAT data received. It contains data for "));
|
||||
Serial.print(ubxDataStruct->header.numSvs);
|
||||
if (ubxDataStruct->header.numSvs == 1)
|
||||
Serial.println(F(" SV."));
|
||||
else
|
||||
Serial.println(F(" SVs."));
|
||||
|
||||
// Just for giggles, print the signal strength for each SV as a barchart
|
||||
for (uint16_t block = 0; block < ubxDataStruct->header.numSvs; block++) // For each SV
|
||||
{
|
||||
switch (ubxDataStruct->blocks[block].gnssId) // Print the GNSS ID
|
||||
{
|
||||
case 0:
|
||||
Serial.print(F("GPS "));
|
||||
break;
|
||||
case 1:
|
||||
Serial.print(F("SBAS "));
|
||||
break;
|
||||
case 2:
|
||||
Serial.print(F("Galileo "));
|
||||
break;
|
||||
case 3:
|
||||
Serial.print(F("BeiDou "));
|
||||
break;
|
||||
case 4:
|
||||
Serial.print(F("IMES "));
|
||||
break;
|
||||
case 5:
|
||||
Serial.print(F("QZSS "));
|
||||
break;
|
||||
case 6:
|
||||
Serial.print(F("GLONASS "));
|
||||
break;
|
||||
default:
|
||||
Serial.print(F("UNKNOWN "));
|
||||
break;
|
||||
}
|
||||
|
||||
Serial.print(ubxDataStruct->blocks[block].svId); // Print the SV ID
|
||||
|
||||
if (ubxDataStruct->blocks[block].svId < 10) Serial.print(F(" "));
|
||||
else if (ubxDataStruct->blocks[block].svId < 100) Serial.print(F(" "));
|
||||
else Serial.print(F(" "));
|
||||
|
||||
// Print the signal strength as a bar chart
|
||||
for (uint8_t cno = 0; cno < ubxDataStruct->blocks[block].cno; cno++)
|
||||
Serial.print(F("="));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one solution per second
|
||||
|
||||
myGNSS.setAutoNAVSATcallbackPtr(&newNAVSAT); // Enable automatic NAV SAT messages with callback to newNAVSAT
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send NAV SVIN reports over I2C and display them using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: April 4th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send NAV SVIN reports automatically
|
||||
and access the data via a callback. No more polling!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: newNAVSVIN will be called when new NAV SVIN data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_SVIN_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoNAVSVINcallbackPtr
|
||||
// / _____ This _must_ be UBX_NAV_SVIN_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newNAVSVIN(UBX_NAV_SVIN_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Survey-in is "));
|
||||
if (ubxDataStruct->active == 0)
|
||||
Serial.print(F("not "));
|
||||
Serial.println(F("in progress"));
|
||||
|
||||
Serial.print(F("Survey-in position is "));
|
||||
if (ubxDataStruct->valid == 0)
|
||||
Serial.print(F("not "));
|
||||
Serial.println(F("valid"));
|
||||
|
||||
Serial.print(F("Survey-in observation time (s): "));
|
||||
Serial.println(ubxDataStruct->dur);
|
||||
|
||||
Serial.print(F("ECEF position (cm): "));
|
||||
Serial.print(ubxDataStruct->meanX);
|
||||
Serial.print(F(" ("));
|
||||
if (ubxDataStruct->meanXHP >= 0)
|
||||
Serial.print(F("+"));
|
||||
Serial.print((float)ubxDataStruct->meanXHP * 0.01); // Convert 0.1mm to cm
|
||||
Serial.print(F("), "));
|
||||
Serial.print(ubxDataStruct->meanY);
|
||||
Serial.print(F(" ("));
|
||||
if (ubxDataStruct->meanYHP >= 0)
|
||||
Serial.print(F("+"));
|
||||
Serial.print((float)ubxDataStruct->meanYHP * 0.01); // Convert 0.1mm to cm
|
||||
Serial.print(F("), "));
|
||||
Serial.print(ubxDataStruct->meanZ);
|
||||
Serial.print(F(" ("));
|
||||
if (ubxDataStruct->meanZHP >= 0)
|
||||
Serial.print(F("+"));
|
||||
Serial.print((float)ubxDataStruct->meanZHP * 0.01); // Convert 0.1mm to cm
|
||||
Serial.println(F(")"));
|
||||
|
||||
Serial.print(F("Mean position accuracy (cm): "));
|
||||
Serial.println((float)ubxDataStruct->meanAcc * 0.01); // Convert 0.1mm to cm
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox Base Station example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save the communications port settings to flash and BBR
|
||||
|
||||
// Set up the callback for NAV SVIN. This will enable SVIN messages at the navigation rate
|
||||
myGNSS.setAutoNAVSVINcallbackPtr(&newNAVSVIN);
|
||||
|
||||
while (Serial.available()) Serial.read(); //Clear the serial buffer
|
||||
Serial.println(F("Press any key to begin Survey-In"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
myGNSS.checkCallbacks(); //Process any waiting callbacks
|
||||
|
||||
if (Serial.available()) // Check if user has pressed a key
|
||||
{
|
||||
bool success = myGNSS.enableSurveyMode(60, 5.000); //Enable Survey in, 60 seconds, 5.0m
|
||||
//bool success = myGNSS.enableSurveyModeFull(86400, 2.000); //Enable Survey in, 24 hours, 2.0m
|
||||
|
||||
Serial.println();
|
||||
|
||||
if (success)
|
||||
{
|
||||
Serial.println(F("Survey-In started!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Survey start failed!"));
|
||||
}
|
||||
|
||||
while (Serial.available()) Serial.read(); //Clear the serial buffer
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over I2C and display them using a callback
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: April 15th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to access the callback data from the main loop.
|
||||
The simple way to check if new data is available is to use a global flag: set it in the callback, check it and clear it in the main loop.
|
||||
Or, you can be more sophisticated and use the callback flags themselves.
|
||||
This example shows how to use the sophisticated method.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// Callback: callbackPVT will be called when new NAV PVT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallbackPtr
|
||||
// / _____ This _must_ be UBX_NAV_PVT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void callbackPVT(UBX_NAV_PVT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println(F("Hey! The NAV PVT callback has been called!"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
|
||||
myGNSS.setAutoPVTcallbackPtr(&callbackPVT); // Enable automatic NAV PVT messages with callback to callbackPVT
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// Check if new NAV PVT data has been received:
|
||||
// If myGNSS.packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid is true, it indicates new PVT data has been received and has been copied.
|
||||
// automaticFlags.flags.bits.callbackCopyValid will be cleared automatically when the callback is called.
|
||||
|
||||
if (myGNSS.packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid == true)
|
||||
{
|
||||
// But, we can manually clear the callback flag too. This will prevent the callback from being called!
|
||||
myGNSS.packetUBXNAVPVT->automaticFlags.flags.bits.callbackCopyValid = false; // Comment this line if you still want the callback to be called
|
||||
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Time: ")); // Print the time
|
||||
uint8_t hms = myGNSS.packetUBXNAVPVT->callbackData->hour; // Print the hours
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = myGNSS.packetUBXNAVPVT->callbackData->min; // Print the minutes
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = myGNSS.packetUBXNAVPVT->callbackData->sec; // Print the seconds
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F("."));
|
||||
unsigned long millisecs = myGNSS.packetUBXNAVPVT->callbackData->iTOW % 1000; // Print the milliseconds
|
||||
if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly
|
||||
if (millisecs < 10) Serial.print(F("0"));
|
||||
Serial.print(millisecs);
|
||||
|
||||
long latitude = myGNSS.packetUBXNAVPVT->callbackData->lat; // Print the latitude
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.packetUBXNAVPVT->callbackData->lon; // Print the longitude
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.packetUBXNAVPVT->callbackData->hMSL; // Print the height above mean sea level
|
||||
Serial.print(F(" Height above MSL: "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(" (mm)"));
|
||||
}
|
||||
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed. There will not be any in this example, unless you commented the line above
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send NAV PVT reports over I2C and log them to file on SD card
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send NAV PVT reports automatically
|
||||
and log the data to SD card in UBX format.
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Data is logged in u-blox UBX format. Please see the u-blox protocol specification for more details.
|
||||
You can replay and analyze the data using u-center:
|
||||
https://www.u-blox.com/en/product/u-center
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define packetLength 100 // NAV PVT is 92 + 8 bytes in length (including the sync chars, class, id, length and checksum bytes)
|
||||
uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card
|
||||
|
||||
// Callback: printPVTdata will be called when new NAV PVT data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_NAV_PVT_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoPVTcallback
|
||||
// / _____ This _must_ be UBX_NAV_PVT_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("Time: ")); // Print the time
|
||||
uint8_t hms = ubxDataStruct->hour; // Print the hours
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = ubxDataStruct->min; // Print the minutes
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F(":"));
|
||||
hms = ubxDataStruct->sec; // Print the seconds
|
||||
if (hms < 10) Serial.print(F("0")); // Print a leading zero if required
|
||||
Serial.print(hms);
|
||||
Serial.print(F("."));
|
||||
unsigned long millisecs = ubxDataStruct->iTOW % 1000; // Print the milliseconds
|
||||
if (millisecs < 100) Serial.print(F("0")); // Print the trailing zeros correctly
|
||||
if (millisecs < 10) Serial.print(F("0"));
|
||||
Serial.print(millisecs);
|
||||
|
||||
long latitude = ubxDataStruct->lat; // Print the latitude
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = ubxDataStruct->lon; // Print the longitude
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level
|
||||
Serial.print(F(" Height above MSL: "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(" (mm)"));
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin(); // Start I2C communication with the GNSS
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "NAV_PVT.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("NAV_PVT.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful GNSS debug messages on Serial
|
||||
|
||||
// NAV PVT messages are 100 bytes long.
|
||||
// In this example, the data will arrive no faster than one message per second.
|
||||
// So, setting the file buffer size to 301 bytes should be more than adequate.
|
||||
// I.e. room for three messages plus an empty tail byte.
|
||||
myGNSS.setFileBufferSize(301); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// (This will also disable any "auto" messages that were enabled and saved by other examples and reduce the load on the I2C bus)
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second
|
||||
|
||||
myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata
|
||||
|
||||
myGNSS.logNAVPVT(); // Enable NAV PVT data logging
|
||||
|
||||
myBuffer = new uint8_t[packetLength]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
if (myGNSS.fileBufferAvailable() >= packetLength) // Check to see if a new packetLength-byte NAV PVT message has been stored
|
||||
{
|
||||
myGNSS.extractFileBufferData(myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, packetLength); // Write exactly packetLength bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
//printBuffer(myBuffer); // Uncomment this line to print the data as Hexadecimal bytes
|
||||
}
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
myFile.close(); // Close the data file
|
||||
Serial.println(F("\r\nLogging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
|
||||
// Print the buffer contents as Hexadecimal bytes
|
||||
// You should see:
|
||||
// SYNC CHAR 1: 0xB5
|
||||
// SYNC CHAR 2: 0x62
|
||||
// CLASS: 0x01 for NAV
|
||||
// ID: 0x07 for PVT
|
||||
// LENGTH: 2-bytes Little Endian (0x5C00 = 92 bytes for NAV PVT)
|
||||
// PAYLOAD: LENGTH bytes
|
||||
// CHECKSUM_A
|
||||
// CHECKSUM_B
|
||||
// Please see the u-blox protocol specification for more details
|
||||
void printBuffer(uint8_t *ptr)
|
||||
{
|
||||
for (int i = 0; i < packetLength; i++)
|
||||
{
|
||||
if (ptr[i] < 16) Serial.print("0"); // Print a leading zero if required
|
||||
Serial.print(ptr[i], HEX); // Print the byte as Hexadecimal
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send TIM TM2 reports over I2C and log them to file on SD card
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send TIM TM2 reports automatically
|
||||
and log the data to SD card in UBX format.
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Connecting the PPS (Pulse Per Second) breakout pin to the INT (Interrupt) pin with a jumper wire
|
||||
will cause a TIM TM2 message to be produced once per second. You can then study the timing of the
|
||||
pulse edges with nanosecond resolution!
|
||||
|
||||
Note: TIM TM2 can only capture the timing of one rising edge and one falling edge per
|
||||
navigation solution. So with setNavigationFrequency set to 1Hz, we can only see the timing
|
||||
of one rising and one falling edge per second. If the frequency of the signal on the INT pin
|
||||
is higher than 1Hz, we will only be able to see the timing of the most recent edges.
|
||||
However, the module can count the number of rising edges too, at rates faster than the navigation rate.
|
||||
|
||||
TIM TM2 messages are only produced when a rising or falling edge is detected on the INT pin.
|
||||
If you disconnect your PPS to INT jumper wire, the messages will stop.
|
||||
|
||||
Data is logged in u-blox UBX format. Please see the u-blox protocol specification for more details.
|
||||
You can replay and analyze the data using u-center:
|
||||
https://www.u-blox.com/en/product/u-center
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
NEO-M9N: https://www.sparkfun.com/products/17285
|
||||
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define packetLength 36 // TIM TM2 is 28 + 8 bytes in length (including the sync chars, class, id, length and checksum bytes)
|
||||
uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card
|
||||
|
||||
int dotsPrinted = 0; // Print dots in rows of 50 while waiting for a TIM TM2 message
|
||||
|
||||
// Callback: printTIMTM2data will be called when new TIM TM2 data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_TIM_TM2_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoTIMTM2callback
|
||||
// / _____ This _must_ be UBX_TIM_TM2_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printTIMTM2data(UBX_TIM_TM2_data_t *ubxDataStruct)
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("newFallingEdge: ")); // 1 if a new falling edge was detected
|
||||
Serial.print(ubxDataStruct->flags.bits.newFallingEdge);
|
||||
|
||||
Serial.print(F(" newRisingEdge: ")); // 1 if a new rising edge was detected
|
||||
Serial.print(ubxDataStruct->flags.bits.newRisingEdge);
|
||||
|
||||
Serial.print(F(" Rising Edge Counter: ")); // Rising edge counter
|
||||
Serial.print(ubxDataStruct->count);
|
||||
|
||||
Serial.print(F(" towMsR: ")); // Time Of Week of rising edge (ms)
|
||||
Serial.print(ubxDataStruct->towMsR);
|
||||
|
||||
Serial.print(F(" towSubMsR: ")); // Millisecond fraction of Time Of Week of rising edge in nanoseconds
|
||||
Serial.print(ubxDataStruct->towSubMsR);
|
||||
|
||||
Serial.print(F(" towMsF: ")); // Time Of Week of falling edge (ms)
|
||||
Serial.print(ubxDataStruct->towMsF);
|
||||
|
||||
Serial.print(F(" towSubMsF: ")); // Millisecond fraction of Time Of Week of falling edge in nanoseconds
|
||||
Serial.println(ubxDataStruct->towSubMsF);
|
||||
|
||||
dotsPrinted = 0; // Reset dotsPrinted
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin(); // Start I2C communication with the GNSS
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "TIM_TM2.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("TIM_TM2.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful GNSS debug messages on Serial
|
||||
|
||||
// TIM TM2 messages are 36 bytes long.
|
||||
// In this example, the data will arrive no faster than one message per second.
|
||||
// So, setting the file buffer size to 109 bytes should be more than adequate.
|
||||
// I.e. room for three messages plus an empty tail byte.
|
||||
myGNSS.setFileBufferSize(109); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// (This will also disable any "auto" messages that were enabled and saved by other examples and reduce the load on the I2C bus)
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second
|
||||
|
||||
myGNSS.setAutoTIMTM2callbackPtr(&printTIMTM2data); // Enable automatic TIM TM2 messages with callback to printTIMTM2data
|
||||
|
||||
myGNSS.logTIMTM2(); // Enable TIM TM2 data logging
|
||||
|
||||
myBuffer = new uint8_t[packetLength]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
if (myGNSS.fileBufferAvailable() >= packetLength) // Check to see if a new packetLength-byte TIM TM2 message has been stored
|
||||
{
|
||||
myGNSS.extractFileBufferData(myBuffer, packetLength); // Extract exactly packetLength bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, packetLength); // Write exactly packetLength bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
//printBuffer(myBuffer); // Uncomment this line to print the data
|
||||
}
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
myFile.close(); // Close the data file
|
||||
Serial.println(F("\r\nLogging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
Serial.print("."); // Print dots in rows of 50
|
||||
delay(50);
|
||||
if (++dotsPrinted > 50)
|
||||
{
|
||||
Serial.println();
|
||||
dotsPrinted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Print the buffer contents as Hexadecimal
|
||||
// You should see:
|
||||
// SYNC CHAR 1: 0xB5
|
||||
// SYNC CHAR 2: 0x62
|
||||
// CLASS: 0x0D for TIM
|
||||
// ID: 0x03 for TM2
|
||||
// LENGTH: 2-bytes Little Endian (0x1C00 = 28 bytes for TIM TM2)
|
||||
// PAYLOAD: LENGTH bytes
|
||||
// CHECKSUM_A
|
||||
// CHECKSUM_B
|
||||
// Please see the u-blox protocol specification for more details
|
||||
void printBuffer(uint8_t *ptr)
|
||||
{
|
||||
for (int i = 0; i < packetLength; i++)
|
||||
{
|
||||
if (ptr[i] < 16) Serial.print("0"); // Print a leading zero if required
|
||||
Serial.print(ptr[i], HEX); // Print the byte as Hexadecimal
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send RXM SFRBX and RAWX reports over I2C and log them to file on SD card
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send RXM SFRBX and RAWX reports automatically
|
||||
and log the data to SD card in UBX format.
|
||||
|
||||
** Please note: this example will only work on u-blox ADR or High Precision GNSS or Time Sync products **
|
||||
|
||||
** Please note: this example will only work on processors like the Artemis which have plenty of RAM available **
|
||||
|
||||
Data is logged in u-blox UBX format. Please see the u-blox protocol specification for more details.
|
||||
You can replay and analyze the data using u-center:
|
||||
https://www.u-blox.com/en/product/u-center
|
||||
Or you can use (e.g.) RTKLIB to analyze the data and extract your precise location or produce
|
||||
Post-Processed Kinematic data:
|
||||
https://rtklibexplorer.wordpress.com/
|
||||
http://rtkexplorer.com/downloads/rtklib-code/
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes
|
||||
#define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage
|
||||
uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card
|
||||
|
||||
unsigned long lastPrint; // Record when the last Serial print took place
|
||||
|
||||
// Note: we'll keep a count of how many SFRBX and RAWX messages arrive - but the count will not be completely accurate.
|
||||
// If two or more SFRBX messages arrive together as a group and are processed by one call to checkUblox, the count will
|
||||
// only increase by one.
|
||||
|
||||
int numSFRBX = 0; // Keep count of how many SFRBX message groups have been received (see note above)
|
||||
int numRAWX = 0; // Keep count of how many RAWX message groups have been received (see note above)
|
||||
|
||||
// Callback: newSFRBX will be called when new RXM SFRBX data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXMSFRBX_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMSFRBXcallback
|
||||
// / _____ This _must_ be UBX_RXM_SFRBX_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newSFRBX(UBX_RXM_SFRBX_data_t *ubxDataStruct)
|
||||
{
|
||||
numSFRBX++; // Increment the count
|
||||
}
|
||||
|
||||
// Callback: newRAWX will be called when new RXM RAWX data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback
|
||||
// / _____ This _must_ be UBX_RXM_RAWX_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct)
|
||||
{
|
||||
numRAWX++; // Increment the count
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Flash LED_BUILTIN each time we write to the SD card
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
Wire.begin(); // Start I2C communication
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "RXM_RAWX.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("RXM_RAWX.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable lots of helpful GNSS debug messages on Serial
|
||||
//myGNSS.enableDebugging(Serial, true); // Or, uncomment this line to enable only the important GNSS debug messages on Serial
|
||||
|
||||
myGNSS.disableUBX7Fcheck(); // RAWX data can legitimately contain 0x7F, so we need to disable the "7F" check in checkUbloxI2C
|
||||
|
||||
// RAWX messages can be over 2KBytes in size, so we need to make sure we allocate enough RAM to hold all the data.
|
||||
// SD cards can occasionally 'hiccup' and a write takes much longer than usual. The buffer needs to be big enough
|
||||
// to hold the backlog of data if/when this happens.
|
||||
// getMaxFileBufferAvail will tell us the maximum number of bytes which the file buffer has contained.
|
||||
myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// (This will also disable any "auto" messages that were enabled and saved by other examples and reduce the load on the I2C bus)
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second (that's plenty for Precise Point Positioning)
|
||||
|
||||
myGNSS.setAutoRXMSFRBXcallbackPtr(&newSFRBX); // Enable automatic RXM SFRBX messages with callback to newSFRBX
|
||||
|
||||
myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging
|
||||
|
||||
myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX
|
||||
|
||||
myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging
|
||||
|
||||
myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
|
||||
lastPrint = millis(); // Initialize lastPrint
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
// In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off again
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (millis() > (lastPrint + 1000)) // Print the message count once per second
|
||||
{
|
||||
Serial.print(F("Number of message groups received: SFRBX: ")); // Print how many message groups have been received (see note above)
|
||||
Serial.print(numSFRBX);
|
||||
Serial.print(F(" RAWX: "));
|
||||
Serial.println(numRAWX);
|
||||
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)
|
||||
|
||||
//Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets
|
||||
//Serial.println(maxBufferBytes);
|
||||
|
||||
if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full
|
||||
{
|
||||
Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost."));
|
||||
}
|
||||
|
||||
lastPrint = millis(); // Update lastPrint
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer
|
||||
|
||||
while (remainingBytes > 0) // While there is still data in the file buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card
|
||||
|
||||
uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
|
||||
if (bytesToWrite > sdWriteSize)
|
||||
{
|
||||
bytesToWrite = sdWriteSize;
|
||||
}
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
remainingBytes -= bytesToWrite; // Decrement remainingBytes
|
||||
}
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off
|
||||
|
||||
myFile.close(); // Close the data file
|
||||
|
||||
Serial.println(F("Logging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
}
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send RXM SFRBX and RAWX reports over I2C and log them to file on SD card
|
||||
** without using callbacks **
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send RXM SFRBX and RAWX reports automatically
|
||||
and log the data to SD card in UBX format ** without using callbacks **
|
||||
|
||||
** Please note: this example will only work on u-blox ADR or High Precision GNSS or Time Sync products **
|
||||
|
||||
** Please note: this example will only work on processors like the Artemis which have plenty of RAM available **
|
||||
|
||||
Data is logged in u-blox UBX format. Please see the u-blox protocol specification for more details.
|
||||
You can replay and analyze the data using u-center:
|
||||
https://www.u-blox.com/en/product/u-center
|
||||
Or you can use (e.g.) RTKLIB to analyze the data and extract your precise location or produce
|
||||
Post-Processed Kinematic data:
|
||||
https://rtklibexplorer.wordpress.com/
|
||||
http://rtkexplorer.com/downloads/rtklib-code/
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes
|
||||
#define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage
|
||||
uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card
|
||||
|
||||
unsigned long lastPrint; // Record when the last Serial print took place
|
||||
unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Flash LED_BUILTIN each time we write to the SD card
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
Wire.begin(); // Start I2C communication
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "RXM_RAWX.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("RXM_RAWX.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable lots of helpful GNSS debug messages on Serial
|
||||
//myGNSS.enableDebugging(Serial, true); // Or, uncomment this line to enable only the important GNSS debug messages on Serial
|
||||
|
||||
myGNSS.disableUBX7Fcheck(); // RAWX data can legitimately contain 0x7F, so we need to disable the "7F" check in checkUbloxI2C
|
||||
|
||||
// RAWX messages can be over 2KBytes in size, so we need to make sure we allocate enough RAM to hold all the data.
|
||||
// SD cards can occasionally 'hiccup' and a write takes much longer than usual. The buffer needs to be big enough
|
||||
// to hold the backlog of data if/when this happens.
|
||||
// getMaxFileBufferAvail will tell us the maximum number of bytes which the file buffer has contained.
|
||||
myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// (This will also disable any "auto" messages that were enabled and saved by other examples and reduce the load on the I2C bus)
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second (that's plenty for Precise Point Positioning)
|
||||
|
||||
myGNSS.setAutoRXMSFRBX(true, false); // Enable automatic RXM SFRBX messages: without callback; without implicit update
|
||||
|
||||
myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging
|
||||
|
||||
myGNSS.setAutoRXMRAWX(true, false); // Enable automatic RXM RAWX messages: without callback; without implicit update
|
||||
|
||||
myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging
|
||||
|
||||
myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
|
||||
lastPrint = millis(); // Initialize lastPrint
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += sdWriteSize; // Update bytesWritten
|
||||
|
||||
// In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off again
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (millis() > (lastPrint + 1000)) // Print bytesWritten once per second
|
||||
{
|
||||
Serial.print(F("The number of bytes written to SD card is ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)
|
||||
|
||||
//Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets
|
||||
//Serial.println(maxBufferBytes);
|
||||
|
||||
if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full
|
||||
{
|
||||
Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost."));
|
||||
}
|
||||
|
||||
lastPrint = millis(); // Update lastPrint
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer
|
||||
|
||||
while (remainingBytes > 0) // While there is still data in the file buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card
|
||||
|
||||
uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
|
||||
if (bytesToWrite > sdWriteSize)
|
||||
{
|
||||
bytesToWrite = sdWriteSize;
|
||||
}
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += bytesToWrite; // Update bytesWritten
|
||||
|
||||
remainingBytes -= bytesToWrite; // Decrement remainingBytes
|
||||
}
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off
|
||||
|
||||
Serial.print(F("The total number of bytes written to SD card is ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
myFile.close(); // Close the data file
|
||||
|
||||
Serial.println(F("Logging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
}
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send RXM SFRBX and RAWX reports over I2C and log them to file on SD card
|
||||
without using callbacks and ** as fast as your module can go! **
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send RXM SFRBX and RAWX reports automatically
|
||||
and log the data to SD card in UBX format without using callbacks and ** as fast as your module can go! **
|
||||
|
||||
** Please note: this example will only work on u-blox ADR or High Precision GNSS or Time Sync products **
|
||||
|
||||
** Please note: this example will only work on processors like the Artemis which have plenty of RAM available **
|
||||
|
||||
Data is logged in u-blox UBX format. Please see the u-blox protocol specification for more details.
|
||||
You can replay and analyze the data using u-center:
|
||||
https://www.u-blox.com/en/product/u-center
|
||||
Or you can use (e.g.) RTKLIB to analyze the data and extract your precise location or produce
|
||||
Post-Processed Kinematic data:
|
||||
https://rtklibexplorer.wordpress.com/
|
||||
http://rtkexplorer.com/downloads/rtklib-code/
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes
|
||||
#define fileBufferSize 32768 // Allocate 32KBytes of RAM for UBX message storage
|
||||
uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card
|
||||
|
||||
unsigned long lastPrint; // Record when the last Serial print took place
|
||||
unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Flash LED_BUILTIN each time we write to the SD card
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
Wire.begin(); // Start I2C communication
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "Fast_RXM.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("Fast_RXM.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable lots of helpful GNSS debug messages on Serial
|
||||
//myGNSS.enableDebugging(Serial, true); // Or, uncomment this line to enable only the important GNSS debug messages on Serial
|
||||
|
||||
myGNSS.disableUBX7Fcheck(); // RAWX data can legitimately contain 0x7F, so we need to disable the "7F" check in checkUbloxI2C
|
||||
|
||||
// RAWX messages can be over 2KBytes in size, so we need to make sure we allocate enough RAM to hold all the data.
|
||||
// SD cards can occasionally 'hiccup' and a write takes much longer than usual. The buffer needs to be big enough
|
||||
// to hold the backlog of data if/when this happens.
|
||||
// getMaxFileBufferAvail will tell us the maximum number of bytes which the file buffer has contained.
|
||||
myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// (This will also disable any "auto" messages that were enabled and saved by other examples and reduce the load on the I2C bus)
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
// Modules like the ZED-F9P can produce RAW navigation data at rates of up to 25Hz but not while using all of the GNSS constellations.
|
||||
// Please consult the data sheet for the Performance figures for your module.
|
||||
// In this example we make sure GPS is enabled and then disable Galileo, GLONASS, BeiDou, SBAS and QZSS to achieve 25Hz.
|
||||
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GPS); // Make sure GPS is enabled (we must leave at least one major GNSS enabled!)
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_SBAS); // Disable SBAS
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_GALILEO); // Disable Galileo
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_BEIDOU); // Disable BeiDou
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_IMES); // Disable IMES
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_QZSS); // Disable QZSS
|
||||
myGNSS.enableGNSS(false, SFE_UBLOX_GNSS_ID_GLONASS); // Disable GLONASS
|
||||
|
||||
delay(2000); // Give the module some extra time to get ready
|
||||
|
||||
//Produce 7 navigation solutions per second. That's a lot of RAWX data - especially when using both GPS bands L1 and L2.
|
||||
//The SD library and card need to be able to cope with the data rate too. You may need a faster SD library to go above 7Hz.
|
||||
myGNSS.setNavigationFrequency(7);
|
||||
|
||||
myGNSS.setAutoRXMSFRBX(true, false); // Enable automatic RXM SFRBX messages: without callback; without implicit update
|
||||
|
||||
myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging
|
||||
|
||||
myGNSS.setAutoRXMRAWX(true, false); // Enable automatic RXM RAWX messages: without callback; without implicit update
|
||||
|
||||
myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging
|
||||
|
||||
myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
|
||||
lastPrint = millis(); // Initialize lastPrint
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += sdWriteSize; // Update bytesWritten
|
||||
|
||||
// In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off again
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (millis() > (lastPrint + 1000)) // Print bytesWritten once per second
|
||||
{
|
||||
Serial.print(F("The number of bytes written to SD card is: ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)
|
||||
|
||||
//Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets
|
||||
//Serial.println(maxBufferBytes);
|
||||
|
||||
if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full
|
||||
{
|
||||
Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost."));
|
||||
}
|
||||
|
||||
lastPrint = millis(); // Update lastPrint
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
myGNSS.setAutoRXMSFRBX(false, false); // Disable the automatic RXM SFRBX messages
|
||||
myGNSS.setAutoRXMRAWX(false, false); // Disable the automatic RXM RAWX messages
|
||||
|
||||
delay(1000); // Allow time for any remaining messages to arrive
|
||||
myGNSS.checkUblox(); // Process any remaining data
|
||||
|
||||
uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer
|
||||
|
||||
while (remainingBytes > 0) // While there is still data in the file buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card
|
||||
|
||||
uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
|
||||
if (bytesToWrite > sdWriteSize)
|
||||
{
|
||||
bytesToWrite = sdWriteSize;
|
||||
}
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += bytesToWrite; // Update bytesWritten
|
||||
|
||||
remainingBytes -= bytesToWrite; // Decrement remainingBytes
|
||||
}
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off
|
||||
|
||||
Serial.print(F("The total number of bytes written to SD card is: ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Show how full the file buffer has been (not how full it is now)
|
||||
Serial.print(F("The maximum number of bytes which the file buffer has contained is: "));
|
||||
Serial.println(maxBufferBytes);
|
||||
|
||||
myFile.close(); // Close the data file
|
||||
|
||||
Serial.println(F("Logging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
Demonstrate how to log NMEA and UBX data simultaneously
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 18th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send PVT reports automatically
|
||||
and log those and any incoming NMEA messages to SD card in UBX format
|
||||
|
||||
** Please note: this example will only work on processors like the Artemis which have plenty of RAM available **
|
||||
|
||||
This code is intended to be run on the MicroMod Data Logging Carrier Board using the Artemis Processor
|
||||
but can be adapted by changing the chip select pin and SPI definitions:
|
||||
https://www.sparkfun.com/products/16829
|
||||
https://www.sparkfun.com/products/16401
|
||||
|
||||
Hardware Connections:
|
||||
Please see: https://learn.sparkfun.com/tutorials/micromod-data-logging-carrier-board-hookup-guide
|
||||
Insert the Artemis Processor into the MicroMod Data Logging Carrier Board and secure with the screw.
|
||||
Connect your GNSS breakout to the Carrier Board using a Qwiic cable.
|
||||
Connect an antenna to your GNSS board if required.
|
||||
Insert a formatted micro-SD card into the socket on the Carrier Board.
|
||||
Connect the Carrier Board to your computer using a USB-C cable.
|
||||
Ensure you have the SparkFun Apollo3 boards installed: http://boardsmanager/All#SparkFun_Apollo3
|
||||
This code has been tested using version 2.2.0 of the Apollo3 boards on Arduino IDE 1.8.13.
|
||||
Select "Artemis MicroMod Processor" as the board type.
|
||||
Press upload to upload the code onto the Artemis.
|
||||
Open the Serial Monitor at 115200 baud to see the output.
|
||||
|
||||
To minimise I2C bus errors, it is a good idea to open the I2C pull-up split pad links on
|
||||
both the MicroMod Data Logging Carrier Board and the u-blox module breakout.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
ZOE-M8Q: https://www.sparkfun.com/products/15193
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15210
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
File myFile; //File that all GNSS data is written to
|
||||
|
||||
//Define the microSD (SPI) Chip Select pin. Adjust for your processor if necessary.
|
||||
#if defined(ARDUINO_ARCH_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1 or v2
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#define sdChipSelect SPI_CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
#elif defined(ARDUINO_AM_AP3_SFE_ARTEMIS_MICROMOD) // Check for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#define sdChipSelect CS // SPI (microSD) Chip Select for the Artemis MicroMod Processor Board on Apollo3 v1
|
||||
#else
|
||||
#define sdChipSelect CS // Catch-all for the other Artemis Boards - change this if required to match your hardware
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define sdChipSelect CS // Catch-all for all non-Artemis boards - change this if required to match your hardware
|
||||
|
||||
#endif
|
||||
|
||||
#define sdWriteSize 512 // Write data to the SD card in blocks of 512 bytes
|
||||
#define fileBufferSize 16384 // Allocate 16KBytes of RAM for UBX message storage
|
||||
uint8_t *myBuffer; // A buffer to hold the data while we write it to SD card
|
||||
|
||||
unsigned long lastPrint; // Record when the last Serial print took place
|
||||
unsigned long bytesWritten = 0; // Record how many bytes have been written to SD card
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT); // Flash LED_BUILTIN each time we write to the SD card
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
Wire.begin(); // Start I2C communication
|
||||
|
||||
// On the Artemis, we can disable the internal I2C pull-ups too to help reduce bus errors
|
||||
#if defined(AM_PART_APOLLO3) // Check for SparkFun Apollo3 (Artemis) v1
|
||||
Wire.setPullups(0); // Disable the internal I2C pull-ups on Apollo3 v1
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3) // Else check for SparkFun Apollo3 (Artemis) (v2)
|
||||
#if defined(ARDUINO_APOLLO3_SFE_ARTEMIS_MM_PB) // Check for the Artemis MicroMod Processor Board on Apollo3 v2
|
||||
// On Apollo3 v2 we can still disable the pull-ups but we need to do it manually
|
||||
// The IOM and pin numbers here are specific to the Artemis MicroMod Processor Board
|
||||
am_hal_gpio_pincfg_t sclPinCfg = g_AM_BSP_GPIO_IOM4_SCL; // Artemis MicroMod Processor Board uses IOM4 for I2C communication
|
||||
am_hal_gpio_pincfg_t sdaPinCfg = g_AM_BSP_GPIO_IOM4_SDA;
|
||||
sclPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; // Disable the pull-ups
|
||||
sdaPinCfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE;
|
||||
pin_config(PinName(39), sclPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 39 for SCL
|
||||
pin_config(PinName(40), sdaPinCfg); // Artemis MicroMod Processor Board uses Pin/Pad 40 for SDA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println("Initializing SD card...");
|
||||
|
||||
// See if the card is present and can be initialized:
|
||||
if (!SD.begin(sdChipSelect))
|
||||
{
|
||||
Serial.println("Card failed, or not present. Freezing...");
|
||||
// don't do anything more:
|
||||
while (1);
|
||||
}
|
||||
Serial.println("SD card initialized.");
|
||||
|
||||
// Create or open a file called "PVT_NMEA.ubx" on the SD card.
|
||||
// If the file already exists, the new data is appended to the end of the file.
|
||||
myFile = SD.open("PVT_NMEA.ubx", FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to create UBX data file! Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable lots of helpful GNSS debug messages on Serial
|
||||
//myGNSS.enableDebugging(Serial, true); // Or, uncomment this line to enable only the important GNSS debug messages on Serial
|
||||
|
||||
//myGNSS.disableUBX7Fcheck(); // RAWX data can legitimately contain 0x7F. Uncomment this line to disable the "7F" check in checkUbloxI2C
|
||||
|
||||
// SD cards can occasionally 'hiccup' and a write takes much longer than usual. The buffer needs to be big enough
|
||||
// to hold the backlog of data if/when this happens.
|
||||
// getMaxFileBufferAvail will tell us the maximum number of bytes which the file buffer has contained.
|
||||
myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
// This will (re)enable the standard NMEA messages too
|
||||
// This will also disable any "auto" UBX messages that were enabled and saved by other examples and reduce the load on the I2C bus
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both UBX and NMEA messages
|
||||
|
||||
//myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Optional: save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(1); //Produce one navigation solution per second
|
||||
|
||||
myGNSS.setAutoPVT(true, false); // Enable automatic NAV PVT messages: without callback; without implicit update
|
||||
myGNSS.logNAVPVT(); // Enable NAV PVT data logging
|
||||
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_I2C, 1); // Ensure the GxGGA (Global positioning system fix data) message is enabled. Send every measurement.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GSA, COM_PORT_I2C, 1); // Ensure the GxGSA (GNSS DOP and Active satellites) message is enabled. Send every measurement.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GSV, COM_PORT_I2C, 1); // Ensure the GxGSV (GNSS satellites in view) message is enabled. Send every measurement.
|
||||
|
||||
myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_ALL); // Enable logging of all enabled NMEA messages
|
||||
//myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_GGA | SFE_UBLOX_FILTER_NMEA_GSA); // Or we can, for example, log only GxGGA & GxGSA and ignore GxGSV
|
||||
|
||||
myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
|
||||
lastPrint = millis(); // Initialize lastPrint
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN each time we write to the SD card
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += sdWriteSize; // Update bytesWritten
|
||||
|
||||
// In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off again
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (millis() > (lastPrint + 1000)) // Print bytesWritten once per second
|
||||
{
|
||||
Serial.print(F("The number of bytes written to SD card is ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)
|
||||
|
||||
//Serial.print(F("The maximum number of bytes which the file buffer has contained is: ")); // It is a fun thing to watch how full the buffer gets
|
||||
//Serial.println(maxBufferBytes);
|
||||
|
||||
if (maxBufferBytes > ((fileBufferSize / 5) * 4)) // Warn the user if fileBufferSize was more than 80% full
|
||||
{
|
||||
Serial.println(F("Warning: the file buffer has been over 80% full. Some data may have been lost."));
|
||||
}
|
||||
|
||||
lastPrint = millis(); // Update lastPrint
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer
|
||||
|
||||
while (remainingBytes > 0) // While there is still data in the file buffer
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // Flash LED_BUILTIN while we write to the SD card
|
||||
|
||||
uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
|
||||
if (bytesToWrite > sdWriteSize)
|
||||
{
|
||||
bytesToWrite = sdWriteSize;
|
||||
}
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
bytesWritten += bytesToWrite; // Update bytesWritten
|
||||
|
||||
remainingBytes -= bytesToWrite; // Decrement remainingBytes
|
||||
}
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW); // Turn LED_BUILTIN off
|
||||
|
||||
Serial.print(F("The total number of bytes written to SD card is ")); // Print how many bytes have been written to SD card
|
||||
Serial.println(bytesWritten);
|
||||
|
||||
myFile.close(); // Close the data file
|
||||
|
||||
Serial.println(F("Logging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
}
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send RXM SFRBX and RAWX reports over SPI and log them to file on SD card using full 4-bit SDIO
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: October 20th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the u-blox GNSS to send RXM SFRBX and RAWX reports automatically
|
||||
and log the data to SD card in UBX format.
|
||||
|
||||
This code is written for the OpenLog ESP32 (DEV-20594) - coming soon!
|
||||
|
||||
Hardware set-up:
|
||||
Close the DSEL jumper on the ZED-F9P breakout - to select SPI mode
|
||||
Connect:
|
||||
OpenLog ESP32 : ZED-F9P
|
||||
GND GND
|
||||
3V3_SW 3V3
|
||||
SCK (18) SCK
|
||||
PICO (23) PICO (MOSI)
|
||||
POCI (19) POCI (MISO)
|
||||
33 CS
|
||||
|
||||
** Please note: this example will only work on u-blox ADR or High Precision GNSS or Time Sync products **
|
||||
|
||||
Data is logged in u-blox UBX format.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
OpenLog ESP32: https://www.sparkfun.com/products/20594
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
*/
|
||||
|
||||
#define GNSS_CS 33 // Connect the ZED-F9P CS pin to OpenLog ESP32 pin 33
|
||||
#define EN_3V3_SW 32 // The 3.3V_SW regulator Enable pin is connected to D32
|
||||
#define STAT_LED 25 // The OpenLog ESP32 STAT LED is connected to pin 25
|
||||
#define IMU_CS 5 // The ISM330 IMU CS is connected to pin 5
|
||||
#define MAG_CS 27 // The MMC5983 Mag CS is connected to pin 27
|
||||
|
||||
#include "FS.h"
|
||||
#include "SD_MMC.h"
|
||||
File myFile;
|
||||
|
||||
#include <SPI.h>
|
||||
#define spiPort SPI
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#define sdWriteSize 2048 // Write data to the SD card in blocks of n*512 bytes
|
||||
#define fileBufferSize 65530 // Allocate just under 64KBytes of RAM for UBX message storage
|
||||
#define navRate 20 // Set the Nav Rate (Frequency) to 20Hz
|
||||
//#define ubxOnly // Uncomment this line to log UBX (RAWX and SFRBX) only
|
||||
uint8_t *myBuffer; // Use myBuffer to hold the data while we write it to SD card
|
||||
|
||||
unsigned long lastPrint; // Record when the last Serial print took place
|
||||
|
||||
// Note: we'll keep a count of how many SFRBX and RAWX messages arrive - but the count will not be completely accurate.
|
||||
// If two or more SFRBX messages arrive together as a group and are processed by one call to checkUblox, the count will
|
||||
// only increase by one.
|
||||
|
||||
int numSFRBX = 0; // Keep count of how many SFRBX message groups have been received (see note above)
|
||||
int numRAWX = 0; // Keep count of how many RAWX message groups have been received (see note above)
|
||||
|
||||
// Callback: newSFRBX will be called when new RXM SFRBX data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXMSFRBX_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMSFRBXcallback
|
||||
// / _____ This _must_ be UBX_RXM_SFRBX_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newSFRBX(UBX_RXM_SFRBX_data_t *ubxDataStruct)
|
||||
{
|
||||
numSFRBX++; // Increment the count
|
||||
}
|
||||
|
||||
// Callback: newRAWX will be called when new RXM RAWX data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXMRAWX_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoRXMRAWXcallback
|
||||
// / _____ This _must_ be UBX_RXM_RAWX_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void newRAWX(UBX_RXM_RAWX_data_t *ubxDataStruct)
|
||||
{
|
||||
numRAWX++; // Increment the count
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
pinMode(STAT_LED, OUTPUT); // Flash the STAT LED each time we write to the SD card
|
||||
digitalWrite(STAT_LED, LOW);
|
||||
|
||||
pinMode(GNSS_CS, OUTPUT);
|
||||
digitalWrite(GNSS_CS, HIGH);
|
||||
pinMode(IMU_CS, OUTPUT);
|
||||
digitalWrite(IMU_CS, HIGH);
|
||||
pinMode(MAG_CS, OUTPUT);
|
||||
digitalWrite(MAG_CS, HIGH);
|
||||
|
||||
spiPort.begin();
|
||||
|
||||
// Do a fake transaction to initialize the SPI pins
|
||||
spiPort.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
spiPort.transfer(0);
|
||||
spiPort.endTransaction();
|
||||
|
||||
pinMode(EN_3V3_SW, OUTPUT); // Enable power for the microSD card and GNSS
|
||||
digitalWrite(EN_3V3_SW, HIGH);
|
||||
|
||||
delay(3000); // Allow time for the GNSS and SD card to start up and for Tera Term to reconnect
|
||||
Serial.println(F("SparkFun OpenLog ESP32 GNSS Logging : SPI and SDIO"));
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Initialize the GNSS
|
||||
|
||||
Serial.println(F("Initializing the GNSS..."));
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial
|
||||
|
||||
myGNSS.setFileBufferSize(fileBufferSize); // setFileBufferSize must be called _before_ .begin
|
||||
|
||||
// Connect to the u-blox module using SPI port, csPin and speed setting
|
||||
// ublox devices generally work up to 5MHz. We'll use 4MHz for this example:
|
||||
bool begun = false;
|
||||
do
|
||||
{
|
||||
begun = myGNSS.begin(spiPort, GNSS_CS, 4000000);
|
||||
if (!begun)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected on SPI bus."));
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
while (!begun);
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Wait for a 3D fix. Get the date and time for the log file
|
||||
|
||||
//myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults
|
||||
|
||||
#ifdef ubxOnly
|
||||
myGNSS.setSPIOutput(COM_TYPE_UBX); //Set the SPI port to output only UBX
|
||||
#else
|
||||
myGNSS.setSPIOutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the SPI port to output both UBX and NMEA messages
|
||||
#endif
|
||||
|
||||
//myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Optional: save (only) the communications port settings to flash and BBR
|
||||
|
||||
Serial.print(F("Waiting for a 3D fix"));
|
||||
|
||||
uint8_t fix = 0;
|
||||
|
||||
do
|
||||
{
|
||||
fix = myGNSS.getFixType();
|
||||
delay(1000);
|
||||
Serial.print(F("."));
|
||||
}
|
||||
while ( fix != 3 ); // Wait for a 3D fix
|
||||
|
||||
Serial.println();
|
||||
|
||||
uint16_t y = myGNSS.getYear();
|
||||
uint8_t M = myGNSS.getMonth();
|
||||
uint8_t d = myGNSS.getDay();
|
||||
uint8_t h = myGNSS.getHour();
|
||||
uint8_t m = myGNSS.getMinute();
|
||||
uint8_t s = myGNSS.getSecond();
|
||||
|
||||
char szBuffer[40] = {'\0'};
|
||||
snprintf(szBuffer, sizeof(szBuffer), "/%04d%02d%02d%02d%02d%02d.ubx", y, M, d, h, m, s);
|
||||
|
||||
Serial.println(F("GNSS initialized."));
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Initialize the SD card. Open the log file
|
||||
|
||||
Serial.println(F("Initializing SD card..."));
|
||||
|
||||
// Begin the SD card
|
||||
if(!SD_MMC.begin())
|
||||
{
|
||||
Serial.println(F("Card mount failed. Freezing..."));
|
||||
while(1);
|
||||
}
|
||||
|
||||
// Open the log file for writing
|
||||
Serial.printf("Log file is: %s\r\n", szBuffer);
|
||||
myFile = SD_MMC.open((const char *)szBuffer, FILE_WRITE);
|
||||
if(!myFile)
|
||||
{
|
||||
Serial.println(F("Failed to open log file for writing. Freezing..."));
|
||||
while(1);
|
||||
}
|
||||
|
||||
Serial.println(F("SD card initialized."));
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Wait for a key press
|
||||
|
||||
while (Serial.available()) // Make sure the Serial buffer is empty
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
Serial.println(F("Press any key to start logging."));
|
||||
|
||||
while (!Serial.available()) // Wait for the user to press a key
|
||||
{
|
||||
; // Do nothing
|
||||
}
|
||||
|
||||
delay(100); // Wait, just in case multiple characters were sent
|
||||
|
||||
while (Serial.available()) // Empty the Serial buffer
|
||||
{
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Enable RAWX and SFRBX
|
||||
|
||||
myGNSS.setAutoRXMSFRBXcallbackPtr(&newSFRBX); // Enable automatic RXM SFRBX messages with callback to newSFRBX
|
||||
|
||||
myGNSS.logRXMSFRBX(); // Enable RXM SFRBX data logging
|
||||
|
||||
myGNSS.setAutoRXMRAWXcallbackPtr(&newRAWX); // Enable automatic RXM RAWX messages with callback to newRAWX
|
||||
|
||||
myGNSS.logRXMRAWX(); // Enable RXM RAWX data logging
|
||||
|
||||
myBuffer = new uint8_t[sdWriteSize]; // Create our own buffer to hold the data while we write it to SD card
|
||||
|
||||
#ifndef ubxOnly
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_SPI, navRate); // Ensure the GxGGA (Global positioning system fix data) message is enabled. Send every second.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GSA, COM_PORT_SPI, navRate); // Ensure the GxGSA (GNSS DOP and Active satellites) message is enabled. Send every second.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GSV, COM_PORT_SPI, navRate); // Ensure the GxGSV (GNSS satellites in view) message is enabled. Send every second.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GST, COM_PORT_SPI, navRate); // Ensure the GxGST (Position error statistics) message is enabled. Send every second.
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_RMC, COM_PORT_SPI, navRate); // Ensure the GxRMC (Recommended minimum: position, velocity and time) message is enabled. Send every second.
|
||||
myGNSS.setNMEALoggingMask(SFE_UBLOX_FILTER_NMEA_GGA | SFE_UBLOX_FILTER_NMEA_GSA | SFE_UBLOX_FILTER_NMEA_GSV | SFE_UBLOX_FILTER_NMEA_GST | SFE_UBLOX_FILTER_NMEA_RMC); // Log only these NMEA messages
|
||||
#endif
|
||||
|
||||
myGNSS.setNavigationFrequency(navRate); // Set navigation rate
|
||||
|
||||
Serial.println(F("Press any key to stop logging."));
|
||||
|
||||
lastPrint = millis(); // Initialize lastPrint
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
while (myGNSS.fileBufferAvailable() >= sdWriteSize) // Check to see if we have at least sdWriteSize waiting in the buffer
|
||||
{
|
||||
digitalWrite(STAT_LED, HIGH); // Flash the STAT LED each time we write to the SD card
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, sdWriteSize); // Extract exactly sdWriteSize bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, sdWriteSize); // Write exactly sdWriteSize bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
// In case the SD writing is slow or there is a lot of data to write, keep checking for the arrival of new data
|
||||
myGNSS.checkUblox(); // Check for the arrival of new data and process it.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
digitalWrite(STAT_LED, LOW); // Turn the STAT LED off again
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (millis() > (lastPrint + 1000)) // Print the message count once per second
|
||||
{
|
||||
uint16_t maxBufferBytes = myGNSS.getMaxFileBufferAvail(); // Get how full the file buffer has been (not how full it is now)
|
||||
float bufferHigh = 100.0 * (float)maxBufferBytes / (float)fileBufferSize;
|
||||
|
||||
Serial.print(F("Message groups received: SFRBX: ")); // Print how many message groups have been received (see note above)
|
||||
Serial.print(numSFRBX);
|
||||
Serial.print(F(" RAWX: "));
|
||||
Serial.print(numRAWX);
|
||||
Serial.print(F(" \tBuffer high tide: "));
|
||||
Serial.print(bufferHigh, 1); // It is a fun thing to watch how full the buffer gets
|
||||
if (bufferHigh > 90.)
|
||||
Serial.println(F("%!!"));
|
||||
else if (bufferHigh > 80.)
|
||||
Serial.println(F("%!"));
|
||||
else
|
||||
Serial.println(F("%"));
|
||||
|
||||
lastPrint = millis(); // Update lastPrint
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
if (Serial.available()) // Check if the user wants to stop logging
|
||||
{
|
||||
uint16_t remainingBytes = myGNSS.fileBufferAvailable(); // Check if there are any bytes remaining in the file buffer
|
||||
|
||||
while (remainingBytes > 0) // While there is still data in the file buffer
|
||||
{
|
||||
digitalWrite(STAT_LED, HIGH); // Flash the STAT LED while we write to the SD card
|
||||
|
||||
uint16_t bytesToWrite = remainingBytes; // Write the remaining bytes to SD card sdWriteSize bytes at a time
|
||||
if (bytesToWrite > sdWriteSize)
|
||||
{
|
||||
bytesToWrite = sdWriteSize;
|
||||
}
|
||||
|
||||
myGNSS.extractFileBufferData(myBuffer, bytesToWrite); // Extract bytesToWrite bytes from the UBX file buffer and put them into myBuffer
|
||||
|
||||
myFile.write(myBuffer, bytesToWrite); // Write bytesToWrite bytes from myBuffer to the ubxDataFile on the SD card
|
||||
|
||||
remainingBytes -= bytesToWrite; // Decrement remainingBytes
|
||||
}
|
||||
|
||||
digitalWrite(STAT_LED, LOW); // Turn the STAT LED off
|
||||
|
||||
myFile.close(); // Close the data file
|
||||
|
||||
myGNSS.setNavigationFrequency(1); // Set navigation rate to 1Hz
|
||||
|
||||
myGNSS.disableMessage(UBX_CLASS_RXM, UBX_RXM_RAWX, COM_PORT_SPI);
|
||||
myGNSS.disableMessage(UBX_CLASS_RXM, UBX_RXM_SFRBX, COM_PORT_SPI);
|
||||
|
||||
myGNSS.setSPIOutput(COM_TYPE_UBX | COM_TYPE_NMEA); // Re-enable NMEA
|
||||
|
||||
Serial.println(F("Logging stopped. Freezing..."));
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
By: Elias Santistevan
|
||||
SparkFun Electronics
|
||||
Date: May, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
To take advantage of the internal IMU of either the Dead Reckoning GNSS
|
||||
boards (ZED-F9R, NEO-M8U), you must first calibrate it. This includes securing the GNSS module
|
||||
to your vehicle so that it is stable within 2 degrees and that the frame of
|
||||
reference of the board is consistent with the picture outlined in the
|
||||
Receiver-Description-Prot-Spec Datasheet under Automotive/Untethered Dead
|
||||
Reckoning. You may also check either the ZED-F9R or NEO-M8U Hookup Guide for
|
||||
more information. After the board is secure, you'll need to put the module
|
||||
through certain conditions for proper calibration: acceleration, turning,
|
||||
stopping for a few minutes, getting to a speed over 30km/h all under a clear sky
|
||||
with good GNSS signal. This example simply looks at the
|
||||
"fusionMode" status which indicates whether the SparkFun Dead Reckoning is
|
||||
initializing - 0, calibrated - 1, or if an error has occurred - 2,3.
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
//myGNSS.resetIMUalignment(); // Uncomment this line to reset the IMU alignment
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// ESF data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getEsfInfo()) // Poll new ESF STATUS data
|
||||
{
|
||||
Serial.print(F("Fusion Mode: "));
|
||||
Serial.print(myGNSS.packetUBXESFSTATUS->data.fusionMode);
|
||||
if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 0)
|
||||
Serial.println(F(" Sensor is initializing..."));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 1)
|
||||
Serial.println(F(" Sensor is calibrated!"));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 2)
|
||||
Serial.println(F(" Sensor fusion is suspended!"));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 3)
|
||||
Serial.println(F(" Sensor fusion is disabled!"));
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
By: Elias Santistevan
|
||||
SparkFun Electronics
|
||||
Date: May, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
After calibrating the module, also known as "Fusion Mode", you can get
|
||||
data directly from the IMU. This data is integrated directly into the GNSS
|
||||
output, but is provided by the module as well.
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
if (myGNSS.getEsfInfo()){
|
||||
|
||||
Serial.print(F("Fusion Mode: "));
|
||||
Serial.println(myGNSS.packetUBXESFSTATUS->data.fusionMode);
|
||||
|
||||
if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 1){
|
||||
Serial.println(F("Fusion Mode is Initialized!"));
|
||||
}
|
||||
else {
|
||||
Serial.println(F("Fusion Mode is either disabled or not initialized!"));
|
||||
Serial.println(F("Please see the previous example for more information."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// ESF data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getEsfIns()) // Poll new ESF INS data
|
||||
{
|
||||
Serial.print(F("X Ang Rate: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.xAngRate);
|
||||
Serial.print(F(" Y Ang Rate: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.yAngRate);
|
||||
Serial.print(F(" Z Ang Rate: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.zAngRate);
|
||||
Serial.print(F(" X Accel: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.xAccel);
|
||||
Serial.print(F(" Y Accel: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.yAccel);
|
||||
Serial.print(F(" Z Accel: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.zAccel);
|
||||
|
||||
// These values also have "validity checks" that can be provided by the
|
||||
// ublox library by reading bitfield0
|
||||
Serial.print(F(" Validity: "));
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.bitfield0.bits.xAngRateValid);
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.bitfield0.bits.yAngRateValid);
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.bitfield0.bits.zAngRateValid);
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.bitfield0.bits.xAccelValid);
|
||||
Serial.print(myGNSS.packetUBXESFINS->data.bitfield0.bits.yAccelValid);
|
||||
Serial.println(myGNSS.packetUBXESFINS->data.bitfield0.bits.zAccelValid);
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
By: Elias Santistevan
|
||||
SparkFun Electronics
|
||||
Date: May, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
After calibrating the module, also known as "Fusion Mode", you can get
|
||||
data directly from the IMU. This example code walks you through trouble
|
||||
shooting or identifying the different states of any individual
|
||||
"external" (which include internal) sensors you've hooked up (vehicle speed
|
||||
sensor) or the internal IMU used by the modules. You can see if the sensor is
|
||||
being used, if it's calibrated, ready, what data type it returns, the state
|
||||
of the measurement etc.
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// GetEsfInfo also gets the number of sensors used by the ublox module, this
|
||||
// includes (in the case of the ZED-F9R) wheel tick input from the vehicle
|
||||
// speed sensor attached to the module.
|
||||
if (myGNSS.getEsfInfo()){
|
||||
|
||||
Serial.print(F("Fusion Mode: "));
|
||||
Serial.println(myGNSS.packetUBXESFSTATUS->data.fusionMode);
|
||||
|
||||
if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 1){
|
||||
Serial.println(F("Fusion Mode is Initialized!"));
|
||||
}
|
||||
else {
|
||||
Serial.println(F("Fusion Mode is either disabled or not initialized!"));
|
||||
Serial.println(F("Please see the previous example for more information."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// ESF data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getEsfInfo()) // Poll new ESF STATUS data
|
||||
{
|
||||
UBX_ESF_STATUS_sensorStatus_t sensorStatus; // Create storage for the individual sensor status
|
||||
|
||||
//See ublox receiver description or our hookup guide for information on the return values
|
||||
|
||||
Serial.println(F(" "));
|
||||
Serial.println(F(" C "));
|
||||
Serial.println(F(" a "));
|
||||
Serial.println(F(" l "));
|
||||
Serial.println(F(" i "));
|
||||
Serial.println(F(" b M "));
|
||||
Serial.println(F(" r i N"));
|
||||
Serial.println(F(" a B s o"));
|
||||
Serial.println(F(" S t T B a s i"));
|
||||
Serial.println(F("S e B i i a d e s"));
|
||||
Serial.println(F("e n e o m d d y"));
|
||||
Serial.println(F("n s i I n e T "));
|
||||
Serial.println(F("s o n s M i M M"));
|
||||
Serial.println(F("o r g S S e m e e"));
|
||||
Serial.println(F("r R t t a e a a"));
|
||||
Serial.println(F(" T U e a a s s s"));
|
||||
Serial.println(F("N y s a t t u T u u"));
|
||||
Serial.println(F("o p e d u u r a r r"));
|
||||
Serial.println(F(". e d y s s e g e e"));
|
||||
Serial.println(F(" "));
|
||||
|
||||
for(uint8_t i = 0; i < myGNSS.packetUBXESFSTATUS->data.numSens; i++)
|
||||
{
|
||||
myGNSS.getSensorFusionStatus(&sensorStatus, i); // Extract the individual sensor data for this sensor
|
||||
|
||||
Serial.print(i); Serial.print(F(" ")); // Print the sensor number
|
||||
|
||||
// Print the sensor type
|
||||
Serial.print(sensorStatus.sensStatus1.bits.type);
|
||||
if (sensorStatus.sensStatus1.bits.type < 10) Serial.print(F(" "));
|
||||
Serial.print(F(" "));
|
||||
|
||||
Serial.print(sensorStatus.sensStatus1.bits.used); Serial.print(F(" ")); // Print the used flag
|
||||
Serial.print(sensorStatus.sensStatus1.bits.ready); Serial.print(F(" ")); // Print the ready flag
|
||||
|
||||
Serial.print(sensorStatus.sensStatus2.bits.calibStatus); Serial.print(F(" ")); // Print the calibration status
|
||||
Serial.print(sensorStatus.sensStatus2.bits.timeStatus); Serial.print(F(" ")); // Print the time status
|
||||
|
||||
Serial.print(sensorStatus.faults.bits.badMeas); Serial.print(F(" ")); // Print the bad measurement flag
|
||||
Serial.print(sensorStatus.faults.bits.badTTag); Serial.print(F(" ")); // Print the time tag flag
|
||||
Serial.print(sensorStatus.faults.bits.missingMeas); Serial.print(F(" ")); // Print the missing measurement flag
|
||||
Serial.print(sensorStatus.faults.bits.noisyMeas); // Print the noisy measure flag
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
By: Elias Santistevan
|
||||
SparkFun Electronics
|
||||
Date: May, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
getEsfAlignment (UBX-ESF-ALG) reports the status and alignment angles of the IMU within the vehicle.
|
||||
These define the rotation of the IMU frame within the vehicle (installation frame) - not the heading
|
||||
of the vehicle itself. The vehicle attitude solution is reported separately by getNAVATT (UBX-NAV-ATT).
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
myGNSS.setESFAutoAlignment(true); //Enable Automatic IMU-mount Alignment
|
||||
|
||||
if (myGNSS.getEsfInfo()){
|
||||
|
||||
Serial.print(F("Fusion Mode: "));
|
||||
Serial.println(myGNSS.packetUBXESFSTATUS->data.fusionMode);
|
||||
|
||||
if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 1){
|
||||
Serial.println(F("Fusion Mode is Initialized!"));
|
||||
}
|
||||
else {
|
||||
Serial.println(F("Fusion Mode is either disabled or not initialized!"));
|
||||
Serial.println(F("Please see the previous example for more information."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// ESF data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getEsfAlignment()) // Poll new ESF ALG data
|
||||
{
|
||||
Serial.print(F("IMU-Mount Alignment: On/Off: "));
|
||||
Serial.print(myGNSS.packetUBXESFALG->data.flags.bits.autoMntAlgOn);
|
||||
Serial.print(F(" Status: "));
|
||||
Serial.print(myGNSS.packetUBXESFALG->data.flags.bits.status);
|
||||
Serial.print(F(" Roll: "));
|
||||
Serial.print(myGNSS.getESFroll(), 2); // Use the helper function to get the roll in degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print(myGNSS.getESFpitch(), 2); // Use the helper function to get the pitch in degrees
|
||||
Serial.print(F(" Yaw: "));
|
||||
Serial.print(myGNSS.getESFyaw(), 2); // Use the helper function to get the yaw in degrees
|
||||
Serial.print(F(" Errors: "));
|
||||
Serial.print(myGNSS.packetUBXESFALG->data.error.bits.tiltAlgError);
|
||||
Serial.print(myGNSS.packetUBXESFALG->data.error.bits.yawAlgError);
|
||||
Serial.println(myGNSS.packetUBXESFALG->data.error.bits.angleError);
|
||||
}
|
||||
|
||||
if (myGNSS.getNAVATT()) // Poll new NAV ATT data
|
||||
{
|
||||
Serial.print(F("Vehicle Attitude: Roll: "));
|
||||
Serial.print(myGNSS.getATTroll(), 2); // Use the helper function to get the roll in degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print(myGNSS.getATTpitch(), 2); // Use the helper function to get the pitch in degrees
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.println(myGNSS.getATTheading(), 2); // Use the helper function to get the heading in degrees
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the High Navigation Rate on the NEO-M8U and then
|
||||
polls and displays the attitude solution, vehicle dynamics information
|
||||
and high rate position, velocity and time.
|
||||
|
||||
This example polls the high rate data.
|
||||
(The next example uses "autoHNR" to receive the HNR data automatically.)
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("Warning! u-blox GPS did not begin correctly."));
|
||||
Serial.println(F("(This may be because the I2C port is busy with HNR messages.)"));
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
if (myGNSS.setHNRNavigationRate(10) == true) //Set the High Navigation Rate to 10Hz
|
||||
Serial.println(F("setHNRNavigationRate was successful"));
|
||||
else
|
||||
Serial.println(F("setHNRNavigationRate was NOT successful"));
|
||||
|
||||
myGNSS.setAutoHNRATT(false); //Make sure auto HNR attitude messages are disabled
|
||||
myGNSS.setAutoHNRINS(false); //Make sure auto HNR vehicle dynamics messages are disabled
|
||||
myGNSS.setAutoHNRPVT(false); //Make sure auto HNR PVT messages are disabled
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Poll and print selected HNR data
|
||||
if (myGNSS.getHNRAtt(125) == true) // Request HNR Att data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("Roll: "));
|
||||
Serial.print(myGNSS.getHNRroll(), 2); // Use the helper function to get the roll in degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print(myGNSS.getHNRpitch(), 2); // Use the helper function to get the pitch in degrees
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.println(myGNSS.getHNRheading(), 2); // Use the helper function to get the heading in degrees
|
||||
}
|
||||
if (myGNSS.getHNRDyn(125) == true) // Request HNR Dyn data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("xAccel: "));
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.xAccel);
|
||||
Serial.print(F(" yAccel: "));
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.yAccel);
|
||||
Serial.print(F(" zAccel: "));
|
||||
Serial.println(myGNSS.packetUBXHNRINS->data.zAccel);
|
||||
}
|
||||
if (myGNSS.getHNRPVT(125) == true) // Request HNR PVT data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("ns: "));
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.nano);
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.lat);
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.println(myGNSS.packetUBXHNRPVT->data.lon);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: December, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the High Navigation Rate on the NEO-M8U and then
|
||||
reads and displays the attitude solution, vehicle dynamics information
|
||||
and high rate position, velocity and time.
|
||||
|
||||
This example uses "autoHNR" to receive the HNR data automatically.
|
||||
|
||||
Please make sure your NEO-M8U is running UDR firmware >= 1.31. Please update using u-center if necessary:
|
||||
https://www.u-blox.com/en/product/neo-m8u-module#tab-documentation-resources
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
bool usingAutoHNRAtt = false;
|
||||
bool usingAutoHNRDyn = false;
|
||||
bool usingAutoHNRPVT = false;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("Warning! u-blox GPS did not begin correctly."));
|
||||
Serial.println(F("(This may be because the I2C port is busy with HNR messages.)"));
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
if (myGNSS.setHNRNavigationRate(10) == true) //Set the High Navigation Rate to 10Hz
|
||||
Serial.println(F("setHNRNavigationRate was successful"));
|
||||
else
|
||||
Serial.println(F("setHNRNavigationRate was NOT successful"));
|
||||
|
||||
usingAutoHNRAtt = myGNSS.setAutoHNRATT(true); //Attempt to enable auto HNR attitude messages
|
||||
if (usingAutoHNRAtt)
|
||||
Serial.println(F("AutoHNRATT successful"));
|
||||
|
||||
usingAutoHNRDyn = myGNSS.setAutoHNRINS(true); //Attempt to enable auto HNR vehicle dynamics messages
|
||||
if (usingAutoHNRDyn)
|
||||
Serial.println(F("AutoHNRINS successful"));
|
||||
|
||||
usingAutoHNRPVT = myGNSS.setAutoHNRPVT(true); //Attempt to enable auto HNR PVT messages
|
||||
if (usingAutoHNRPVT)
|
||||
Serial.println(F("AutoHNRPVT successful"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (usingAutoHNRAtt && (myGNSS.getHNRAtt() == true)) // If setAutoHNRAtt was successful and new data is available
|
||||
{
|
||||
Serial.print(F("Roll: ")); // Print selected data
|
||||
Serial.print(myGNSS.getHNRroll(), 2); // Use the helper function to get the roll in degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print(myGNSS.getHNRpitch(), 2); // Use the helper function to get the pitch in degrees
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.println(myGNSS.getHNRheading(), 2); // Use the helper function to get the heading in degrees
|
||||
myGNSS.flushHNRATT(); // Mark data as stale
|
||||
}
|
||||
if (usingAutoHNRDyn && (myGNSS.getHNRDyn() == true)) // If setAutoHNRDyn was successful and new data is available
|
||||
{
|
||||
Serial.print(F("xAccel: ")); // Print selected data
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.xAccel);
|
||||
Serial.print(F(" yAccel: "));
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.yAccel);
|
||||
Serial.print(F(" zAccel: "));
|
||||
Serial.println(myGNSS.packetUBXHNRINS->data.zAccel);
|
||||
myGNSS.flushHNRINS(); // Mark data as stale
|
||||
}
|
||||
if (usingAutoHNRPVT && (myGNSS.getHNRPVT() == true)) // If setAutoHNRPVT was successful and new data is available
|
||||
{
|
||||
Serial.print(F("ns: ")); // Print selected data
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.nano);
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.lat);
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.println(myGNSS.packetUBXHNRPVT->data.lon);
|
||||
myGNSS.flushHNRPVT(); // Mark data as stale
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: August, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example configures the AutoAlignment option for the IMU.
|
||||
The ZED-F9R Integration guide recommends enabling Auto Alignment once
|
||||
the device has been attached to the vehicle's frame.
|
||||
Enabling auto-alignment will cause the the sensor fusion status
|
||||
to begin initialization. After driving around a few turns, the sensors
|
||||
should enter 'Calibrated' state. See example 1 for fusion state or
|
||||
monitor UBX-ESF-STATUS.
|
||||
|
||||
As of writing the ZED-F9R is using HPS v1.2 firmware. Please update using u-center if necessary.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
ZED-F9R pHat: https://www.sparkfun.com/products/16475
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GPS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/17912)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GPS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("Warning! u-blox GPS did not begin correctly."));
|
||||
Serial.println(F("(This may be because the I2C port is busy with HNR messages.)"));
|
||||
}
|
||||
|
||||
bool esfAutoAlignment = myGNSS.getESFAutoAlignment();
|
||||
Serial.print(F("esfAutoAlignment: "));
|
||||
if (esfAutoAlignment == true)
|
||||
Serial.println(F("True"));
|
||||
else
|
||||
Serial.println(F("False"));
|
||||
|
||||
myGNSS.setESFAutoAlignment(true); //Enable UBX-CFG-ESFALG Automatic IMU-mount Alignment
|
||||
|
||||
myGNSS.setAutoHNRATT(false); //Make sure auto HNR attitude messages are disabled
|
||||
myGNSS.setAutoHNRINS(false); //Make sure auto HNR vehicle dynamics messages are disabled
|
||||
myGNSS.setAutoHNRPVT(false); //Make sure auto HNR PVT messages are disabled
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// ESF data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getEsfInfo()) // Poll new ESF STATUS data
|
||||
{
|
||||
Serial.print(F("Fusion Mode: "));
|
||||
Serial.print(myGNSS.packetUBXESFSTATUS->data.fusionMode);
|
||||
if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 0)
|
||||
Serial.println(F(" Sensor is initializing..."));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 1)
|
||||
Serial.println(F(" Sensor is calibrated!"));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 2)
|
||||
Serial.println(F(" Sensor fusion is suspended!"));
|
||||
else if (myGNSS.packetUBXESFSTATUS->data.fusionMode == 3)
|
||||
Serial.println(F(" Sensor fusion is disabled!"));
|
||||
}
|
||||
|
||||
// Poll and print selected HNR data
|
||||
if (myGNSS.getHNRAtt(125) == true) // Request HNR Att data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("Roll: "));
|
||||
Serial.print(myGNSS.getHNRroll(), 2); // Use the helper function to get the roll in degrees
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print(myGNSS.getHNRpitch(), 2); // Use the helper function to get the pitch in degrees
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.println(myGNSS.getHNRheading(), 2); // Use the helper function to get the heading in degrees
|
||||
}
|
||||
if (myGNSS.getHNRDyn(125) == true) // Request HNR Dyn data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("xAccel: "));
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.xAccel);
|
||||
Serial.print(F(" yAccel: "));
|
||||
Serial.print(myGNSS.packetUBXHNRINS->data.yAccel);
|
||||
Serial.print(F(" zAccel: "));
|
||||
Serial.println(myGNSS.packetUBXHNRINS->data.zAccel);
|
||||
}
|
||||
if (myGNSS.getHNRPVT(125) == true) // Request HNR PVT data using a 125ms timeout
|
||||
{
|
||||
Serial.print(F("ns: "));
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.nano);
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(myGNSS.packetUBXHNRPVT->data.lat);
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.println(myGNSS.packetUBXHNRPVT->data.lon);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
By: Paul CLark
|
||||
SparkFun Electronics
|
||||
Date: January, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9R: https://www.sparkfun.com/products/16344
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a Redboard Qwiic
|
||||
If you don't have a platform with a Qwiic connection use the
|
||||
SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
|
||||
After calibrating the module and securing it to your vehicle such that it's
|
||||
stable within 2 degrees, and the board is oriented correctly with regards to
|
||||
the vehicle's frame, you can now read the vehicle's "attitude". The attitude
|
||||
includes the vehicle's heading, pitch, and roll.
|
||||
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// PVAT data is produced at the navigation rate, so by default we'll get fresh data once per second
|
||||
if (myGNSS.getNAVPVAT()) // Poll new PVAT
|
||||
{
|
||||
Serial.print(F("Roll: "));
|
||||
Serial.print((float)myGNSS.getVehicleRoll() / 100000.0, 5); // Use the helper function to get the roll in degrees * 10^-5
|
||||
|
||||
Serial.print(F(" Pitch: "));
|
||||
Serial.print((float)myGNSS.getVehiclePitch() / 100000.0, 5); // Use the helper function to get the pitch in degrees * 10^-5
|
||||
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.print((float)myGNSS.getVehicleHeading() / 100000.0, 5); // Use the helper function to get the heading in degrees * 10^-5
|
||||
|
||||
// We don't have helper functions to extract the roll, pitch and heading valid flags from the PVAT message. But we can do it manually:
|
||||
|
||||
Serial.print(F(" Roll Valid: "));
|
||||
Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehRollValid);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehRollValid = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.print(F(" Pitch Valid: "));
|
||||
Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehPitchValid);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehPitchValid = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.print(F(" Heading Valid: "));
|
||||
Serial.print(myGNSS.packetUBXNAVPVAT->data.flags.bits.vehHeadingValid);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.vehHeadingValid = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
// We don't have helper functions to extract the roll, pitch and heading accuracy from the PVAT message. But we can do it manually:
|
||||
|
||||
Serial.print(F(" Roll Acc: "));
|
||||
Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accRoll) / 100, 2);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accRoll = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.print(F(" Pitch Acc: "));
|
||||
Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accPitch) / 100, 2);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accPitch = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.print(F(" Heading Acc: "));
|
||||
Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.accHeading) / 100, 2);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried2.bits.accHeading = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
// We don't have helper functions to extract the lat and lon from the PVAT message. But we can do it manually:
|
||||
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.lat) / 10000000.0, 7);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.lat = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.print(((float)myGNSS.packetUBXNAVPVAT->data.lon) / 10000000.0, 7);
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.lon = false; // Mark the data as stale
|
||||
myGNSS.packetUBXNAVPVAT->moduleQueried.moduleQueried1.bits.all = false;
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
delay(250);
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Reading two altitudes - Mean Sea Level and Ellipsode
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its lat/long/altitude.
|
||||
|
||||
getAltitude() reports mm above ellipsode model of the globe. There are some
|
||||
instances where altitude above Mean Sea Level is better. This example shows how
|
||||
to use getAltitudeMSL(). The difference varies but is ~20m.
|
||||
Ellipsoid model: https://www.esri.com/news/arcuser/0703/geoid1of3.html
|
||||
Difference between Ellipsoid Model and Mean Sea Level: https://eos-gnss.com/elevation-for-beginners/
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Tracks the passing of 2000ms (2 seconds)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
long altitudeMSL = myGNSS.getAltitudeMSL();
|
||||
Serial.print(F(" AltMSL: "));
|
||||
Serial.print(altitudeMSL);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Send command to reset module over I2C
|
||||
By: Nathan Seidle
|
||||
Date: January 29rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to reset the U-Blox module to factory defaults over I2C.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
while (Serial.available()) Serial.read(); //Trash any incoming chars
|
||||
Serial.println("Press a key to reset module to factory defaults");
|
||||
while (Serial.available() == false) ; //Wait for user to send character
|
||||
|
||||
myGNSS.factoryReset(); //Reset everything: baud rate, I2C address, update rate, everything.
|
||||
|
||||
delay(5000); // Wait while the module restarts
|
||||
|
||||
while (myGNSS.begin() == false) //Attempt to re-connect
|
||||
{
|
||||
delay(1000);
|
||||
Serial.println(F("Attempting to re-connect to u-blox GNSS..."));
|
||||
}
|
||||
|
||||
Serial.println("Unit has now been factory reset. Freezing...");
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Test baud rate changes on serial, factory reset, and hard reset.
|
||||
By: Thorsten von Eicken
|
||||
Date: January 29rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to reset the U-Blox module to factory defaults over serial.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Connect the U-Blox serial port to Serial1
|
||||
If you're using a Uno or don't have a 2nd serial port (Serial1), use SoftwareSerial instead (see below)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
//#define mySerial Serial1 // Uncomment this line to connect via Serial1
|
||||
// - or -
|
||||
SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin.
|
||||
|
||||
#define defaultRate 9600 // Uncomment this line if you are using an M8 - which defaults to 9600 Baud on UART1
|
||||
// - or -
|
||||
//#define defaultRate 38400 // Uncomment this line if you are using an F9 - which defaults to 38400 Baud on UART1
|
||||
|
||||
int state = 0; // steps through auto-baud, reset, etc states
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.print("===== STATE ");
|
||||
Serial.println(state);
|
||||
switch (state) {
|
||||
case 0: // auto-baud connection, then switch to 38400 and save config
|
||||
do {
|
||||
Serial.println("GNSS: trying 38400 baud");
|
||||
mySerial.begin(38400);
|
||||
if (myGNSS.begin(mySerial)) break;
|
||||
|
||||
delay(100);
|
||||
Serial.println("GNSS: trying 9600 baud");
|
||||
mySerial.begin(9600);
|
||||
if (myGNSS.begin(mySerial)) {
|
||||
Serial.println("GNSS: connected at 9600 baud, switching to 38400");
|
||||
myGNSS.setSerialRate(38400);
|
||||
delay(100);
|
||||
} else {
|
||||
delay(2000); //Wait a bit before trying again to limit the Serial output flood
|
||||
}
|
||||
} while(1);
|
||||
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
Serial.println("GNSS serial connected, saved config");
|
||||
state++;
|
||||
break;
|
||||
case 1: // hardReset, expect to see GNSS back at 38400 baud
|
||||
Serial.println("Issuing hardReset (cold start)");
|
||||
myGNSS.hardReset();
|
||||
delay(2000);
|
||||
mySerial.begin(38400);
|
||||
if (myGNSS.begin(mySerial)) {
|
||||
Serial.println("Success.");
|
||||
state++;
|
||||
} else {
|
||||
Serial.println("*** GNSS did not respond at 38400 baud, starting over.");
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
case 2: // factoryReset, expect to see GNSS back at defaultRate baud
|
||||
Serial.println("Issuing factoryReset");
|
||||
myGNSS.factoryReset();
|
||||
delay(5000); // takes more than one second... a loop to resync would be best
|
||||
mySerial.begin(defaultRate);
|
||||
if (myGNSS.begin(mySerial)) {
|
||||
Serial.println("Success.");
|
||||
state++;
|
||||
} else {
|
||||
Serial.println("*** GNSS did not come back at defaultRate baud, starting over.");
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
case 3: // print version info
|
||||
// Note: this may fail on boards like the UNO (ATmega328P) with modules like the ZED-F9P
|
||||
// because getProtocolVersion returns a lot of data - more than the UNO's serial buffer can hold
|
||||
Serial.print("GNSS protocol version: ");
|
||||
Serial.print(myGNSS.getProtocolVersionHigh());
|
||||
Serial.print('.');
|
||||
Serial.println(myGNSS.getProtocolVersionLow());
|
||||
Serial.println("All finished! Freezing...");
|
||||
while(1);
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Reading lat and long via UBX binary commands using UART @38400 baud - free from I2C
|
||||
By: Nathan Seidle, Adapted from Example3_GetPosition by Thorsten von Eicken
|
||||
SparkFun Electronics
|
||||
Date: January 28rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the library and U-Blox for serial port use as well as
|
||||
switching the module from the default 9600 baud to 38400.
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Connect the U-Blox serial TX pin to Uno pin 10
|
||||
Connect the U-Blox serial RX pin to Uno pin 11
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial mySerial(10, 11); // RX, TX. Pin 10 on Uno goes to TX pin on GNSS module.
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount of I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
//Assume that the U-Blox GNSS is running at 9600 baud (the default) or at 38400 baud.
|
||||
//Loop until we're in sync and then ensure it's at 38400 baud.
|
||||
do {
|
||||
Serial.println("GNSS: trying 38400 baud");
|
||||
mySerial.begin(38400);
|
||||
if (myGNSS.begin(mySerial) == true) break;
|
||||
|
||||
delay(100);
|
||||
Serial.println("GNSS: trying 9600 baud");
|
||||
mySerial.begin(9600);
|
||||
if (myGNSS.begin(mySerial) == true) {
|
||||
Serial.println("GNSS: connected at 9600 baud, switching to 38400");
|
||||
myGNSS.setSerialRate(38400);
|
||||
delay(100);
|
||||
} else {
|
||||
//myGNSS.factoryReset();
|
||||
delay(2000); //Wait a bit before trying again to limit the Serial output
|
||||
}
|
||||
} while(1);
|
||||
Serial.println("GNSS serial connected");
|
||||
|
||||
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART port to output UBX only
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over I2C
|
||||
By: Nathan Seidle and Thorsten von Eicken
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the U-Blox GNSS the send navigation reports automatically
|
||||
and retrieving the latest one via getPVT. This eliminates the blocking in getPVT while the GNSS
|
||||
produces a fresh navigation solution at the expense of returning a slighly old solution.
|
||||
|
||||
This can be used over serial or over I2C, this example shows the I2C use. With serial the GNSS
|
||||
simply outputs the UBX_NAV_PVT packet. With I2C it queues it into its internal I2C buffer (4KB in
|
||||
size?) where it can be retrieved in the next I2C poll.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Calling getPVT returns true if there actually is a fresh navigation solution available.
|
||||
// Start the reading only when valid LLH is available
|
||||
if (myGNSS.getPVT() && (myGNSS.getInvalidLlh() == false))
|
||||
{
|
||||
Serial.println();
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
int PDOP = myGNSS.getPDOP();
|
||||
Serial.print(F(" PDOP: "));
|
||||
Serial.print(PDOP);
|
||||
Serial.print(F(" (10^-2)"));
|
||||
|
||||
int nedNorthVel = myGNSS.getNedNorthVel();
|
||||
Serial.print(F(" VelN: "));
|
||||
Serial.print(nedNorthVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int nedEastVel = myGNSS.getNedEastVel();
|
||||
Serial.print(F(" VelE: "));
|
||||
Serial.print(nedEastVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int nedDownVel = myGNSS.getNedDownVel();
|
||||
Serial.print(F(" VelD: "));
|
||||
Serial.print(nedDownVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int verticalAccEst = myGNSS.getVerticalAccEst();
|
||||
Serial.print(F(" VAccEst: "));
|
||||
Serial.print(verticalAccEst);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
int horizontalAccEst = myGNSS.getHorizontalAccEst();
|
||||
Serial.print(F(" HAccEst: "));
|
||||
Serial.print(horizontalAccEst);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
int speedAccEst = myGNSS.getSpeedAccEst();
|
||||
Serial.print(F(" SpeedAccEst: "));
|
||||
Serial.print(speedAccEst);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int headAccEst = myGNSS.getHeadingAccEst();
|
||||
Serial.print(F(" HeadAccEst: "));
|
||||
Serial.print(headAccEst);
|
||||
Serial.print(F(" (degrees * 10^-5)"));
|
||||
|
||||
if (myGNSS.getHeadVehValid() == true) {
|
||||
int headVeh = myGNSS.getHeadVeh();
|
||||
Serial.print(F(" HeadVeh: "));
|
||||
Serial.print(headVeh);
|
||||
Serial.print(F(" (degrees * 10^-5)"));
|
||||
|
||||
int magDec = myGNSS.getMagDec();
|
||||
Serial.print(F(" MagDec: "));
|
||||
Serial.print(magDec);
|
||||
Serial.print(F(" (degrees * 10^-2)"));
|
||||
|
||||
int magAcc = myGNSS.getMagAcc();
|
||||
Serial.print(F(" MagAcc: "));
|
||||
Serial.print(magAcc);
|
||||
Serial.print(F(" (degrees * 10^-2)"));
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over I2C, with explicit data parsing calls
|
||||
By: Nathan Seidle Thorsten von Eicken and Felix Jirka
|
||||
SparkFun Electronics
|
||||
Date: July 1st, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the U-Blox GNSS the send navigation reports automatically
|
||||
and retrieving the latest one via checkUblox when available.
|
||||
This eliminates the implicit update in getPVT when accessing data fields twice.
|
||||
Also this reduces the memory overhead of a separate buffer while introducing a slight error by inconsistencies because of the unsynchronized updates (on a multi core system).
|
||||
|
||||
This can be used over serial or over I2C, this example shows the I2C use. With serial the GNSS
|
||||
simply outputs the UBX_NAV_PVT packet. With I2C it queues it into its internal I2C buffer (4KB in
|
||||
size?) where it can be retrieved in the next I2C poll.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
myGNSS.setAutoPVT(true, false); //Tell the GNSS to "send" each solution and the lib not to update stale data implicitly
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
/*
|
||||
Calling getPVT would return false now (compare to previous example where it would return true), so we just use the data provided
|
||||
If you are using a threaded OS eg. FreeRTOS on an ESP32, the explicit mode of autoPVT allows you to use the data provided on both cores and inside multiple threads
|
||||
The data update in background creates an inconsistent state, but that should not cause issues for most applications as they usually won't change the GNSS location significantly within a 2Hz - 5Hz update rate.
|
||||
Also you could oversample (10Hz - 20Hz) the data to smooth out such issues...
|
||||
*/
|
||||
void loop()
|
||||
{
|
||||
static uint16_t counter = 0;
|
||||
|
||||
if (counter % 10 == 0)
|
||||
{
|
||||
// update your AHRS filter here for a ~100Hz update rate
|
||||
// GNSS data will be quasi static but data from your IMU will be changing
|
||||
}
|
||||
// debug output each half second
|
||||
if (counter % 500 == 0)
|
||||
{
|
||||
Serial.println();
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
// call checkUblox all 50ms to capture the GNSS data
|
||||
if (counter % 50 == 0)
|
||||
{
|
||||
myGNSS.checkUblox();
|
||||
}
|
||||
delay(1);
|
||||
counter++;
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over Serial
|
||||
By: Nathan Seidle, Adapted from Example11 by Felix Jirka
|
||||
SparkFun Electronics
|
||||
Date: July 2nd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the U-Blox GNSS the send navigation reports automatically
|
||||
and retrieving the latest one via getPVT. This eliminates the blocking in getPVT while the GNSS
|
||||
produces a fresh navigation solution at the expense of returning a slighly old solution.
|
||||
|
||||
This can be used over serial or over I2C, this example shows the Serial use. With serial the GNSS
|
||||
simply outputs the UBX_NAV_PVT packet. With I2C it queues it into its internal I2C buffer (4KB in
|
||||
size?) where it can be retrieved in the next I2C poll.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
//#define mySerial Serial2 // Uncomment this line to connect via Serial2
|
||||
// - or -
|
||||
SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin.
|
||||
|
||||
//#define baudRate 9600 // Uncomment this line to select 9600 Baud for the M8
|
||||
// - or -
|
||||
#define baudRate 38400 // Uncomment this line to select 38400 Baud for the F9
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
mySerial.begin(baudRate); // Start the Serial port
|
||||
|
||||
if (myGNSS.begin(mySerial) == false) //Connect to the u-blox module using Serial
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setUART1Output(COM_TYPE_UBX); //Set the UART1 port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// getPVT will return true if there actually is a fresh navigation solution available.
|
||||
// Important note: the PVT message is 100 bytes long. We need to call getPVT often enough
|
||||
// to prevent serial buffer overflows on boards like the original RedBoard / UNO.
|
||||
// At 38400 Baud, the 100 PVT bytes will arrive in 26ms.
|
||||
// On the RedBoard, we need to call getPVT every 5ms to keep up.
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
else
|
||||
{
|
||||
delay(5); // Delay for 5ms only
|
||||
|
||||
static int counter = 0; // Print a dot every 50ms
|
||||
counter++;
|
||||
if (counter > 10)
|
||||
{
|
||||
Serial.print(".");
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
Reading lat and long via UBX binary commands using an RX-only UART
|
||||
By: Nathan Seidle, Adapted from Example11 by Felix Jirka
|
||||
SparkFun Electronics
|
||||
Date: July 2nd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the library for serial port use with a single wire connection using the assumeAutoPVT method.
|
||||
Saving your pins for other stuff :-)
|
||||
|
||||
This example only works correctly if the module has already been configured is sending PVT messages via its UART1 TX pin.
|
||||
Run the previous example to enable the auto PVT messages if you need to.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Preconditions:
|
||||
U-Blox module is configured to send cyclical PVT message
|
||||
|
||||
Hardware Connections:
|
||||
Connect the U-Blox serial TX pin to Rx of Serial2 (default: GPIO16) on your ESP32
|
||||
Or, switch to SoftwareSerial
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
//#define mySerial Serial2 // Uncomment this line to connect via Serial2
|
||||
// - or -
|
||||
SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin.
|
||||
|
||||
//#define baudRate 9600 // Uncomment this line to select 9600 Baud for the M8
|
||||
// - or -
|
||||
#define baudRate 38400 // Uncomment this line to select 38400 Baud for the F9
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
//Use any Serial port with at least a RX Pin connected or a receive only version of SoftwareSerial here
|
||||
//Assume that the U-Blox GNSS is running at baudRate baud
|
||||
mySerial.begin(baudRate);
|
||||
// No need to check return value as internal call to isConnected() will not succeed
|
||||
myGNSS.begin(mySerial);
|
||||
|
||||
// Tell the library we are expecting the module to send PVT messages by itself to our Rx pin.
|
||||
// You can set second parameter to "false" if you want to control the parsing and eviction of the data (need to call checkUblox cyclically)
|
||||
myGNSS.assumeAutoPVT(true, true);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// If implicit updates are enabled, calling getPVT will trigger parsing of the incoming messages
|
||||
// and return true once a PVT message has been parsed.
|
||||
// In case you want to use explicit updates, wrap this in a timer and call checkUblox()
|
||||
// as often as needed, not to overflow your UART buffers.
|
||||
//
|
||||
// Important note: the PVT message is 100 bytes long. We need to call getPVT often enough
|
||||
// to prevent serial buffer overflows on boards like the original RedBoard / UNO.
|
||||
// At 38400 Baud, the 100 PVT bytes will arrive in 26ms.
|
||||
// On the RedBoard, we need to call getPVT every 5ms to keep up.
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
else
|
||||
{
|
||||
delay(5); // Delay for 5ms only
|
||||
|
||||
static int counter = 0; // Print a dot every 50ms
|
||||
counter++;
|
||||
if (counter > 10)
|
||||
{
|
||||
Serial.print(".");
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Debug Output
|
||||
By: Nathan Seidle, Adapted from Example3_GetPosition by Thorsten von Eicken
|
||||
SparkFun Electronics
|
||||
Date: January 28rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the debug output from the library.
|
||||
Debug shows various packet and status outputs. These prints can be directed
|
||||
towards Serial (as in Serial.print) or any other port (Serial1, SerialUSB, etc).
|
||||
|
||||
You can also limit the debug messages to the "critical" ones by adding an extra argument.
|
||||
|
||||
The debug messages can be disabled again by calling disableDebugging()
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
unsigned long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
int counter = 0; // Disable the debug messages when counter reaches 20
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
|
||||
myGNSS.enableDebugging(); //Enable all the debug messages over Serial (default)
|
||||
|
||||
//myGNSS.enableDebugging(SerialUSB); //Enable debug messages over Serial USB
|
||||
|
||||
//myGNSS.enableDebugging(Serial, true); //Enable only the critical debug messages over Serial
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.print(F(" "));
|
||||
Serial.print(myGNSS.getYear());
|
||||
Serial.print(F("-"));
|
||||
Serial.print(myGNSS.getMonth());
|
||||
Serial.print(F("-"));
|
||||
Serial.print(myGNSS.getDay());
|
||||
Serial.print(F(" "));
|
||||
Serial.print(myGNSS.getHour());
|
||||
Serial.print(F(":"));
|
||||
Serial.print(myGNSS.getMinute());
|
||||
Serial.print(F(":"));
|
||||
Serial.println(myGNSS.getSecond());
|
||||
|
||||
Serial.println();
|
||||
|
||||
counter++; // Increment counter
|
||||
if (counter == 20)
|
||||
{
|
||||
myGNSS.disableDebugging(); // Disable the debug messages when counter reaches 20
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Getting time and date using u-blox commands
|
||||
By: davidallenmann
|
||||
SparkFun Electronics
|
||||
Date: April 16th, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for the current time and date. We also
|
||||
turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic
|
||||
dramatically.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
Serial.print(myGNSS.getYear());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getMonth());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getDay());
|
||||
Serial.print(" ");
|
||||
Serial.print(myGNSS.getHour());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getMinute());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getSecond());
|
||||
|
||||
Serial.print(" Time is ");
|
||||
if (myGNSS.getTimeValid() == false)
|
||||
{
|
||||
Serial.print("not ");
|
||||
}
|
||||
Serial.print("valid Date is ");
|
||||
if (myGNSS.getDateValid() == false)
|
||||
{
|
||||
Serial.print("not ");
|
||||
}
|
||||
Serial.print("valid");
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Getting time and date using u-blox commands
|
||||
By: davidallenmann
|
||||
SparkFun Electronics
|
||||
Date: April 16th, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for the current time and date. We also
|
||||
turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic
|
||||
dramatically.
|
||||
|
||||
Note: you will need to set your Serial Monitor to 500000 Baud to see the output
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(500000); //Increase serial speed to maximize
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // Increase I2C clock speed to 400kHz
|
||||
|
||||
//myGNSS.enableDebugging(); //Uncomment this line to enable debug messages over Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(5); //Set output to 5 times a second
|
||||
|
||||
byte rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
|
||||
Serial.print("Current update rate: ");
|
||||
Serial.println(rate);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Calling getPVT returns true if there actually is a fresh navigation solution available.
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.print(myGNSS.getYear());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getMonth());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getDay());
|
||||
Serial.print(" ");
|
||||
Serial.print(myGNSS.getHour());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getMinute());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getSecond());
|
||||
Serial.print(" nanoseconds: ");
|
||||
Serial.print(myGNSS.getNanosecond()); // Nanoseconds can be negative
|
||||
|
||||
myGNSS.flushPVT();
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Getting time and date using u-blox commands
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: April 16th, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to use the Millisecond and Nanosecond output as well as increase the
|
||||
I2C speed (100 to 400kHz), and serial output (115200 to 500kbps).
|
||||
|
||||
Note: you will need to set your Serial Monitor to 500000 Baud to see the output
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(500000); //Increase serial speed to maximize
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); // Increase I2C clock speed to 400kHz
|
||||
|
||||
//myGNSS.enableDebugging(); //Uncomment this line to enable debug messages over Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Note: not all u-blox modules can output solutions at 10Hz - or not while tracking all satellite constellations
|
||||
// If the rate drops back to 1Hz, you're asking too much of your module
|
||||
myGNSS.setNavigationFrequency(10); //Set output to 10 times a second
|
||||
|
||||
byte rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
|
||||
Serial.print("Current update rate:");
|
||||
Serial.println(rate);
|
||||
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Calling getPVT returns true if there actually is a fresh navigation solution available.
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.print(myGNSS.getYear());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getMonth());
|
||||
Serial.print("-");
|
||||
Serial.print(myGNSS.getDay());
|
||||
Serial.print(" ");
|
||||
Serial.print(myGNSS.getHour());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getMinute());
|
||||
Serial.print(":");
|
||||
Serial.print(myGNSS.getSecond());
|
||||
Serial.print(".");
|
||||
//Pretty print leading zeros
|
||||
int mseconds = myGNSS.getMillisecond();
|
||||
if (mseconds < 100)
|
||||
Serial.print("0");
|
||||
if (mseconds < 10)
|
||||
Serial.print("0");
|
||||
Serial.print(mseconds);
|
||||
|
||||
Serial.print(" nanoseconds: ");
|
||||
Serial.print(myGNSS.getNanosecond());
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
u-blox M8 geofence example
|
||||
|
||||
Written by Paul Clark (PaulZC)
|
||||
10th December 2019
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example demonstrates how to use the addGeofence and getGeofenceState functions
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15210
|
||||
ZOE-M8Q: https://www.sparkfun.com/products/15193
|
||||
|
||||
This example powers up the GNSS and reads the fix.
|
||||
Once a valid 3D fix has been found, the code reads the latitude and longitude.
|
||||
The code then sets four geofences around that position with a radii of 5m, 10m, 15m and 20m with 95% confidence.
|
||||
The code then monitors the geofence status.
|
||||
The LED will be illuminated if you are inside the _combined_ geofence (i.e. within the 20m radius).
|
||||
|
||||
This code has been tested on the ZOE-M8Q.
|
||||
*/
|
||||
|
||||
#define LED LED_BUILTIN // Change this if your LED is on a different pin
|
||||
|
||||
#include <Wire.h> // Needed for I2C
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED, OUTPUT);
|
||||
|
||||
// Set up the I2C pins
|
||||
Wire.begin();
|
||||
|
||||
// Start the console serial port
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // Wait for the user to open the serial monitor
|
||||
delay(100);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println(F("u-blox M8 geofence example"));
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
delay(1000); // Let the GNSS power up
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Enable debug messages
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); // Limit I2C output to UBX (disable the NMEA noise)
|
||||
|
||||
Serial.println(F("Waiting for a 3D fix..."));
|
||||
|
||||
byte fixType = 0;
|
||||
|
||||
while (fixType < 3)
|
||||
{
|
||||
fixType = myGNSS.getFixType(); // Get the fix type
|
||||
Serial.print(F("Fix: ")); // Print it
|
||||
Serial.print(fixType);
|
||||
if(fixType == 0) Serial.print(F(" = No fix"));
|
||||
else if(fixType == 1) Serial.print(F(" = Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F(" = 2D"));
|
||||
else if(fixType == 3) Serial.print(F(" = 3D"));
|
||||
else if(fixType == 4) Serial.print(F(" = GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F(" = Time only"));
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println(F("3D fix found!"));
|
||||
|
||||
long latitude = myGNSS.getLatitude(); // Get the latitude in degrees * 10^-7
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude(); // Get the longitude in degrees * 10^-7
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.println(longitude);
|
||||
|
||||
uint32_t radius = 500; // Set the radius to 5m (radius is in m * 10^-2 i.e. cm)
|
||||
|
||||
byte confidence = 2; // Set the confidence level: 0=none, 1=68%, 2=95%, 3=99.7%, 4=99.99%
|
||||
|
||||
// Call clearGeofences() to clear all existing geofences.
|
||||
Serial.print(F("Clearing any existing geofences. clearGeofences returned: "));
|
||||
Serial.println(myGNSS.clearGeofences());
|
||||
|
||||
// It is possible to define up to four geofences.
|
||||
// Call addGeofence up to four times to define them.
|
||||
Serial.println(F("Setting the geofences:"));
|
||||
|
||||
Serial.print(F("addGeofence for geofence 1 returned: "));
|
||||
Serial.println(myGNSS.addGeofence(latitude, longitude, radius, confidence));
|
||||
|
||||
radius = 1000; // 10m
|
||||
Serial.print(F("addGeofence for geofence 2 returned: "));
|
||||
Serial.println(myGNSS.addGeofence(latitude, longitude, radius, confidence));
|
||||
|
||||
radius = 1500; // 15m
|
||||
Serial.print(F("addGeofence for geofence 3 returned: "));
|
||||
Serial.println(myGNSS.addGeofence(latitude, longitude, radius, confidence));
|
||||
|
||||
radius = 2000; // 20m
|
||||
Serial.print(F("addGeofence for geofence 4 returned: "));
|
||||
Serial.println(myGNSS.addGeofence(latitude, longitude, radius, confidence));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
geofenceState currentGeofenceState; // Create storage for the geofence state
|
||||
|
||||
bool result = myGNSS.getGeofenceState(currentGeofenceState);
|
||||
|
||||
Serial.print(F("getGeofenceState returned: ")); // Print the combined state
|
||||
Serial.print(result); // Get the geofence state
|
||||
|
||||
if (!result) // If getGeofenceState did not return true
|
||||
{
|
||||
Serial.println(F(".")); // Tidy up
|
||||
return; // and go round the loop again
|
||||
}
|
||||
|
||||
Serial.print(F(". status is: ")); // Print the status
|
||||
Serial.print(currentGeofenceState.status);
|
||||
|
||||
Serial.print(F(". numFences is: ")); // Print the numFences
|
||||
Serial.print(currentGeofenceState.numFences);
|
||||
|
||||
Serial.print(F(". combState is: ")); // Print the combined state
|
||||
Serial.print(currentGeofenceState.combState);
|
||||
|
||||
if (currentGeofenceState.combState == 0)
|
||||
{
|
||||
Serial.print(F(" = Unknown"));
|
||||
digitalWrite(LED, LOW);
|
||||
}
|
||||
if (currentGeofenceState.combState == 1)
|
||||
{
|
||||
Serial.print(F(" = Inside"));
|
||||
digitalWrite(LED, HIGH);
|
||||
}
|
||||
else if (currentGeofenceState.combState == 2)
|
||||
{
|
||||
Serial.print(F(" = Outside"));
|
||||
digitalWrite(LED, LOW);
|
||||
}
|
||||
|
||||
Serial.print(F(". The individual states are: ")); // Print the state of each geofence
|
||||
for(int i = 0; i < currentGeofenceState.numFences; i++)
|
||||
{
|
||||
if (i > 0) Serial.print(F(","));
|
||||
Serial.print(currentGeofenceState.states[i]);
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Power Save Mode
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: April 22nd, 2020
|
||||
|
||||
Based extensively on Example3_GetPosition
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to put the u-blox module into power save mode and then
|
||||
query its lat/long/altitude. We also turn off the NMEA output on the I2C port.
|
||||
This decreases the amount of I2C traffic dramatically.
|
||||
|
||||
** When it is able to ** the module will reduce its current draw.
|
||||
For the ZOE-M8Q with a passive antenna, you should see the current drop
|
||||
from (approx.) 25-28mA to (approx.) 9mA when power save mode kicks in.
|
||||
|
||||
Note: this will fail on the ZED (protocol version >= 27) as UBX-CFG-RXM is not supported
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Uncomment this line to save the current settings to flash and BBR
|
||||
|
||||
Serial.println("Power save example.");
|
||||
Serial.println("1) Enable power saving");
|
||||
Serial.println("2) Disable power saving");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available())
|
||||
{
|
||||
byte incoming = Serial.read();
|
||||
|
||||
if (incoming == '1')
|
||||
{
|
||||
// Put the GNSS into power save mode
|
||||
// (If you want to disable power save mode, call myGNSS.powerSaveMode(false) instead)
|
||||
// This will fail on the ZED (protocol version >= 27) as UBX-CFG-RXM is not supported
|
||||
if (myGNSS.powerSaveMode()) // Defaults to true
|
||||
Serial.println(F("Power Save Mode enabled."));
|
||||
else
|
||||
Serial.println(F("*** Power Save Mode FAILED ***"));
|
||||
}
|
||||
else if (incoming == '2')
|
||||
{
|
||||
//Go to normal power mode (not power saving mode)
|
||||
if (myGNSS.powerSaveMode(false))
|
||||
Serial.println(F("Power Save Mode disabled."));
|
||||
else
|
||||
Serial.println(F("*** Power Save Disable FAILED ***"));
|
||||
}
|
||||
|
||||
// Read and print the new low power mode
|
||||
uint8_t lowPowerMode = myGNSS.getPowerSaveMode();
|
||||
if (lowPowerMode == 255)
|
||||
{
|
||||
Serial.println(F("*** getPowerSaveMode FAILED ***"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("The low power mode is: "));
|
||||
Serial.print(lowPowerMode);
|
||||
if (lowPowerMode == 0)
|
||||
{
|
||||
Serial.println(F(" (Continuous)"));
|
||||
}
|
||||
else if (lowPowerMode == 1)
|
||||
{
|
||||
Serial.println(F(" (Power Save)"));
|
||||
}
|
||||
else if (lowPowerMode == 4)
|
||||
{
|
||||
Serial.println(F(" (Continuous)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F(" (Unknown!)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Query module every 10 seconds so it is easier to monitor the current draw
|
||||
if (millis() - lastTime > 10000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
byte fixType = myGNSS.getFixType(); // Get the fix type
|
||||
Serial.print(F("Fix: "));
|
||||
Serial.print(fixType);
|
||||
if (fixType == 0)
|
||||
Serial.print(F("(No fix)"));
|
||||
else if (fixType == 1)
|
||||
Serial.print(F("(Dead reckoning)"));
|
||||
else if (fixType == 2)
|
||||
Serial.print(F("(2D)"));
|
||||
else if (fixType == 3)
|
||||
Serial.print(F("(3D)"));
|
||||
else if (fixType == 4)
|
||||
Serial.print(F("(GNSS + Dead reckoning)"));
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F(" Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Set Dynamic Model
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: April 22nd, 2020
|
||||
|
||||
Based extensively on Example3_GetPosition
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to change the u-blox module's dynamic platform model and then
|
||||
query its lat/long/altitude. We also turn off the NMEA output on the I2C port.
|
||||
This decreases the amount of I2C traffic dramatically.
|
||||
|
||||
Possible values for the dynamic model are: PORTABLE, STATIONARY, PEDESTRIAN, AUTOMOTIVE,
|
||||
SEA, AIRBORNE1g, AIRBORNE2g, AIRBORNE4g, WRIST, BIKE
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// If we are going to change the dynamic platform model, let's do it here.
|
||||
// Possible values are:
|
||||
// PORTABLE, STATIONARY, PEDESTRIAN, AUTOMOTIVE, SEA, AIRBORNE1g, AIRBORNE2g, AIRBORNE4g, WRIST, BIKE
|
||||
|
||||
if (myGNSS.setDynamicModel(DYN_MODEL_PORTABLE) == false) // Set the dynamic model to PORTABLE
|
||||
{
|
||||
Serial.println(F("*** Warning: setDynamicModel failed ***"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Dynamic platform model changed successfully!"));
|
||||
}
|
||||
|
||||
// Let's read the new dynamic model to see if it worked
|
||||
uint8_t newDynamicModel = myGNSS.getDynamicModel();
|
||||
if (newDynamicModel == DYN_MODEL_UNKNOWN)
|
||||
{
|
||||
Serial.println(F("*** Warning: getDynamicModel failed ***"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F("The new dynamic model is: "));
|
||||
Serial.println(newDynamicModel);
|
||||
}
|
||||
|
||||
//myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); //Uncomment this line to save only the NAV settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Read NMEA sentences over I2C using u-blox module SAM-M8Q, NEO-M8P, ZED-F9P, etc
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: August 22nd, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example reads the NMEA setences from the u-blox module over I2c and outputs
|
||||
them to the serial port
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
//This will pipe all NMEA sentences to the serial port so we can see them
|
||||
myGNSS.setNMEAOutputPort(Serial);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
Send Custom Command
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: April 20th, 2020
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how you can create and send a custom UBX packet
|
||||
using the SparkFun u-blox library.
|
||||
|
||||
Previously it was possible to create and send a custom packet
|
||||
through the library but it would always appear to timeout as
|
||||
some of the internal functions referred to the internal private
|
||||
struct packetCfg.
|
||||
The most recent version of the library allows sendCommand to
|
||||
use a custom packet as if it were packetCfg and so:
|
||||
- sendCommand will return a sfe_ublox_status_e enum as if
|
||||
it had been called from within the library
|
||||
- the custom packet will be updated with data returned by the module
|
||||
(previously this was not possible from outside the library)
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#define NAV_RATE 5 // The new navigation rate in Hz (measurements per second)
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // You may need to increase this for high navigation rates!
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Let's configure the module's navigation rate as if we were using setNavigationFrequency
|
||||
|
||||
// Let's create our custom packet
|
||||
uint8_t customPayload[MAX_PAYLOAD_SIZE]; // This array holds the payload data bytes. MAX_PAYLOAD_SIZE defaults to 256. The CFG_RATE payload is only 6 bytes!
|
||||
|
||||
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
|
||||
// It is more memory-efficient to call setPacketCfgPayloadSize before .begin (to avoid creating a new buffer, copying across
|
||||
// the contents of the old buffer and then deleting the old buffer). But let's call it here just to prove that we can.
|
||||
myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
|
||||
|
||||
// The next line creates and initialises the packet information which wraps around the payload
|
||||
ubxPacket customCfg = {0, 0, 0, 0, 0, customPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
|
||||
|
||||
// The structure of ubxPacket is:
|
||||
// uint8_t cls : The message Class
|
||||
// uint8_t id : The message ID
|
||||
// uint16_t len : Length of the payload. Does not include cls, id, or checksum bytes
|
||||
// uint16_t counter : Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
|
||||
// uint16_t startingSpot : The counter value needed to go past before we begin recording into payload array
|
||||
// uint8_t *payload : The payload
|
||||
// uint8_t checksumA : Given to us by the module. Checked against the rolling calculated A/B checksums.
|
||||
// uint8_t checksumB
|
||||
// sfe_ublox_packet_validity_e valid : Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
|
||||
// sfe_ublox_packet_validity_e classAndIDmatch : Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
|
||||
|
||||
// sendCommand will return:
|
||||
// SFE_UBLOX_STATUS_DATA_RECEIVED if the data we requested was read / polled successfully
|
||||
// SFE_UBLOX_STATUS_DATA_SENT if the data we sent was writted successfully (ACK'd)
|
||||
// Other values indicate errors. Please see the sfe_ublox_status_e enum for further details.
|
||||
|
||||
// Referring to the u-blox M8 Receiver Description and Protocol Specification we see that
|
||||
// the navigation rate is configured using the UBX-CFG-RATE message. So let's load our
|
||||
// custom packet with the correct information so we can read (poll / get) the current settings.
|
||||
|
||||
customCfg.cls = UBX_CLASS_CFG; // This is the message Class
|
||||
customCfg.id = UBX_CFG_RATE; // This is the message ID
|
||||
customCfg.len = 0; // Setting the len (length) to zero let's us poll the current settings
|
||||
customCfg.startingSpot = 0; // Always set the startingSpot to zero (unless you really know what you are doing)
|
||||
|
||||
// We also need to tell sendCommand how long it should wait for a reply
|
||||
uint16_t maxWait = 250; // Wait for up to 250ms (Serial may need a lot longer e.g. 1100)
|
||||
|
||||
// Now let's read the current navigation rate. The results will be loaded into customCfg.
|
||||
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
|
||||
{
|
||||
Serial.println(F("sendCommand (poll / get) failed! Freezing..."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Referring to the message definition for UBX-CFG-RATE we see that the measurement rate
|
||||
// is stored in payload bytes 0 and 1 as a uint16_t in LSB-first (little endian) format
|
||||
|
||||
uint16_t rate = (customPayload[1] << 8) | customPayload[0]; // Extract the current rate (ms)
|
||||
float f_rate = 1000.0 / ((float)rate); // Convert the navigation rate to Hz (measurements per second)
|
||||
|
||||
// Print the current measurement rate
|
||||
Serial.print(F("The current measurement rate is: "));
|
||||
Serial.println(f_rate, 1);
|
||||
|
||||
// Let's change it
|
||||
rate = 1000 / NAV_RATE; // Load the new value into rate
|
||||
customPayload[0] = rate & 0xFF; // Store it in the payload
|
||||
customPayload[1] = rate >> 8;
|
||||
|
||||
// Print the new measurement rate
|
||||
Serial.print(F("The new measurement rate will be: "));
|
||||
Serial.println(NAV_RATE);
|
||||
|
||||
// We don't need to update customCfg.len as it will have been set to 6
|
||||
// when sendCommand read the data
|
||||
|
||||
// Now we write the custom packet back again to change the setting
|
||||
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) // This time we are only expecting an ACK
|
||||
{
|
||||
Serial.println(F("sendCommand (set) failed! Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Navigation rate updated. Here we go..."));
|
||||
}
|
||||
|
||||
myGNSS.setAutoPVT(true); // Enable AutoPVT. The module will generate measurements automatically without being polled.
|
||||
|
||||
//myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); //Uncomment this line to save only the NAV settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query the module as fast as possible
|
||||
int32_t latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
int32_t longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Lon: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
int32_t altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
uint16_t milliseconds = myGNSS.getMillisecond();
|
||||
Serial.print(F(" Milliseconds: "));
|
||||
Serial.print(milliseconds);
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
Module Info - extracts and prints the full module information from UBX_MON_VER
|
||||
using a custom command.
|
||||
By: @mayopan
|
||||
Date: May 9th, 2020
|
||||
|
||||
Based on:
|
||||
Send Custom Command
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: April 20th, 2020
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
Previously it was possible to create and send a custom packet
|
||||
through the library but it would always appear to timeout as
|
||||
some of the internal functions referred to the internal private
|
||||
struct packetCfg.
|
||||
The most recent version of the library allows sendCommand to
|
||||
use a custom packet as if it were packetCfg and so:
|
||||
- sendCommand will return a sfe_ublox_status_e enum as if
|
||||
it had been called from within the library
|
||||
- the custom packet will be updated with data returned by the module
|
||||
(previously this was not possible from outside the library)
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#define MAX_PAYLOAD_SIZE 384 // Override MAX_PAYLOAD_SIZE for getModuleInfo which can return up to 348 bytes
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
|
||||
// Extend the class for getModuleInfo
|
||||
class SFE_UBLOX_GPS_ADD : public SFE_UBLOX_GNSS
|
||||
{
|
||||
public:
|
||||
bool getModuleInfo(uint16_t maxWait = 1100); //Queries module, texts
|
||||
|
||||
struct minfoStructure // Structure to hold the module info (uses 341 bytes of RAM)
|
||||
{
|
||||
char swVersion[30];
|
||||
char hwVersion[10];
|
||||
uint8_t extensionNo = 0;
|
||||
char extension[10][30];
|
||||
} minfo;
|
||||
};
|
||||
|
||||
SFE_UBLOX_GPS_ADD myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // You may need to increase this for high navigation rates!
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
|
||||
// If we call it after the .begin, the library will attempt to resize the existing 256 byte payload buffer
|
||||
// by creating a new buffer, copying across the contents of the old buffer, and then delete the old buffer.
|
||||
// This uses a lot of RAM and causes the code to fail on the ATmega328P. (We are also allocating another 341 bytes for minfo.)
|
||||
// To keep the code ATmega328P compliant - don't call setPacketCfgPayloadSize after .begin. Call it here instead.
|
||||
myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
Serial.print(F("Polling module info"));
|
||||
if (myGNSS.getModuleInfo(1100) == false) // Try to get the module info
|
||||
{
|
||||
Serial.print(F("getModuleInfo failed! Freezing..."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.println(F("Module Info : "));
|
||||
Serial.print(F("Soft version: "));
|
||||
Serial.println(myGNSS.minfo.swVersion);
|
||||
Serial.print(F("Hard version: "));
|
||||
Serial.println(myGNSS.minfo.hwVersion);
|
||||
Serial.print(F("Extensions:"));
|
||||
Serial.println(myGNSS.minfo.extensionNo);
|
||||
for (int i = 0; i < myGNSS.minfo.extensionNo; i++)
|
||||
{
|
||||
Serial.print(" ");
|
||||
Serial.println(myGNSS.minfo.extension[i]);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(F("Done!"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
bool SFE_UBLOX_GPS_ADD::getModuleInfo(uint16_t maxWait)
|
||||
{
|
||||
myGNSS.minfo.hwVersion[0] = 0;
|
||||
myGNSS.minfo.swVersion[0] = 0;
|
||||
for (int i = 0; i < 10; i++)
|
||||
myGNSS.minfo.extension[i][0] = 0;
|
||||
myGNSS.minfo.extensionNo = 0;
|
||||
|
||||
// Let's create our custom packet
|
||||
uint8_t customPayload[MAX_PAYLOAD_SIZE]; // This array holds the payload data bytes
|
||||
|
||||
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
|
||||
// If we call it here, after the .begin, the library will attempt to resize the existing 256 byte payload buffer
|
||||
// by creating a new buffer, copying across the contents of the old buffer, and then delete the old buffer.
|
||||
// This uses a lot of RAM and causes the code to fail on the ATmega328P. (We are also allocating another 341 bytes for minfo.)
|
||||
// To keep the code ATmega328P compliant - don't call setPacketCfgPayloadSize here. Call it before .begin instead.
|
||||
//myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
|
||||
|
||||
// The next line creates and initialises the packet information which wraps around the payload
|
||||
ubxPacket customCfg = {0, 0, 0, 0, 0, customPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
|
||||
|
||||
// The structure of ubxPacket is:
|
||||
// uint8_t cls : The message Class
|
||||
// uint8_t id : The message ID
|
||||
// uint16_t len : Length of the payload. Does not include cls, id, or checksum bytes
|
||||
// uint16_t counter : Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
|
||||
// uint16_t startingSpot : The counter value needed to go past before we begin recording into payload array
|
||||
// uint8_t *payload : The payload
|
||||
// uint8_t checksumA : Given to us by the module. Checked against the rolling calculated A/B checksums.
|
||||
// uint8_t checksumB
|
||||
// sfe_ublox_packet_validity_e valid : Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
|
||||
// sfe_ublox_packet_validity_e classAndIDmatch : Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
|
||||
|
||||
// sendCommand will return:
|
||||
// SFE_UBLOX_STATUS_DATA_RECEIVED if the data we requested was read / polled successfully
|
||||
// SFE_UBLOX_STATUS_DATA_SENT if the data we sent was writted successfully (ACK'd)
|
||||
// Other values indicate errors. Please see the sfe_ublox_status_e enum for further details.
|
||||
|
||||
// Referring to the u-blox M8 Receiver Description and Protocol Specification we see that
|
||||
// the module information can be read using the UBX-MON-VER message. So let's load our
|
||||
// custom packet with the correct information so we can read (poll / get) the module information.
|
||||
|
||||
customCfg.cls = UBX_CLASS_MON; // This is the message Class
|
||||
customCfg.id = UBX_MON_VER; // This is the message ID
|
||||
customCfg.len = 0; // Setting the len (length) to zero let's us poll the current settings
|
||||
customCfg.startingSpot = 0; // Always set the startingSpot to zero (unless you really know what you are doing)
|
||||
|
||||
// Now let's send the command. The module info is returned in customPayload
|
||||
|
||||
if (sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED)
|
||||
return (false); //If command send fails then bail
|
||||
|
||||
// Now let's extract the module info from customPayload
|
||||
|
||||
uint16_t position = 0;
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
minfo.swVersion[i] = customPayload[position];
|
||||
position++;
|
||||
}
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
minfo.hwVersion[i] = customPayload[position];
|
||||
position++;
|
||||
}
|
||||
|
||||
while (customCfg.len >= position + 30)
|
||||
{
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
minfo.extension[minfo.extensionNo][i] = customPayload[position];
|
||||
position++;
|
||||
}
|
||||
minfo.extensionNo++;
|
||||
if (minfo.extensionNo > 9)
|
||||
break;
|
||||
}
|
||||
|
||||
return (true); //Success!
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Powering off a ublox GNSS module
|
||||
By: bjorn
|
||||
unsurv.org
|
||||
Date: July 20th, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows you how to turn off the ublox module to lower the power consumption.
|
||||
There are two functions: one just specifies a duration in milliseconds the other also specifies a pin on the GNSS device to wake it up with.
|
||||
By driving a voltage from LOW to HIGH or HIGH to LOW on the chosen module pin you wake the device back up.
|
||||
Note: Doing so on the INT0 pin when using the regular powerOff(durationInMs) function will wake the device anyway. (tested on SAM-M8Q)
|
||||
Note: While powered off, you should not query the device for data or it might wake up. This can be used to wake the device but is not recommended.
|
||||
Works best when also putting your microcontroller to sleep.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard.
|
||||
To force the device to wake up you need to connect to a pin (for example INT0) seperately on the module.
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// define a digital pin capable of driving HIGH and LOW
|
||||
#define WAKEUP_PIN 5
|
||||
|
||||
// Possible GNSS interrupt pins for powerOffWithInterrupt are:
|
||||
// VAL_RXM_PMREQ_WAKEUPSOURCE_UARTRX = uartrx
|
||||
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0 = extint0 (default)
|
||||
// VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT1 = extint1
|
||||
// VAL_RXM_PMREQ_WAKEUPSOURCE_SPICS = spics
|
||||
// These values can be or'd (|) together to enable interrupts on multiple pins
|
||||
|
||||
void wakeUp() {
|
||||
|
||||
Serial.print("-- waking up module via pin " + String(WAKEUP_PIN));
|
||||
Serial.println(" on your microcontroller --");
|
||||
|
||||
digitalWrite(WAKEUP_PIN, LOW);
|
||||
delay(1000);
|
||||
digitalWrite(WAKEUP_PIN, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(WAKEUP_PIN, LOW);
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
pinMode(WAKEUP_PIN, OUTPUT);
|
||||
digitalWrite(WAKEUP_PIN, LOW);
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Powering off for 20s, you should see the power consumption drop.
|
||||
Serial.println("-- Powering off module for 20s --");
|
||||
|
||||
myGNSS.powerOff(20000);
|
||||
//myGNSS.powerOffWithInterrupt(20000, VAL_RXM_PMREQ_WAKEUPSOURCE_EXTINT0);
|
||||
|
||||
delay(10000);
|
||||
|
||||
// After 10 seconds wake the device via the specified pin on your microcontroller and module.
|
||||
wakeUp();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Do nothing
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Time Pulse Parameters - Bullet Time (https://en.wikipedia.org/wiki/Bullet_time)
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: January 13th, 2021
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
|
||||
pin to produce a pulse once per second but with an adjustable delay. You could use this to
|
||||
trigger multiple cameras and replicate the "bullet time" effect.
|
||||
|
||||
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
|
||||
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
|
||||
accurate timelapse camera shutter signal? This is the product for you!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Create storage for the time pulse parameters
|
||||
UBX_CFG_TP5_data_t timePulseParameters;
|
||||
|
||||
// Get the time pulse parameters
|
||||
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("getTimePulseParameters failed! Freezing..."));
|
||||
while (1) ; // Do nothing more
|
||||
}
|
||||
|
||||
// Print the CFG TP5 version
|
||||
Serial.print(F("UBX_CFG_TP5 version: "));
|
||||
Serial.println(timePulseParameters.version);
|
||||
|
||||
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
|
||||
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
|
||||
|
||||
// We can configure the time pulse pin to produce a defined frequency or period
|
||||
// Here is how to set the period:
|
||||
|
||||
// Let's say that we want our pulse-per-second to be as accurate as possible. So, let's tell the module
|
||||
// to generate no signal while it is _locking_ to GNSS time. We want the signal to start only when the module is
|
||||
// _locked_ to GNSS time.
|
||||
timePulseParameters.freqPeriod = 0; // Set the frequency/period to zero
|
||||
timePulseParameters.pulseLenRatio = 0; // Set the pulse ratio to zero
|
||||
|
||||
// When the module is _locked_ to GNSS time, make it generate a 0.1 second pulse once per second
|
||||
timePulseParameters.freqPeriodLock = 1000000; // Set the period to 1,000,000 us
|
||||
timePulseParameters.pulseLenRatioLock = 100000; // Set the pulse length to 0.1s (100,000 us)
|
||||
timePulseParameters.flags.bits.polarity = 1; // Set the polarity to "1" (high for 0.1s, low for 0.9s, rising edge at top of second)
|
||||
|
||||
// We can use userConfigDelay to delay the pulse for each camera. The delay needs to be negative for this example.
|
||||
// We can delay the pulse by +/- 2^31 nanoseconds (+/- 2.147 seconds)
|
||||
//timePulseParameters.userConfigDelay = 0; // Camera 1: delay the pulse by 0ns
|
||||
//timePulseParameters.userConfigDelay = -100000000; // Camera 2: delay the pulse by 0.1s (100,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -200000000; // Camera 3: delay the pulse by 0.2s (200,000,000 ns)
|
||||
timePulseParameters.userConfigDelay = -300000000; // Camera 4: delay the pulse by 0.3s (300,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -400000000; // Camera 5: delay the pulse by 0.4s (400,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -500000000; // Camera 6: delay the pulse by 0.5s (500,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -600000000; // Camera 7: delay the pulse by 0.6s (600,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -700000000; // Camera 8: delay the pulse by 0.7s (700,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -800000000; // Camera 9: delay the pulse by 0.8s (800,000,000 ns)
|
||||
//timePulseParameters.userConfigDelay = -900000000; // Camera 10: delay the pulse by 0.9s (900,000,000 ns)
|
||||
|
||||
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
|
||||
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
|
||||
timePulseParameters.flags.bits.isFreq = 0; // Tell the module that we want to set the period (not the frequency)
|
||||
timePulseParameters.flags.bits.isLength = 1; // Tell the module that pulseLenRatio is a length (in us) - not a duty cycle
|
||||
|
||||
// Now set the time pulse parameters
|
||||
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("setTimePulseParameters failed!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Success!"));
|
||||
}
|
||||
|
||||
// Finally, save the time pulse parameters in battery-backed memory so the pulse will automatically restart at power on
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); // Save the configuration
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Time Pulse Parameters - Frequency
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: January 13th, 2021
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
|
||||
pin to produce a 1kHz squarewave
|
||||
|
||||
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
|
||||
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
|
||||
accurate frequency or clock source for your latest project? This is the product for you!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Create storage for the time pulse parameters
|
||||
UBX_CFG_TP5_data_t timePulseParameters;
|
||||
|
||||
// Get the time pulse parameters
|
||||
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("getTimePulseParameters failed! Freezing..."));
|
||||
while (1) ; // Do nothing more
|
||||
}
|
||||
|
||||
// Print the CFG TP5 version
|
||||
Serial.print(F("UBX_CFG_TP5 version: "));
|
||||
Serial.println(timePulseParameters.version);
|
||||
|
||||
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
|
||||
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
|
||||
|
||||
// We can configure the time pulse pin to produce a defined frequency or period
|
||||
// Here is how to set the frequency:
|
||||
|
||||
// While the module is _locking_ to GNSS time, make it generate 2kHz
|
||||
timePulseParameters.freqPeriod = 2000; // Set the frequency/period to 2000Hz
|
||||
timePulseParameters.pulseLenRatio = 0x55555555; // Set the pulse ratio to 1/3 * 2^32 to produce 33:67 mark:space
|
||||
|
||||
// When the module is _locked_ to GNSS time, make it generate 1kHz
|
||||
timePulseParameters.freqPeriodLock = 1000; // Set the frequency/period to 1000Hz
|
||||
timePulseParameters.pulseLenRatioLock = 0x80000000; // Set the pulse ratio to 1/2 * 2^32 to produce 50:50 mark:space
|
||||
|
||||
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
|
||||
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
|
||||
timePulseParameters.flags.bits.isFreq = 1; // Tell the module that we want to set the frequency (not the period)
|
||||
timePulseParameters.flags.bits.isLength = 0; // Tell the module that pulseLenRatio is a ratio / duty cycle (* 2^-32) - not a length (in us)
|
||||
timePulseParameters.flags.bits.polarity = 1; // Tell the module that we want the rising edge at the top of second. (Set to 0 for falling edge.)
|
||||
|
||||
// Now set the time pulse parameters
|
||||
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("setTimePulseParameters failed!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Success!"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Time Pulse Parameters - Period
|
||||
By: Paul Clark (PaulZC)
|
||||
Date: January 13th, 2021
|
||||
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to change the time pulse parameters and configure the TIMEPULSE (PPS)
|
||||
pin to produce a 1 second pulse every 30 seconds. What's really cool is that if you run this
|
||||
example on two GNSS boards, the pulses are precisely synchronised!
|
||||
|
||||
The SparkFun GPS-RTK-SMA Breakout - ZED-F9P (Qwiic) (https://www.sparkfun.com/products/16481)
|
||||
has solder pads which will let you connect an SMA connector to the TIMEPULSE signal. Need an
|
||||
accurate timelapse camera shutter signal? This is the product for you!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include "SparkFun_u-blox_GNSS_Arduino_Library.h" //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Create storage for the time pulse parameters
|
||||
UBX_CFG_TP5_data_t timePulseParameters;
|
||||
|
||||
// Get the time pulse parameters
|
||||
if (myGNSS.getTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("getTimePulseParameters failed! Freezing..."));
|
||||
while (1) ; // Do nothing more
|
||||
}
|
||||
|
||||
// Print the CFG TP5 version
|
||||
Serial.print(F("UBX_CFG_TP5 version: "));
|
||||
Serial.println(timePulseParameters.version);
|
||||
|
||||
timePulseParameters.tpIdx = 0; // Select the TIMEPULSE pin
|
||||
//timePulseParameters.tpIdx = 1; // Or we could select the TIMEPULSE2 pin instead, if the module has one
|
||||
|
||||
// We can configure the time pulse pin to produce a defined frequency or period
|
||||
// Here is how to set the period:
|
||||
|
||||
// Let's say that we want our 1 pulse every 30 seconds to be as accurate as possible. So, let's tell the module
|
||||
// to generate no signal while it is _locking_ to GNSS time. We want the signal to start only when the module is
|
||||
// _locked_ to GNSS time.
|
||||
timePulseParameters.freqPeriod = 0; // Set the frequency/period to zero
|
||||
timePulseParameters.pulseLenRatio = 0; // Set the pulse ratio to zero
|
||||
|
||||
// When the module is _locked_ to GNSS time, make it generate a 1 second pulse every 30 seconds
|
||||
// (Although the period can be a maximum of 2^32 microseconds (over one hour), the upper limit appears to be around 33 seconds)
|
||||
timePulseParameters.freqPeriodLock = 30000000; // Set the period to 30,000,000 us
|
||||
timePulseParameters.pulseLenRatioLock = 1000000; // Set the pulse length to 1,000,000 us
|
||||
|
||||
timePulseParameters.flags.bits.active = 1; // Make sure the active flag is set to enable the time pulse. (Set to 0 to disable.)
|
||||
timePulseParameters.flags.bits.lockedOtherSet = 1; // Tell the module to use freqPeriod while locking and freqPeriodLock when locked to GNSS time
|
||||
timePulseParameters.flags.bits.isFreq = 0; // Tell the module that we want to set the period (not the frequency)
|
||||
timePulseParameters.flags.bits.isLength = 1; // Tell the module that pulseLenRatio is a length (in us) - not a duty cycle
|
||||
timePulseParameters.flags.bits.polarity = 1; // Tell the module that we want the rising edge at the top of second. (Set to 0 for falling edge.)
|
||||
|
||||
// Now set the time pulse parameters
|
||||
if (myGNSS.setTimePulseParameters(&timePulseParameters) == false)
|
||||
{
|
||||
Serial.println(F("setTimePulseParameters failed!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("Success!"));
|
||||
}
|
||||
|
||||
// Finally, save the time pulse parameters in battery-backed memory so the pulse will automatically restart at power on
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_NAVCONF); // Save the configuration
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Getting Unix Epoch Time and micros using u-blox commands
|
||||
By: UT2UH
|
||||
Date: March 31th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for the current time and date as Unix Epoch uint32_t type to avoid time.h dependency.
|
||||
We also turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic dramatically.
|
||||
|
||||
Note: this example works best on modules like the ZED_F9P. Modules like the ZOE_M8Q do not support confirmedTime.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Uncomment the next line if you need to completely reset your module
|
||||
//myGNSS.factoryDefault(); delay(5000); // Reset everything and wait while the module restarts
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
|
||||
Serial.println(F("Compare Unix Epoch given with reference one from https://www.epochconverter.com/"));
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
// getUnixEpoch marks the PVT data as stale so you will get Unix time and PVT time on alternate seconds
|
||||
|
||||
uint32_t us; //microseconds returned by getUnixEpoch()
|
||||
uint32_t epoch = myGNSS.getUnixEpoch();
|
||||
Serial.print(F("Unix Epoch rounded: "));
|
||||
Serial.print(epoch, DEC);
|
||||
epoch = myGNSS.getUnixEpoch(us);
|
||||
Serial.print(F(" Exact Unix Epoch: "));
|
||||
Serial.print(epoch, DEC);
|
||||
Serial.print(F(" micros: "));
|
||||
Serial.println(us, DEC);
|
||||
|
||||
Serial.print(myGNSS.getYear());
|
||||
Serial.print(F("-"));
|
||||
Serial.print(myGNSS.getMonth());
|
||||
Serial.print(F("-"));
|
||||
Serial.print(myGNSS.getDay());
|
||||
Serial.print(F(" "));
|
||||
Serial.print(myGNSS.getHour());
|
||||
Serial.print(F(":"));
|
||||
Serial.print(myGNSS.getMinute());
|
||||
Serial.print(F(":"));
|
||||
Serial.print(myGNSS.getSecond());
|
||||
|
||||
Serial.print(F(" Time is "));
|
||||
if (myGNSS.getTimeFullyResolved() == false)
|
||||
{
|
||||
Serial.print(F("not fully resolved but "));
|
||||
} else {
|
||||
Serial.print(F("fully resolved and "));
|
||||
}
|
||||
if (myGNSS.getTimeValid() == false)
|
||||
{
|
||||
Serial.print(F("not "));
|
||||
}
|
||||
Serial.print(F("valid "));
|
||||
if (myGNSS.getConfirmedTime() == false)
|
||||
{
|
||||
Serial.print(F("but not "));
|
||||
} else {
|
||||
Serial.print(F("and "));
|
||||
}
|
||||
Serial.print(F("confirmed"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.println(SIV);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
Demonstrate get/setMeasurementRate and get/setNavigationRate
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 30th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to slow down the measurement and navigation rates.
|
||||
This should run on any GNSS module but has only been tested on the ZED_F9P and ZOE_M8Q.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
unsigned long lastTime = 0; //Simple local timer. Used to calc the message interval.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Uncomment the next line if you need to completely reset your module
|
||||
//myGNSS.factoryDefault(); delay(5000); // Reset everything and wait while the module restarts
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
// Begin by printing the current measurement rate and navigation rate
|
||||
|
||||
uint16_t rate = myGNSS.getMeasurementRate(); //Get the measurement rate of this module
|
||||
Serial.print("Current measurement interval (ms): ");
|
||||
Serial.println(rate);
|
||||
|
||||
rate = myGNSS.getNavigationRate(); //Get the navigation rate of this module
|
||||
Serial.print("Current navigation ratio (cycles): ");
|
||||
Serial.println(rate);
|
||||
|
||||
// The measurement rate is the elapsed time between GNSS measurements, which defines the rate
|
||||
// e.g. 100 ms => 10 Hz, 1000 ms => 1 Hz, 10000 ms => 0.1 Hz.
|
||||
// Let's set the measurement rate (interval) to 5 seconds = 5000 milliseconds
|
||||
if (myGNSS.setMeasurementRate(5000) == false)
|
||||
{
|
||||
Serial.println(F("Could not set the measurement rate. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// setMeasurementRate will set i2cPollingWait to a quarter of the interval
|
||||
// Let's override that so we can poll the module more frequently and avoid timeouts
|
||||
myGNSS.setI2CpollingWait(25); // Set i2cPollingWait to 25ms
|
||||
|
||||
// The navigation rate is the ratio between the number of measurements and the number of navigation solutions
|
||||
// e.g. 5 means five measurements for every navigation solution. Maximum value is 127
|
||||
// Let's set the navigation rate (ratio) to 12 to produce a solution every minute
|
||||
if (myGNSS.setNavigationRate(12) == false)
|
||||
{
|
||||
Serial.println(F("Could not set the navigation rate. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Read and print the updated measurement rate and navigation rate
|
||||
|
||||
rate = myGNSS.getMeasurementRate(); //Get the measurement rate of this module
|
||||
Serial.print("New measurement interval (ms): ");
|
||||
Serial.println(rate);
|
||||
|
||||
rate = myGNSS.getNavigationRate(); //Get the navigation rate of this module
|
||||
Serial.print("New navigation ratio (cycles): ");
|
||||
Serial.println(rate);
|
||||
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// i2cPollingWait will prevent us from thrashing the I2C bus
|
||||
|
||||
if (myGNSS.getPVT()) //Check for new Position, Velocity, Time data. getPVT returns true if new data is available.
|
||||
{
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
|
||||
//Calculate the interval since the last message
|
||||
Serial.print(F(" Interval: "));
|
||||
Serial.print(((float)(millis() - lastTime)) / 1000.0, 2);
|
||||
Serial.print(F("s"));
|
||||
|
||||
Serial.println();
|
||||
|
||||
lastTime = millis(); //Update lastTime
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Demonstrating how to use "end"
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: April 1st, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to use the end function.
|
||||
End will stop all automatic message processing and free (nearly) all used RAM.
|
||||
The file buffer is deleted (if it exists).
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
|
||||
myGNSS.end(); // Call end now just because we can - it won't do much as we haven't used any automatic messages
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Allocate 128 bytes for file storage - this checks that issue #20 has been resolved
|
||||
// Allocating only 128 bytes will let this code run on the ATmega328P
|
||||
// If your processor has plenty of RAM, you can increase this to something useful like 16KB
|
||||
myGNSS.setFileBufferSize(128);
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.print(F("The file buffer size is: "));
|
||||
Serial.println(myGNSS.getFileBufferSize());
|
||||
|
||||
// Request Position, Velocity, Time
|
||||
// RAM will be allocated for PVT message processing
|
||||
// getPVT will return true is fresh PVT data was received and processed
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(" (mm)"));
|
||||
}
|
||||
|
||||
// Calling end will free the RAM allocated for file storage and PVT processing
|
||||
// Calling end is optional. You can comment the next line if you want to.
|
||||
myGNSS.end();
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Configuring the GNSS to produce multiple messages at different rates
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: April 1st, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the U-Blox GNSS to output multiple messages at different rates:
|
||||
PVT is output every second;
|
||||
POSECEF is output every five seconds;
|
||||
VELNED is output every ten seconds.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setMeasurementRate(1000); //Produce a measurement every 1000ms
|
||||
myGNSS.setNavigationRate(1); //Produce a navigation solution every measurement
|
||||
|
||||
myGNSS.setAutoPVTrate(1); //Tell the GNSS to send the PVT solution every measurement
|
||||
myGNSS.setAutoNAVPOSECEFrate(5); //Tell the GNSS to send each POSECEF solution every 5th measurement
|
||||
myGNSS.setAutoNAVVELNEDrate(10); //Tell the GNSS to send each VELNED solution every 10th measurement
|
||||
//myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Calling getPVT returns true if there actually is a fresh navigation solution available.
|
||||
if (myGNSS.getPVT())
|
||||
{
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(" (mm)"));
|
||||
}
|
||||
|
||||
// Calling getNAVPOSECEF returns true if there actually is a fresh position solution available.
|
||||
if (myGNSS.getNAVPOSECEF())
|
||||
{
|
||||
Serial.print(F("ecefX: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVPOSECEF->data.ecefX / 100.0, 2); // convert ecefX to m
|
||||
|
||||
Serial.print(F(" ecefY: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVPOSECEF->data.ecefY / 100.0, 2); // convert ecefY to m
|
||||
|
||||
Serial.print(F(" ecefZ: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVPOSECEF->data.ecefZ / 100.0, 2); // convert ecefY to m
|
||||
Serial.println(F(" (m)"));
|
||||
|
||||
myGNSS.flushNAVPOSECEF(); //Mark all the data as read/stale so we get fresh data next time
|
||||
}
|
||||
|
||||
// Calling getNAVVELNED returns true if there actually is fresh velocity data available.
|
||||
if (myGNSS.getNAVVELNED())
|
||||
{
|
||||
Serial.print(F("velN: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velN / 100.0, 2); // convert velN to m/s
|
||||
|
||||
Serial.print(F(" velE: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velE / 100.0, 2); // convert velE to m/s
|
||||
|
||||
Serial.print(F(" velD: "));
|
||||
Serial.print((float)myGNSS.packetUBXNAVVELNED->data.velD / 100.0, 2); // convert velD to m/s
|
||||
Serial.println(F(" (m/s)"));
|
||||
|
||||
myGNSS.flushNAVVELNED(); //Mark all the data as read/stale so we get fresh data next time
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
Getting leap second event info as SNTP Leap Indicator, time to a leap second event and the number of leap seconds since GPS epoch
|
||||
By: UT2UH
|
||||
Date: April 14th, 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for the leap second event info to cast to SNTP Leap Indicator enumeration.
|
||||
We also turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic dramatically.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
typedef enum {
|
||||
LI_NO_WARNING, //Time leaping not scheduled
|
||||
LI_LAST_MINUTE_61_SEC, //Last minute has 61 seconds
|
||||
LI_LAST_MINUTE_59_SEC, //Last minute has 59 seconds
|
||||
LI_ALARM_CONDITION //The NTP server's clock not synchronized
|
||||
} ntp_LI_e;
|
||||
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
; //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Uncomment the next line if you need to completely reset your module
|
||||
//myGNSS.factoryDefault(); delay(5000); // Reset everything and wait while the module restarts
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfiguration(); //Optional: Save the current settings to flash and BBR
|
||||
|
||||
Serial.println(F("Compare Unix Epoch given with reference one from https://www.epochconverter.com/"));
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
// getUnixEpoch marks the PVT data as stale so you will get Unix time and PVT time on alternate seconds
|
||||
|
||||
uint32_t us; //microseconds returned by getUnixEpoch()
|
||||
uint32_t epoch = myGNSS.getUnixEpoch();
|
||||
Serial.print(F("Unix Epoch rounded: "));
|
||||
Serial.print(epoch, DEC);
|
||||
epoch = myGNSS.getUnixEpoch(us);
|
||||
Serial.print(F(" Exact Unix Epoch: "));
|
||||
Serial.print(epoch, DEC);
|
||||
Serial.print(F(" micros: "));
|
||||
Serial.println(us, DEC);
|
||||
int32_t timeToLeapSecEvent;
|
||||
ntp_LI_e leapIndicator = (ntp_LI_e)myGNSS.getLeapIndicator(timeToLeapSecEvent);
|
||||
Serial.print(F("NTP LI: "));
|
||||
Serial.print(leapIndicator, DEC);
|
||||
switch (leapIndicator){
|
||||
case LI_NO_WARNING:
|
||||
Serial.print(F(" - No event scheduled"));
|
||||
break;
|
||||
case LI_LAST_MINUTE_61_SEC:
|
||||
Serial.print(F(" - last minute will end at 23:60"));
|
||||
break;
|
||||
case LI_LAST_MINUTE_59_SEC:
|
||||
Serial.print(F(" - last minute will end at 23:58"));
|
||||
break;
|
||||
case LI_ALARM_CONDITION:
|
||||
default:
|
||||
Serial.print(F(" - Unknown (clock not synchronized)"));
|
||||
break;
|
||||
}
|
||||
if (timeToLeapSecEvent < 0)
|
||||
{
|
||||
Serial.print(F(". Time since the last leap second event: "));
|
||||
Serial.println(timeToLeapSecEvent * -1, DEC);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(F(". Time to the next leap second event: "));
|
||||
Serial.println(timeToLeapSecEvent, DEC);
|
||||
}
|
||||
|
||||
sfe_ublox_ls_src_e leapSecSource;
|
||||
Serial.print(F("Leap seconds since GPS Epoch (Jan 6th, 1980): "));
|
||||
Serial.print(myGNSS.getCurrentLeapSeconds(leapSecSource), DEC);
|
||||
switch (leapSecSource){
|
||||
case SFE_UBLOX_LS_SRC_DEFAULT:
|
||||
Serial.print(F(" - hardcoded"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_GLONASS:
|
||||
Serial.print(F(" - derived from GPS and GLONASS time difference"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_GPS:
|
||||
Serial.print(F(" - according to GPS"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_SBAS:
|
||||
Serial.print(F(" - according to SBAS"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_BEIDOU:
|
||||
Serial.print(F(" - according to BeiDou"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_GALILEO:
|
||||
Serial.print(F(" - according to Galileo"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_AIDED:
|
||||
Serial.print(F(" - last minute will end at 23:58"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_CONFIGURED:
|
||||
Serial.print(F(" - as configured)"));
|
||||
break;
|
||||
case SFE_UBLOX_LS_SRC_UNKNOWN:
|
||||
default:
|
||||
Serial.print(F(" - source unknown"));
|
||||
break;
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
Get the jamming state and indication
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 2nd, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to enable the jamming / interference monitor and read the
|
||||
jamming state and information.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("SparkFun u-blox GNSS Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Enable the jamming / interference monitor
|
||||
UBX_CFG_ITFM_data_t jammingConfig; // Create storage for the jamming configuration
|
||||
if (myGNSS.getJammingConfiguration(&jammingConfig)) // Read the jamming configuration
|
||||
{
|
||||
Serial.print(F("The jamming / interference monitor is "));
|
||||
if (jammingConfig.config.bits.enable == 0) // Check if the monitor is already enabled
|
||||
Serial.print(F("not "));
|
||||
Serial.println(F("enabled"));
|
||||
|
||||
if (jammingConfig.config.bits.enable == 0) // Check if the monitor is already enabled
|
||||
{
|
||||
Serial.print(F("Enabling the jamming / interference monitor: "));
|
||||
(jammingConfig.config.bits.enable = 1); // Enable the monitor
|
||||
if (myGNSS.setJammingConfiguration(&jammingConfig)) // Set the jamming configuration
|
||||
Serial.println(F("success"));
|
||||
else
|
||||
Serial.println(F("failed!"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Create storage to hold the hardware status
|
||||
// See the definition of UBX_MON_HW_data_t in u-blox_structs.h for more details
|
||||
UBX_MON_HW_data_t hwStatus;
|
||||
|
||||
if (myGNSS.getHWstatus(&hwStatus)) // Read the hardware status
|
||||
{
|
||||
Serial.println(F("Hardware status (UBX_MON_HW):"));
|
||||
|
||||
Serial.print(F("Jamming state: "));
|
||||
Serial.print(hwStatus.flags.bits.jammingState);
|
||||
if (hwStatus.flags.bits.jammingState == 0)
|
||||
Serial.println(F(" = unknown / disabled"));
|
||||
else if (hwStatus.flags.bits.jammingState == 1)
|
||||
Serial.println(F(" = ok"));
|
||||
else if (hwStatus.flags.bits.jammingState == 2)
|
||||
Serial.println(F(" = warning"));
|
||||
else // if (hwStatus.flags.bits.jammingState == 3)
|
||||
Serial.println(F(" = critical!"));
|
||||
|
||||
Serial.print(F("Noise level: "));
|
||||
Serial.println(hwStatus.noisePerMS);
|
||||
|
||||
Serial.print(F("AGC monitor: "));
|
||||
Serial.println(hwStatus.agcCnt);
|
||||
|
||||
Serial.print(F("CW jamming indicator: "));
|
||||
Serial.println(hwStatus.jamInd);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Create storage to hold the RF information from a ZED-F9
|
||||
// See the definition of UBX_MON_RF_data_t in u-blox_structs.h for more details
|
||||
UBX_MON_RF_data_t rfInformation;
|
||||
|
||||
// Read the RF information from the ZED-F9n. Allow 2 seconds for the data to be returned. Will time out on M8 modules
|
||||
if (myGNSS.getRFinformation(&rfInformation, 2000))
|
||||
{
|
||||
Serial.print(F("The UBX_MON_RF message contains "));
|
||||
Serial.print(rfInformation.header.nBlocks); // Print how many information blocks were returned. Should be 0, 1 or 2
|
||||
Serial.println(F(" information blocks"));
|
||||
|
||||
for (uint8_t block = 0; block < rfInformation.header.nBlocks; block++)
|
||||
{
|
||||
Serial.print(F("Block ID: "));
|
||||
Serial.print(rfInformation.blocks[block].blockId);
|
||||
if (rfInformation.blocks[block].blockId == 0)
|
||||
Serial.println(F(" = L1"));
|
||||
else // if (rfInformation.blocks[block].blockId == 1)
|
||||
Serial.println(F(" = L2 / L5"));
|
||||
|
||||
Serial.print(F("Jamming state: "));
|
||||
Serial.print(rfInformation.blocks[block].flags.bits.jammingState);
|
||||
if (rfInformation.blocks[block].flags.bits.jammingState == 0)
|
||||
Serial.println(F(" = unknown / disabled"));
|
||||
else if (rfInformation.blocks[block].flags.bits.jammingState == 1)
|
||||
Serial.println(F(" = ok"));
|
||||
else if (rfInformation.blocks[block].flags.bits.jammingState == 2)
|
||||
Serial.println(F(" = warning"));
|
||||
else // if (rfInformation.blocks[block].flags.bits.jammingState == 3)
|
||||
Serial.println(F(" = critical!"));
|
||||
|
||||
Serial.print(F("Noise level: "));
|
||||
Serial.println(rfInformation.blocks[block].noisePerMS);
|
||||
|
||||
Serial.print(F("AGC monitor: "));
|
||||
Serial.println(rfInformation.blocks[block].agcCnt);
|
||||
|
||||
Serial.print(F("CW jamming indicator: "));
|
||||
Serial.println(rfInformation.blocks[block].jamInd);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Read NMEA sentences over I2C using u-blox module SAM-M8Q, NEO-M8P, etc
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: August 22nd, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example reads the NMEA characters over I2C and pipes them to MicroNMEA
|
||||
This example will output your current long/lat and satellites in view
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
For more MicroNMEA info see https://github.com/stevemarple/MicroNMEA
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
Go outside! Wait ~25 seconds and you should see your lat/long
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <MicroNMEA.h> //http://librarymanager/All#MicroNMEA
|
||||
char nmeaBuffer[100];
|
||||
MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA); //Set the I2C port to output both NMEA and UBX messages
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setProcessNMEAMask(SFE_UBLOX_FILTER_NMEA_ALL); // Make sure the library is passing all NMEA messages to processNMEA
|
||||
|
||||
myGNSS.setProcessNMEAMask(SFE_UBLOX_FILTER_NMEA_GGA); // Or, we can be kind to MicroNMEA and _only_ pass the GGA messages to it
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
if(nmea.isValid() == true)
|
||||
{
|
||||
long latitude_mdeg = nmea.getLatitude();
|
||||
long longitude_mdeg = nmea.getLongitude();
|
||||
|
||||
Serial.print("Latitude (deg): ");
|
||||
Serial.println(latitude_mdeg / 1000000., 6);
|
||||
Serial.print("Longitude (deg): ");
|
||||
Serial.println(longitude_mdeg / 1000000., 6);
|
||||
|
||||
nmea.clear(); // Clear the MicroNMEA storage to make sure we are getting fresh data
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Waiting for fresh data");
|
||||
}
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
||||
//This function gets called from the SparkFun u-blox Arduino Library
|
||||
//As each NMEA character comes in you can specify what to do with it
|
||||
//Useful for passing to other libraries like tinyGPS, MicroNMEA, or even
|
||||
//a buffer, radio, etc.
|
||||
void SFE_UBLOX_GNSS::processNMEA(char incoming)
|
||||
{
|
||||
//Take the incoming char from the u-blox I2C port and pass it on to the MicroNMEA lib
|
||||
//for sentence cracking
|
||||
nmea.process(incoming);
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
NEO-D9S L-Band receiver example
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: March 7th, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to display the NEO-D9S's received signal imbalance and magnitude, plus a summary of any received PMP data.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
NEO-D9S Correction Data Receiver: https://www.sparkfun.com/products/19390
|
||||
|
||||
Hardware Connections:
|
||||
Use a Qwiic cable to connect the NEO-D9S L-Band corection data receiver to your board
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myLBand; // NEO-D9S
|
||||
|
||||
const uint32_t myLBandFreq = 1556290000; // Uncomment this line to use the US SPARTN 1.8 service
|
||||
//const uint32_t myLBandFreq = 1545260000; // Uncomment this line to use the EU SPARTN 1.8 service
|
||||
|
||||
#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printRXMPMP will be called when new PMP data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXM_PMP_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setRXMPMPcallbackPtr
|
||||
// / _____ This _must_ be UBX_RXM_PMP_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printRXMPMP(UBX_RXM_PMP_data_t *pmpData)
|
||||
{
|
||||
Serial.println(F("New PMP data received:"));
|
||||
|
||||
Serial.print(F("PMP message version: "));
|
||||
Serial.println(pmpData->version);
|
||||
|
||||
Serial.print(F("numBytesUserData : "));
|
||||
Serial.println(pmpData->numBytesUserData);
|
||||
|
||||
Serial.print(F("serviceIdentifier: 0x"));
|
||||
Serial.println(pmpData->serviceIdentifier, HEX);
|
||||
|
||||
Serial.print(F("uniqueWordBitErrors: "));
|
||||
Serial.println(pmpData->uniqueWordBitErrors);
|
||||
|
||||
Serial.print(F("fecBits: "));
|
||||
Serial.println(pmpData->fecBits);
|
||||
|
||||
Serial.print(F("ebno (dB): "));
|
||||
Serial.println((double)pmpData->ebno / 8, 3); //Convert ebno to dB
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("NEO-D9S Example"));
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Begin and configure the NEO-D9S L-Band receiver
|
||||
|
||||
//myLBand.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
while (myLBand.begin(Wire, 0x43) == false) //Connect to the u-blox NEO-D9S using Wire port. The D9S default I2C address is 0x43 (not 0x42)
|
||||
{
|
||||
Serial.println(F("u-blox NEO-D9S not detected at default I2C address. Please check wiring."));
|
||||
delay(2000);
|
||||
}
|
||||
Serial.println(F("u-blox NEO-D9S connected"));
|
||||
|
||||
uint8_t ok = myLBand.setVal32(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz
|
||||
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1
|
||||
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821
|
||||
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1
|
||||
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0
|
||||
if (ok) ok = myLBand.setVal64(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull);
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_UART2OUTPROT_UBX, 1); // Enable UBX output on UART2
|
||||
if (ok) ok = myLBand.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2
|
||||
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default
|
||||
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default
|
||||
|
||||
Serial.print(F("L-Band: configuration "));
|
||||
Serial.println(OK(ok));
|
||||
|
||||
myLBand.softwareResetGNSSOnly(); // Do a restart
|
||||
|
||||
myLBand.setRXMPMPcallbackPtr(&printRXMPMP); // Call printRXMPMP when new PMP data arrives
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
myLBand.checkUblox(); // Check for the arrival of new PMP data and process it.
|
||||
myLBand.checkCallbacks(); // Check if any LBand callbacks are waiting to be processed.
|
||||
|
||||
UBX_MON_HW2_data_t hwStatus; // Create storage for the HW2 extended hardware status
|
||||
if (myLBand.getHW2status(&hwStatus)) // Request the extended hardware status
|
||||
{
|
||||
// Print the signal imbalance and magnitude
|
||||
Serial.print(F("Signal imbalance and magnitude: ofsI: "));
|
||||
Serial.print(hwStatus.ofsI);
|
||||
Serial.print(F(" magI: "));
|
||||
Serial.print(hwStatus.magI);
|
||||
Serial.print(F(" ofsQ: "));
|
||||
Serial.print(hwStatus.ofsQ);
|
||||
Serial.print(F(" magQ: "));
|
||||
Serial.println(hwStatus.magQ);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
Calculating the Great Circle Distance and Course to a target position
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: September 21st, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its latitude/longitude and then
|
||||
calculate the Great Circle Distance and Course to a target location.
|
||||
|
||||
Thanks! distanceBetween and courseTo were taken from Mikal Hart's TinyGPSPlus:
|
||||
https://github.com/mikalhart/TinyGPSPlus/blob/ca29434514a5c5172bd807af0608df7f296582a2/src/TinyGPS%2B%2B.cpp#L285-L328
|
||||
|
||||
Note: Lat/Long are large numbers because they are degrees * 10^-7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
//#include <math.h> //Uncomment if required. May be needed for sqrt, atan2, etc..
|
||||
|
||||
double distanceBetween(long lat1_l, long long1_l, long lat2_l, long long2_l)
|
||||
{
|
||||
// returns distance in meters between two positions, both specified
|
||||
// as signed decimal-degrees latitude and longitude. Uses great-circle
|
||||
// distance computation for hypothetical sphere of radius 6372795 meters.
|
||||
// Because Earth is no exact sphere, rounding errors may be up to 0.5%.
|
||||
// Courtesy of Maarten Lamers
|
||||
double lat1 = (double)lat1_l / 10000000.0; // Convert lat and long to degrees
|
||||
double long1 = (double)long1_l / 10000000.0;
|
||||
double lat2 = (double)lat2_l / 10000000.0;
|
||||
double long2 = (double)long2_l / 10000000.0;
|
||||
double delta = radians(long1-long2);
|
||||
double sdlong = sin(delta);
|
||||
double cdlong = cos(delta);
|
||||
lat1 = radians(lat1);
|
||||
lat2 = radians(lat2);
|
||||
double slat1 = sin(lat1);
|
||||
double clat1 = cos(lat1);
|
||||
double slat2 = sin(lat2);
|
||||
double clat2 = cos(lat2);
|
||||
delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
|
||||
delta = sq(delta);
|
||||
delta += sq(clat2 * sdlong);
|
||||
delta = sqrt(delta);
|
||||
double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
|
||||
delta = atan2(delta, denom);
|
||||
return delta * 6372795;
|
||||
}
|
||||
|
||||
double courseTo(long lat1_l, long long1_l, long lat2_l, long long2_l)
|
||||
{
|
||||
// returns course in degrees (North=0, West=270) from position 1 to position 2,
|
||||
// both specified as signed decimal-degrees latitude and longitude.
|
||||
// Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
|
||||
// Courtesy of Maarten Lamers
|
||||
double lat1 = (double)lat1_l / 10000000.0; // Convert lat and long to degrees
|
||||
double long1 = (double)long1_l / 10000000.0;
|
||||
double lat2 = (double)lat2_l / 10000000.0;
|
||||
double long2 = (double)long2_l / 10000000.0;
|
||||
double dlon = radians(long2-long1);
|
||||
lat1 = radians(lat1);
|
||||
lat2 = radians(lat2);
|
||||
double a1 = sin(dlon) * cos(lat2);
|
||||
double a2 = sin(lat1) * cos(lat2) * cos(dlon);
|
||||
a2 = cos(lat1) * sin(lat2) - a2;
|
||||
a2 = atan2(a1, a2);
|
||||
if (a2 < 0.0)
|
||||
{
|
||||
a2 += TWO_PI;
|
||||
}
|
||||
return degrees(a2);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.println(F(" (degrees * 10^-7)"));
|
||||
|
||||
static const long TARGET_LAT = 400909142, TARGET_LON = -1051849833; // SparkFun's location: degrees * 10^-7 (40.091 N, 105.185 W)
|
||||
|
||||
double distanceToTarget = distanceBetween(
|
||||
latitude,
|
||||
longitude,
|
||||
TARGET_LAT,
|
||||
TARGET_LON);
|
||||
|
||||
Serial.print(F("Distance to target: "));
|
||||
Serial.print(distanceToTarget, 2);
|
||||
Serial.print(F(" (m) "));
|
||||
|
||||
double courseToTarget = courseTo(
|
||||
latitude,
|
||||
longitude,
|
||||
TARGET_LAT,
|
||||
TARGET_LON);
|
||||
|
||||
Serial.print(F("Course to target: "));
|
||||
Serial.print(courseToTarget, 1);
|
||||
Serial.println(F(" (degrees)"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
NEO-D9C QZSS-L6 receiver example
|
||||
By: SparkFun Electronics / Paul Clark
|
||||
Date: September 23rd, 2022
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to display a summary of the NEO-D9C's UBX-RXM-QZSSL6 data.
|
||||
It also enables UBX-RXM-QZSSL6 message output on both UART1 and UART2 at 38400 baud
|
||||
so you can feed the corrections directly to (e.g.) a ZED-F9P.
|
||||
|
||||
We believe the NEO-D9C's I2C address should be 0x43 (like the NEO-D9S). But, reported by users in Japan,
|
||||
the initial NEO-D9C's use address 0x42 - which is the same as the ZED-F9P.
|
||||
|
||||
If you have one of the initial NEO-D9C's, the address 0x42 should work for you.
|
||||
If you have a newer or upgraded NEO-D9C, then you may need to change to 0x43. See line 100.
|
||||
|
||||
Also, again reported by users in Japan, the initial NEO-D9C's do not support UBX-CFG-PRT.
|
||||
The library uses UBX-CFG-PRT inside .begin (.isConnected) to check if the module is connected.
|
||||
This then fails with the initial NEO-D9C's.
|
||||
The work-around is to set the .begin assumeSuccess parameter to true.
|
||||
With newer NEO-D9C's this work-around may not be necessary. Again see line 100.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||
NEO-D9S L-Band Correction Data Receiver: https://www.sparkfun.com/products/19390
|
||||
|
||||
Hardware Connections:
|
||||
Use a Qwiic cable to connect the NEO-D9C QZSS-L6 corection data receiver to your board
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myQZSS; // NEO-D9C
|
||||
|
||||
#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
// Callback: printRXMQZSSL6 will be called when new QZSS-L6 data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_RXM_QZSSL6_message_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setRXMQZSSL6messageCallbackPtr
|
||||
// / _____ This _must_ be UBX_RXM_QZSSL6_message_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printRXMQZSSL6(UBX_RXM_QZSSL6_message_data_t *qzssL6Data)
|
||||
{
|
||||
Serial.println(F("New QZSS-L6 data received:"));
|
||||
|
||||
Serial.print(F("Message version: "));
|
||||
Serial.println(qzssL6Data->payload[0]);
|
||||
|
||||
Serial.print(F("Satellite Identifier: "));
|
||||
Serial.println(qzssL6Data->payload[1]);
|
||||
|
||||
Serial.print(F("Carrier / Noise: "));
|
||||
double cno = (0.00390625 * ((double)qzssL6Data->payload[2])) + ((double)qzssL6Data->payload[3]);
|
||||
Serial.println(cno, 1);
|
||||
|
||||
Serial.print(F("Bit Errors Corrected: "));
|
||||
Serial.println(qzssL6Data->payload[9]);
|
||||
|
||||
uint16_t chInfo = (((uint16_t)qzssL6Data->payload[11]) << 8) | qzssL6Data->payload[10];
|
||||
uint16_t errStatus = ((chInfo >> 12) & 0x3);
|
||||
Serial.print(F("Receiver Channel: "));
|
||||
Serial.println((chInfo >> 8) & 0x3);
|
||||
Serial.print(F("Message Name: L6"));
|
||||
Serial.println(((chInfo >> 10) & 0x1) == 0 ? F("D") : F("E"));
|
||||
Serial.print(F("Error Status: "));
|
||||
if (errStatus == 1)
|
||||
Serial.println("error-free");
|
||||
else if (errStatus == 2)
|
||||
Serial.println("erroneous");
|
||||
else
|
||||
Serial.println("unknown");
|
||||
Serial.print(F("Channel Name: "));
|
||||
Serial.println(((chInfo >> 14) & 0x3) == 0 ? F("A") : F("B"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("NEO-D9C Example"));
|
||||
|
||||
Wire.begin(); //Start I2C
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
// Begin and configure the NEO-D9C QZSS-L6 receiver
|
||||
|
||||
//myQZSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
// For the initial NEO-D9C's: connect using address 0x42; set the assumeSuccess parameter to true
|
||||
while (myQZSS.begin(Wire, 0x42, 1100, true) == false)
|
||||
// For newer NEO-D9C's: use address 0x43; leave assumeSuccess set to false (default)
|
||||
//while (myQZSS.begin(Wire, 0x43) == false)
|
||||
{
|
||||
Serial.println(F("u-blox NEO-D9C not detected at selected I2C address. Please check wiring and I2C address."));
|
||||
delay(2000);
|
||||
}
|
||||
Serial.println(F("u-blox NEO-D9C connected"));
|
||||
|
||||
uint8_t ok = myQZSS.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_I2C, 1); // Output QZSS-L6 message on the I2C port
|
||||
|
||||
Serial.print(F("QZSS-L6: I2C configuration "));
|
||||
Serial.println(OK(ok));
|
||||
|
||||
if (ok) ok = myQZSS.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_UART1, 1); // Output QZSS-L6 message on UART1
|
||||
if (ok) ok = myQZSS.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // Match UART1 baudrate with ZED
|
||||
|
||||
Serial.print(F("QZSS-L6: UART1 configuration "));
|
||||
Serial.println(OK(ok));
|
||||
|
||||
if (ok) ok = myQZSS.setVal8(UBLOX_CFG_UART2OUTPROT_UBX, 1); // Enable UBX output on UART2
|
||||
if (ok) ok = myQZSS.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_QZSSL6_UART2, 1); // Output QZSS-L6 message on UART2
|
||||
if (ok) ok = myQZSS.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // Match UART2 baudrate with ZED
|
||||
|
||||
Serial.print(F("QZSS-L6: UART2 configuration "));
|
||||
Serial.println(OK(ok));
|
||||
|
||||
myQZSS.setRXMQZSSL6messageCallbackPtr(&printRXMQZSSL6); // Call printRXMQZSSL6 when new QZSS-L6 data arrives
|
||||
}
|
||||
|
||||
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
void loop()
|
||||
{
|
||||
myQZSS.checkUblox(); // Check for the arrival of new QZSS-L6 data and process it.
|
||||
myQZSS.checkCallbacks(); // Check if any QZSS-L6 callbacks are waiting to be processed.
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
Configure Time & Frequency Sync manager (UBX-CFG-SMGR)
|
||||
By: Danylo Ulianych
|
||||
SparkFun Electronics
|
||||
Date: March 6th, 2024
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example reads / sets UBX-CFG-SMGR configuration and prints UBX-TIM-SMEAS messages.
|
||||
Works only with Time & Frequency Sync products like LEA-M8F, etc.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
|
||||
// Callback: printTIMSMEASdata will be called when new TIM SMEA data arrives
|
||||
// See u-blox_structs.h for the full definition of UBX_TIM_SMEAS_data_t
|
||||
// _____ You can use any name you like for the callback. Use the same name when you call setAutoTIMTM2callback
|
||||
// / _____ This _must_ be UBX_TIM_SMEAS_data_t
|
||||
// | / _____ You can use any name you like for the struct
|
||||
// | | /
|
||||
// | | |
|
||||
void printTIMSMEASdata(UBX_TIM_SMEAS_data_t smea)
|
||||
{
|
||||
Serial.print("UBX-TIM-SMEAS:");
|
||||
Serial.printf("\n version: %u", smea.version);
|
||||
Serial.printf("\n numMeas: %u", smea.numMeas);
|
||||
Serial.printf("\n iTOW: %lu", smea.iTOW);
|
||||
for (int i = 0; i < smea.numMeas; i++) {
|
||||
Serial.printf("\n sourceId %u:", smea.data[i].sourceId);
|
||||
Serial.printf("\n flags:");
|
||||
Serial.printf("\n freqValid %u", smea.data[i].flags.bits.freqValid);
|
||||
Serial.printf("\n phaseValid %u", smea.data[i].flags.bits.phaseValid);
|
||||
Serial.printf("\n phaseOffsetFrac %d", smea.data[i].phaseOffsetFrac);
|
||||
Serial.printf("\n phaseUncFrac %u", smea.data[i].phaseUncFrac);
|
||||
Serial.printf("\n phaseOffset %ld", smea.data[i].phaseOffset);
|
||||
Serial.printf("\n phaseUnc %lu", smea.data[i].phaseUnc);
|
||||
Serial.printf("\n freqOffset %ld", smea.data[i].freqOffset);
|
||||
Serial.printf("\n freqUnc %lu", smea.data[i].freqUnc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UBX_CFG_SMGR_data_t convertRawBufToCfgSmgr(const ubxPacket* msg) {
|
||||
UBX_CFG_SMGR_data_t smgr;
|
||||
if (msg->len < sizeof(UBX_CFG_SMGR_data_t)) {
|
||||
Serial.printf("Payload message size (%zu) is too small to be converted to UBX_CFG_SMGR_data_t\n", msg->len);
|
||||
return smgr;
|
||||
}
|
||||
|
||||
smgr.version = SFE_UBLOX_GNSS::extractByte(msg, 0);
|
||||
smgr.minGNSSFix = SFE_UBLOX_GNSS::extractByte(msg, 1);
|
||||
smgr.maxFreqChangeRate = SFE_UBLOX_GNSS::extractInt(msg, 2);
|
||||
smgr.maxPhaseCorrRate = SFE_UBLOX_GNSS::extractInt(msg, 4);
|
||||
smgr.freqTolerance = SFE_UBLOX_GNSS::extractInt(msg, 8);
|
||||
smgr.timeTolerance = SFE_UBLOX_GNSS::extractInt(msg, 10);
|
||||
smgr.messageCfg.all = SFE_UBLOX_GNSS::extractInt(msg, 12);
|
||||
smgr.maxSlewRate = SFE_UBLOX_GNSS::extractInt(msg, 14);
|
||||
smgr.flags.all = SFE_UBLOX_GNSS::extractLong(msg, 16);
|
||||
|
||||
return smgr;
|
||||
}
|
||||
|
||||
|
||||
void printUbxCfgSmgr(const UBX_CFG_SMGR_data_t& smgr) {
|
||||
Serial.printf("\nUBX-CFG-SMGR:");
|
||||
Serial.printf("\n version %u (0x%02x)", smgr.version, smgr.version);
|
||||
Serial.printf("\n minGNSSFix %u (0x%02x)", smgr.minGNSSFix, smgr.minGNSSFix);
|
||||
Serial.printf("\n maxFreqChangeRate %u (0x%02x)", smgr.maxFreqChangeRate, smgr.maxFreqChangeRate);
|
||||
Serial.printf("\n maxPhaseCorrRate %u (0x%02x)", smgr.maxPhaseCorrRate, smgr.maxPhaseCorrRate);
|
||||
Serial.printf("\n freqTolerance %u (0x%02x)", smgr.freqTolerance, smgr.freqTolerance);
|
||||
Serial.printf("\n timeTolerance %u (0x%02x)", smgr.timeTolerance, smgr.timeTolerance);
|
||||
Serial.printf("\n messageCfg:");
|
||||
Serial.printf("\n measInternal: %u", smgr.messageCfg.bits.measInternal);
|
||||
Serial.printf("\n measGNSS: %u", smgr.messageCfg.bits.measGNSS);
|
||||
Serial.printf("\n measEXTINT0: %u", smgr.messageCfg.bits.measEXTINT0);
|
||||
Serial.printf("\n measEXTINT1: %u", smgr.messageCfg.bits.measEXTINT1);
|
||||
Serial.printf("\n maxSlewRate %u (0x%02x)", smgr.maxSlewRate, smgr.maxSlewRate);
|
||||
Serial.printf("\n flags:");
|
||||
Serial.printf("\n disableInternal: %u", smgr.flags.bits.disableInternal);
|
||||
Serial.printf("\n disableExternal: %u", smgr.flags.bits.disableExternal);
|
||||
Serial.printf("\n preferenceMode: %u", smgr.flags.bits.preferenceMode);
|
||||
Serial.printf("\n enableGNSS: %u", smgr.flags.bits.enableGNSS);
|
||||
Serial.printf("\n enableEXTINT0: %u", smgr.flags.bits.enableEXTINT0);
|
||||
Serial.printf("\n enableEXTINT1: %u", smgr.flags.bits.enableEXTINT1);
|
||||
Serial.printf("\n enableHostMeasInt: %u", smgr.flags.bits.enableHostMeasInt);
|
||||
Serial.printf("\n enableHostMeasExt: %u", smgr.flags.bits.enableHostMeasExt);
|
||||
Serial.printf("\n useAnyFix: %u", smgr.flags.bits.useAnyFix);
|
||||
Serial.printf("\n disableMaxSlewRate: %u", smgr.flags.bits.disableMaxSlewRate);
|
||||
Serial.printf("\n issueFreqWarn: %u", smgr.flags.bits.issueFreqWarn);
|
||||
Serial.printf("\n issueTimeWarn: %u", smgr.flags.bits.issueTimeWarn);
|
||||
Serial.printf("\n TPCoherent: %u", smgr.flags.bits.TPCoherent);
|
||||
Serial.printf("\n disableOffset: %u", smgr.flags.bits.disableOffset);
|
||||
Serial.println("\n");
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for Serial ready
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); // ignore NMEA messages
|
||||
|
||||
// setPacketCfgPayloadSize tells the library how many bytes our customPayload can hold.
|
||||
// It is more memory-efficient to call setPacketCfgPayloadSize before .begin (to avoid creating a new buffer, copying across
|
||||
// the contents of the old buffer and then deleting the old buffer). But let's call it here just to prove that we can.
|
||||
myGNSS.setPacketCfgPayloadSize(MAX_PAYLOAD_SIZE);
|
||||
|
||||
uint8_t customPayload[MAX_PAYLOAD_SIZE]; // This array holds the payload data bytes. MAX_PAYLOAD_SIZE defaults to 256. The CFG_RATE payload is only 6 bytes!
|
||||
|
||||
// The next line creates and initialises the packet information which wraps around the payload
|
||||
ubxPacket customCfg = {0, 0, 0, 0, 0, customPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED};
|
||||
|
||||
// The structure of ubxPacket is:
|
||||
// uint8_t cls : The message Class
|
||||
// uint8_t id : The message ID
|
||||
// uint16_t len : Length of the payload. Does not include cls, id, or checksum bytes
|
||||
// uint16_t counter : Keeps track of number of overall bytes received. Some responses are larger than 255 bytes.
|
||||
// uint16_t startingSpot : The counter value needed to go past before we begin recording into payload array
|
||||
// uint8_t *payload : The payload
|
||||
// uint8_t checksumA : Given to us by the module. Checked against the rolling calculated A/B checksums.
|
||||
// uint8_t checksumB
|
||||
// sfe_ublox_packet_validity_e valid : Goes from NOT_DEFINED to VALID or NOT_VALID when checksum is checked
|
||||
// sfe_ublox_packet_validity_e classAndIDmatch : Goes from NOT_DEFINED to VALID or NOT_VALID when the Class and ID match the requestedClass and requestedID
|
||||
|
||||
// sendCommand will return:
|
||||
// SFE_UBLOX_STATUS_DATA_RECEIVED if the data we requested was read / polled successfully
|
||||
// SFE_UBLOX_STATUS_DATA_SENT if the data we sent was writted successfully (ACK'd)
|
||||
// Other values indicate errors. Please see the sfe_ublox_status_e enum for further details.
|
||||
|
||||
// Referring to the u-blox M8 Receiver Description and Protocol Specification we see that
|
||||
// the navigation rate is configured using the UBX-CFG-RATE message. So let's load our
|
||||
// custom packet with the correct information so we can read (poll / get) the current settings.
|
||||
|
||||
customCfg.cls = UBX_CLASS_CFG; // This is the message Class
|
||||
customCfg.id = UBX_CFG_SMGR; // This is the message ID
|
||||
customCfg.len = 0; // Setting the len (length) to zero let's us poll the current settings
|
||||
customCfg.startingSpot = 0; // Always set the startingSpot to zero (unless you really know what you are doing)
|
||||
|
||||
// We also need to tell sendCommand how long it should wait for a reply
|
||||
uint16_t maxWait = 250; // Wait for up to 250ms (Serial may need a lot longer e.g. 1100)
|
||||
|
||||
// Now let's read the current UBX-CFG-SMGR settings. The results will be loaded into customCfg.
|
||||
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_RECEIVED) // We are expecting data and an ACK
|
||||
{
|
||||
Serial.println(F("sendCommand (poll / get) failed! Freezing..."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
UBX_CFG_SMGR_data_t cfgSmgrPayload = convertRawBufToCfgSmgr(&customCfg);
|
||||
|
||||
printUbxCfgSmgr(cfgSmgrPayload);
|
||||
|
||||
cfgSmgrPayload.minGNSSFix = 5; // update the min no. of GNSS fixes to start freq/phase sync
|
||||
cfgSmgrPayload.flags.bits.useAnyFix = 1; // use any fix
|
||||
|
||||
// update the raw payload buffer
|
||||
memmove(customPayload, &cfgSmgrPayload, sizeof(UBX_CFG_SMGR_data_t));
|
||||
|
||||
// Now let's set the updated settings.
|
||||
if (myGNSS.sendCommand(&customCfg, maxWait) != SFE_UBLOX_STATUS_DATA_SENT) // We are expecting data and an ACK
|
||||
{
|
||||
Serial.println(F("sendCommand set failed! Freezing..."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
Serial.println("UBX-CFG-SMGR successfully updated");
|
||||
|
||||
myGNSS.setAutoTIMSMEAcallback(&printTIMSMEASdata);
|
||||
|
||||
// Enable info/warns messages
|
||||
// myGNSS.setVal8(UBLOX_CFG_INFMSG_UBX_I2C, 1);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new UBX data is available. Process bytes as they come in.
|
||||
myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Reading lat and long via UBX binary commands - no more NMEA parsing!
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its lat/long/altitude. We also
|
||||
turn off the NMEA output on the I2C port. This decreases the amount of I2C traffic
|
||||
dramatically.
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Get fix type and RTK fix type if available
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for fix type and RTK fix type.
|
||||
The fix type is as follows:
|
||||
0 = no fix
|
||||
1 = dead reckoning (requires external sensors)
|
||||
2 = 2D (not quite enough satellites in view)
|
||||
3 = 3D (the standard fix)
|
||||
4 = GNSS + dead reckoning (requires external sensors)
|
||||
5 = Time fix only
|
||||
|
||||
Additionally, if we are doing RTK, we can figure out if we have a floating
|
||||
RTK solution or if we have been able to resolve a fixec solution (better precision).
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
//Wire.setClock(400000); //Optional. Increase I2C clock speed to 400kHz.
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
|
||||
byte fixType = myGNSS.getFixType();
|
||||
Serial.print(F(" Fix: "));
|
||||
if(fixType == 0) Serial.print(F("No fix"));
|
||||
else if(fixType == 1) Serial.print(F("Dead reckoning"));
|
||||
else if(fixType == 2) Serial.print(F("2D"));
|
||||
else if(fixType == 3) Serial.print(F("3D"));
|
||||
else if(fixType == 4) Serial.print(F("GNSS + Dead reckoning"));
|
||||
else if(fixType == 5) Serial.print(F("Time only"));
|
||||
|
||||
byte RTK = myGNSS.getCarrierSolutionType();
|
||||
Serial.print(" RTK: ");
|
||||
Serial.print(RTK);
|
||||
if (RTK == 0) Serial.print(F(" (No solution)"));
|
||||
else if (RTK == 1) Serial.print(F(" (High precision floating fix)"));
|
||||
else if (RTK == 2) Serial.print(F(" (High precision fix)"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Get Speed/Heading and dilution of precision via UBX binary commands - no more NMEA parsing!
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its lat/long/altitude.
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 1,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
|
||||
long speed = myGNSS.getGroundSpeed();
|
||||
Serial.print(F(" Speed: "));
|
||||
Serial.print(speed);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
long heading = myGNSS.getHeading();
|
||||
Serial.print(F(" Heading: "));
|
||||
Serial.print(heading);
|
||||
Serial.print(F(" (degrees * 10^-5)"));
|
||||
|
||||
int pDOP = myGNSS.getPDOP();
|
||||
Serial.print(F(" pDOP: "));
|
||||
Serial.print(pDOP / 100.0, 2); // Convert pDOP scaling from 0.01 to 1
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Turn on/off various NMEA sentences.
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to turn on/off the NMEA sentences being output
|
||||
over UART1. We use the I2C interface on the u-blox module for configuration
|
||||
but you won't see any output from this sketch. You'll need to hook up
|
||||
a Serial Basic or other USB to Serial device to UART1 on your u-blox module
|
||||
to see the output.
|
||||
|
||||
This example turns off all sentences except for the GPGGA and GPVTG sentences.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
Hookup a Serial Basic (https://www.sparkfun.com/products/15096) to UART1 on the u-blox module. Open a terminal at 57600bps
|
||||
and see GPGGA and GPVTG sentences.
|
||||
*/
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
unsigned long lastGNSSsend = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Serial debug output over USB visible from Arduino IDE
|
||||
Serial.println("Example showing how to enable/disable certain NMEA sentences");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
//Disable or enable various NMEA sentences over the UART1 interface
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GLL, COM_PORT_UART1); //Several of these are on by default on ublox board so let's disable them
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSA, COM_PORT_UART1);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_GSV, COM_PORT_UART1);
|
||||
myGNSS.disableNMEAMessage(UBX_NMEA_RMC, COM_PORT_UART1);
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_UART1); //Only leaving GGA & VTG enabled at current navigation rate
|
||||
myGNSS.enableNMEAMessage(UBX_NMEA_VTG, COM_PORT_UART1);
|
||||
|
||||
//Here's the advanced configure method
|
||||
//Some of the other examples in this library enable the PVT message so let's disable it
|
||||
myGNSS.configureMessage(UBX_CLASS_NAV, UBX_NAV_PVT, COM_PORT_UART1, 0); //Message Class, ID, and port we want to configure, sendRate of 0 (disable).
|
||||
|
||||
myGNSS.setUART1Output(COM_TYPE_NMEA); //Turn off UBX and RTCM sentences on the UART1 interface
|
||||
|
||||
myGNSS.setSerialRate(57600); //Set UART1 to 57600bps.
|
||||
|
||||
//myGNSS.saveConfiguration(); //Optional: Save these settings to NVM
|
||||
|
||||
Serial.println(F("Messages configured. NMEA now being output over the UART1 port on the u-blox module at 57600bps."));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (millis() - lastGNSSsend > 200)
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available, but we don't want to get NMEA here. Go check UART1.
|
||||
lastGNSSsend = millis();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Set update rate to 10Hz
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to increase the output of the module from 1Hz to 4Hz.
|
||||
The max output rate various from model to model. RTFM! But you cannot do harm
|
||||
to the module.
|
||||
|
||||
We also disable NMEA output on the I2C bus and use only UBX. This dramatically
|
||||
decreases the amount of data that needs to be transmitted.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
unsigned long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
unsigned long startTime = 0; //Used to calc the actual update rate.
|
||||
unsigned long updateCount = 0; //Used to calc the actual update rate.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
// Increase I2C clock speed to 400kHz to cope with the high navigation rate
|
||||
// (We normally recommend running the bus at 100kHz)
|
||||
Wire.setClock(400000);
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setNavigationFrequency(5); //Set output to 5 times a second
|
||||
|
||||
uint8_t rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
|
||||
Serial.print("Current update rate: ");
|
||||
Serial.println(rate);
|
||||
|
||||
startTime = millis();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module every 25 ms. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available. This is defined
|
||||
//by the update freq.
|
||||
if (millis() - lastTime > 25)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
|
||||
updateCount++;
|
||||
|
||||
//Calculate the actual update rate based on the sketch start time and the
|
||||
//number of updates we've received.
|
||||
Serial.print(F(" Rate: "));
|
||||
Serial.print( updateCount / ((millis() - startTime) / 1000.0), 2);
|
||||
Serial.print(F("Hz"));
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Reading the protocol version of a u-blox module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its protocol version.
|
||||
|
||||
Various modules have various protocol version. We've seen v18 up to v27. Depending
|
||||
on the protocol version there are different commands available. This is a handy
|
||||
way to predict which commands will or won't work.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
Serial.print(F("Version: "));
|
||||
byte versionHigh = myGNSS.getProtocolVersionHigh();
|
||||
Serial.print(versionHigh);
|
||||
Serial.print(".");
|
||||
byte versionLow = myGNSS.getProtocolVersionLow();
|
||||
Serial.print(versionLow);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
Reading the protocol version of a u-blox module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its protocol version.
|
||||
|
||||
Note: this may fail on boards like the UNO (ATmega328P) with modules like the ZED-F9P
|
||||
because getProtocolVersion returns a lot of data - more than the UNO's serial buffer can hold
|
||||
|
||||
Various modules have various protocol version. We've seen v18 up to v27. Depending
|
||||
on the protocol version there are different commands available. This is a handy
|
||||
way to predict which commands will or won't work.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
#define mySerial Serial1 // Uncomment this line to connect via Serial1
|
||||
// - or -
|
||||
//SoftwareSerial mySerial(10, 11); // Uncomment this line to connect via SoftwareSerial(RX, TX). Connect pin 10 to GNSS TX pin.
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Serial.println("Trying 38400 baud");
|
||||
mySerial.begin(38400);
|
||||
if (myGNSS.begin(mySerial))
|
||||
{
|
||||
Serial.println("GNSS connected at 38400 baud");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Trying 9600 baud");
|
||||
mySerial.begin(9600);
|
||||
if (myGNSS.begin(mySerial))
|
||||
{
|
||||
Serial.println("GNSS connected at 9600 baud");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Could not connect to GNSS. Freezing...");
|
||||
while(1); // Do nothing more
|
||||
}
|
||||
}
|
||||
|
||||
Serial.print(F("Version: "));
|
||||
byte versionHigh = myGNSS.getProtocolVersionHigh();
|
||||
Serial.print(versionHigh);
|
||||
Serial.print(".");
|
||||
byte versionLow = myGNSS.getProtocolVersionLow();
|
||||
Serial.print(versionLow);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Change the I2C address of a u-blox module using I2C
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to change the I2C address of a u-blox module
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Tracks the passing of 2000ms (2 seconds)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
byte oldAddress = 0x42; //The default address for u-blox modules is 0x42
|
||||
byte newAddress = 0x3F; //Address you want to change to. Valid is 0x08 to 0x77.
|
||||
|
||||
while (Serial.available()) Serial.read(); //Trash any incoming chars
|
||||
Serial.print("Press a key to change address to 0x");
|
||||
Serial.println(newAddress, HEX);
|
||||
while (Serial.available() == false) ; //Wait for user to send character
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
|
||||
|
||||
if (myGNSS.begin(Wire, oldAddress) == true) //Connect to the u-blox module using Wire port and the old address
|
||||
{
|
||||
Serial.print("GNSS found at address 0x");
|
||||
Serial.println(oldAddress, HEX);
|
||||
|
||||
myGNSS.setI2CAddress(newAddress); //Change I2C address of this device
|
||||
//Device's I2C address is stored to memory and loaded on each power-on
|
||||
|
||||
delay(2000); // Allow time for the change to take
|
||||
|
||||
if (myGNSS.begin(Wire, newAddress) == true)
|
||||
{
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
Serial.print("Address successfully changed to 0x");
|
||||
Serial.println(newAddress, HEX);
|
||||
Serial.print("Now load another example sketch using .begin(Wire, 0x");
|
||||
Serial.print(newAddress, HEX);
|
||||
Serial.println(") to use this GPS module");
|
||||
Serial.println("Freezing...");
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
//Something went wrong, begin looking for the I2C device
|
||||
Serial.println("Address change probably failed. Beginning an I2C scan.");
|
||||
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
byte address;
|
||||
int nDevices;
|
||||
|
||||
Serial.println("Scanning...");
|
||||
|
||||
nDevices = 0;
|
||||
for (address = 1; address < 127; address++ )
|
||||
{
|
||||
Wire.beginTransmission(address);
|
||||
byte error = Wire.endTransmission();
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
Serial.print("I2C device found at address 0x");
|
||||
if (address < 16)
|
||||
Serial.print("0");
|
||||
Serial.print(address, HEX);
|
||||
Serial.println(" !");
|
||||
|
||||
nDevices++;
|
||||
}
|
||||
// else if (error == 4)
|
||||
// {
|
||||
// Serial.print("Unknown error at address 0x");
|
||||
// if (address < 16)
|
||||
// Serial.print("0");
|
||||
// Serial.println(address, HEX);
|
||||
// }
|
||||
}
|
||||
|
||||
if (nDevices == 0)
|
||||
Serial.println("No I2C devices found\n");
|
||||
else
|
||||
Serial.println("done\n");
|
||||
|
||||
delay(5000); // wait 5 seconds for next scan
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Send UBX binary commands to enable RTCM sentences on u-blox NEO-M8P module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: September 7th, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example sends the command to enable the four RTCM messages needed for RTK. This
|
||||
is the first part of a larger tutorial and example to setup an RTK base station.
|
||||
These commands are only accepted by the NEO-M8P module.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while(!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox RTCM Enable Example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
while(Serial.available()) Serial.read(); //Clear any latent chars in serial buffer
|
||||
Serial.println(F("Press any key to send commands to enable RTCM 3.x"));
|
||||
while(Serial.available() == 0) ; //Wait for user to press a key
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); // Ensure RTCM3 is enabled
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
bool response = true;
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every second
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_I2C, 10); //Enable message every 10 seconds
|
||||
|
||||
if (response == true)
|
||||
{
|
||||
Serial.println(F("RTCM messages enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("RTCM failed to enable. Are you sure you have an NEO-M8P?"));
|
||||
while(1); //Freeze
|
||||
}
|
||||
|
||||
//RTCM is now enabled but we haven't done a 'survey-in'
|
||||
//See example 4 for the full Base RTK setup
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Note: compiles OK with v2.0 but is currently untested
|
||||
|
||||
Send UBX binary commands to enable RTCM sentences on u-blox NEO-M8P-2 module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: September 7th, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example does all steps to configure and enable a NEO-M8P-2 as a base station:
|
||||
Begin Survey-In
|
||||
Once we've achieved 2m accuracy and 300s have passed, survey is complete
|
||||
Enable four RTCM messages
|
||||
Begin outputting RTCM bytes
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox NEO-M8P-2 base station example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); // Ensure RTCM3 is enabled
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
while (Serial.available()) Serial.read(); //Clear any latent chars in serial buffer
|
||||
Serial.println(F("Press any key to send commands to begin Survey-In"));
|
||||
while (Serial.available() == 0) ; //Wait for user to press a key
|
||||
|
||||
bool response;
|
||||
|
||||
//Check if Survey is in Progress before initiating one
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (request can take a long time)
|
||||
|
||||
if (response == false) // Check if fresh data was received
|
||||
{
|
||||
Serial.println(F("Failed to get Survey In status. Freezing..."));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
if (myGNSS.getSurveyInActive() == true) // Use the helper function
|
||||
{
|
||||
Serial.print(F("Survey already in progress."));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Start survey
|
||||
response = myGNSS.enableSurveyMode(300, 2.000); //Enable Survey in, 300 seconds, 2.0m
|
||||
if (response == false)
|
||||
{
|
||||
Serial.println(F("Survey start failed. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("Survey started. This will run until 300s has passed and less than 2m accuracy is achieved."));
|
||||
}
|
||||
|
||||
while(Serial.available()) Serial.read(); //Clear buffer
|
||||
|
||||
//Begin waiting for survey to complete
|
||||
while (myGNSS.getSurveyInValid() == false) // Call the helper function
|
||||
{
|
||||
if(Serial.available())
|
||||
{
|
||||
byte incoming = Serial.read();
|
||||
if(incoming == 'x')
|
||||
{
|
||||
//Stop survey mode
|
||||
response = myGNSS.disableSurveyMode(); //Disable survey
|
||||
Serial.println(F("Survey stopped"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (req can take a long time)
|
||||
if (response == true) // Check if fresh data was received
|
||||
{
|
||||
Serial.print(F("Press x to end survey - "));
|
||||
Serial.print(F("Time elapsed: "));
|
||||
Serial.print((String)myGNSS.getSurveyInObservationTime());
|
||||
|
||||
Serial.print(F(" Accuracy: "));
|
||||
Serial.print((String)myGNSS.getSurveyInMeanAccuracy());
|
||||
Serial.println();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("SVIN request failed"));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
Serial.println(F("Survey valid!"));
|
||||
|
||||
response = true;
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every second
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_I2C, 10); //Enable message every 10 seconds
|
||||
|
||||
if (response == true)
|
||||
{
|
||||
Serial.println(F("RTCM messages enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("RTCM failed to enable. Are you sure you have an NEO-M8P?"));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
Serial.println(F("Base survey complete! RTCM now broadcasting."));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
||||
//This function gets called from the SparkFun u-blox Arduino Library.
|
||||
//As each RTCM byte comes in you can specify what to do with it
|
||||
//Useful for passing the RTCM correction data to a radio, Ntrip broadcaster, etc.
|
||||
void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming)
|
||||
{
|
||||
//Let's just pretty-print the HEX values for now
|
||||
if (myGNSS.rtcmFrameCounter % 16 == 0) Serial.println();
|
||||
Serial.print(F(" "));
|
||||
if (incoming < 0x10) Serial.print(F("0"));
|
||||
Serial.print(incoming, HEX);
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
Note: compiles OK with v2.0 but is currently untested
|
||||
|
||||
Send UBX binary commands to enable RTCM sentences on u-blox NEO-M8P-2 module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: September 7th, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example does all steps to configure and enable a NEO-M8P-2 as a base station:
|
||||
Begin Survey-In
|
||||
Once we've achieved 2m accuracy and 300s have passed, survey is complete
|
||||
Enable four RTCM messages
|
||||
Begin outputting RTCM bytes
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
|
||||
class MY_SFE_UBLOX_GNSS : public SFE_UBLOX_GNSS
|
||||
{
|
||||
//This function gets called from the SparkFun u-blox Arduino Library.
|
||||
//As each RTCM byte comes in you can specify what to do with it
|
||||
//Useful for passing the RTCM correction data to a radio, Ntrip broadcaster, etc.
|
||||
virtual void processRTCM_v(uint8_t incoming)
|
||||
{
|
||||
//Let's just pretty-print the HEX values for now
|
||||
if (rtcmFrameCounter % 16 == 0) Serial.println();
|
||||
Serial.print(F(" "));
|
||||
if (incoming < 0x10) Serial.print(F("0"));
|
||||
Serial.print(incoming, HEX);
|
||||
}
|
||||
};
|
||||
|
||||
MY_SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox NEO-M8P-2 base station example"));
|
||||
|
||||
Wire.begin();
|
||||
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||
|
||||
if (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); // Ensure RTCM3 is enabled
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
while (Serial.available()) Serial.read(); //Clear any latent chars in serial buffer
|
||||
Serial.println(F("Press any key to send commands to begin Survey-In"));
|
||||
while (Serial.available() == 0) ; //Wait for user to press a key
|
||||
|
||||
bool response;
|
||||
|
||||
//Check if Survey is in Progress before initiating one
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (request can take a long time)
|
||||
|
||||
if (response == false) // Check if fresh data was received
|
||||
{
|
||||
Serial.println(F("Failed to get Survey In status. Freezing..."));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
if (myGNSS.getSurveyInActive() == true) // Use the helper function
|
||||
{
|
||||
Serial.print(F("Survey already in progress."));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Start survey
|
||||
response = myGNSS.enableSurveyMode(300, 2.000); //Enable Survey in, 300 seconds, 2.0m
|
||||
if (response == false)
|
||||
{
|
||||
Serial.println(F("Survey start failed. Freezing..."));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("Survey started. This will run until 300s has passed and less than 2m accuracy is achieved."));
|
||||
}
|
||||
|
||||
while(Serial.available()) Serial.read(); //Clear buffer
|
||||
|
||||
//Begin waiting for survey to complete
|
||||
while (myGNSS.getSurveyInValid() == false) // Call the helper function
|
||||
{
|
||||
if(Serial.available())
|
||||
{
|
||||
byte incoming = Serial.read();
|
||||
if(incoming == 'x')
|
||||
{
|
||||
//Stop survey mode
|
||||
response = myGNSS.disableSurveyMode(); //Disable survey
|
||||
Serial.println(F("Survey stopped"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (req can take a long time)
|
||||
if (response == true) // Check if fresh data was received
|
||||
{
|
||||
Serial.print(F("Press x to end survey - "));
|
||||
Serial.print(F("Time elapsed: "));
|
||||
Serial.print((String)myGNSS.getSurveyInObservationTime());
|
||||
|
||||
Serial.print(F(" Accuracy: "));
|
||||
Serial.print((String)myGNSS.getSurveyInMeanAccuracy());
|
||||
Serial.println();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("SVIN request failed"));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
Serial.println(F("Survey valid!"));
|
||||
|
||||
response = true;
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every second
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_I2C, 10); //Enable message every 10 seconds
|
||||
|
||||
if (response == true)
|
||||
{
|
||||
Serial.println(F("RTCM messages enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("RTCM failed to enable. Are you sure you have an NEO-M8P?"));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
Serial.println(F("Base survey complete! RTCM now broadcasting."));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
Note: compiles OK with v2.0 but is currently untested
|
||||
|
||||
Send UBX binary commands to enable RTCM sentences on u-blox NEO-M8P-2 module
|
||||
By: Nathan Seidle
|
||||
SparkFun Electronics
|
||||
Date: September 7th, 2018
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example does all steps to configure and enable a NEO-M8P-2 as a base station:
|
||||
Begin Survey-In
|
||||
Once we've achieved 2m accuracy and 300s have passed, survey is complete
|
||||
Enable four RTCM messages
|
||||
Begin outputting RTCM bytes
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
SAM-M8Q: https://www.sparkfun.com/products/15106
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
Plug a SerLCD onto the Qwiic bus
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Watch the output on the LCD or open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#define STAT_LED 13
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
#include <SerLCD.h> //Click here to get the library: http://librarymanager/All#SparkFun_SerLCD
|
||||
SerLCD lcd; // Initialize the library with default I2C address 0x72
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox GNSS I2C Test"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
pinMode(STAT_LED, OUTPUT);
|
||||
digitalWrite(STAT_LED, LOW);
|
||||
|
||||
lcd.begin(Wire); //Set up the LCD for Serial communication at 9600bps
|
||||
lcd.setBacklight(0x4B0082); //indigo, a kind of dark purplish blue
|
||||
lcd.clear();
|
||||
lcd.print(F("LCD Ready"));
|
||||
|
||||
myGNSS.begin(Wire);
|
||||
if (myGNSS.isConnected() == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(F("No GNSS detected"));
|
||||
while (1);
|
||||
}
|
||||
|
||||
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("GNSS Detected");
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3); // Ensure RTCM3 is enabled
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
//Check if Survey is in Progress before initiating one
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
bool response;
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (request can take a long time)
|
||||
if (response == false)
|
||||
{
|
||||
Serial.println(F("Failed to get Survey In status"));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
if (myGNSS.getSurveyInActive() == true) // Use the helper function
|
||||
{
|
||||
Serial.print(F("Survey already in progress."));
|
||||
lcd.setCursor(0, 2);
|
||||
lcd.print(F("Survey already going"));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Start survey
|
||||
response = myGNSS.enableSurveyMode(300, 2.000); //Enable Survey in, 300 seconds, 2.0m
|
||||
if (response == false)
|
||||
{
|
||||
Serial.println(F("Survey start failed"));
|
||||
lcd.setCursor(0, 3);
|
||||
lcd.print(F("Survey start failed"));
|
||||
while (1);
|
||||
}
|
||||
Serial.println(F("Survey started. This will run until 300s has passed and less than 2m accuracy is achieved."));
|
||||
}
|
||||
|
||||
while (Serial.available()) Serial.read(); //Clear buffer
|
||||
|
||||
lcd.clear();
|
||||
lcd.print(F("Survey in progress"));
|
||||
|
||||
//Begin waiting for survey to complete
|
||||
while (myGNSS.getSurveyInValid() == false) // Call the helper function
|
||||
{
|
||||
if (Serial.available())
|
||||
{
|
||||
byte incoming = Serial.read();
|
||||
if (incoming == 'x')
|
||||
{
|
||||
//Stop survey mode
|
||||
response = myGNSS.disableSurveyMode(); //Disable survey
|
||||
Serial.println(F("Survey stopped"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// From v2.0, the data from getSurveyStatus (UBX-NAV-SVIN) is returned in UBX_NAV_SVIN_t packetUBXNAVSVIN
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_SVIN_t
|
||||
// You can either read the data from packetUBXNAVSVIN directly
|
||||
// or can use the helper functions: getSurveyInActive; getSurveyInValid; getSurveyInObservationTime; and getSurveyInMeanAccuracy
|
||||
response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (req can take a long time)
|
||||
if (response == true)
|
||||
{
|
||||
Serial.print(F("Press x to end survey - "));
|
||||
Serial.print(F("Time elapsed: "));
|
||||
Serial.print((String)myGNSS.getSurveyInObservationTime());
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print(F("Elapsed: "));
|
||||
lcd.print((String)myGNSS.getSurveyInObservationTime());
|
||||
|
||||
Serial.print(F(" Accuracy: "));
|
||||
Serial.print((String)myGNSS.getSurveyInMeanAccuracy());
|
||||
Serial.println();
|
||||
|
||||
lcd.setCursor(0, 2);
|
||||
lcd.print(F("Accuracy: "));
|
||||
lcd.print((String)myGNSS.getSurveyInMeanAccuracy());
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("SVIN request failed"));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
Serial.println(F("Survey valid!"));
|
||||
|
||||
response = true;
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1005, COM_PORT_I2C, 1); //Enable message 1005 to output through I2C port, message every second
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_I2C, 1);
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_I2C, 10); //Enable message every 10 seconds
|
||||
|
||||
if (response == true)
|
||||
{
|
||||
Serial.println(F("RTCM messages enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("RTCM failed to enable. Are you sure you have an NEO-M8P?"));
|
||||
while (1); //Freeze
|
||||
}
|
||||
|
||||
Serial.println(F("Base survey complete! RTCM now broadcasting."));
|
||||
lcd.clear();
|
||||
lcd.print(F("Transmitting RTCM"));
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
//Do anything you want. Call checkUblox() every second. NEO-M8P-2 has TX buffer of 4k bytes.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
||||
//This function gets called from the SparkFun u-blox Arduino Library.
|
||||
//As each RTCM byte comes in you can specify what to do with it
|
||||
//Useful for passing the RTCM correction data to a radio, Ntrip broadcaster, etc.
|
||||
void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming)
|
||||
{
|
||||
//Let's just pretty-print the HEX values for now
|
||||
if (myGNSS.rtcmFrameCounter % 16 == 0) Serial.println();
|
||||
Serial.print(" ");
|
||||
if (incoming < 0x10) Serial.print("0");
|
||||
Serial.print(incoming, HEX);
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Configure the NEO-M8P-2 as a "moving base"
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 20th, 2023
|
||||
License: MIT. See license file for more information.
|
||||
|
||||
This example configures the NEO-M8P-2 as a moving base.
|
||||
It will output RTCM3 1077, 1087, 1230 and 4072.0 messages on UART1.
|
||||
Connect UART1 TX to UART1 RX on a NEO-M8P rover. Also connect GND to GND.
|
||||
The next example shows how to display the relative position of the rover.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Connect UART1 TX to UART1 RX on a NEO-M8P rover. Also connect GND to GND.
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
while(!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("u-blox NEO-M8P Moving Base Example"));
|
||||
|
||||
Wire.begin();
|
||||
|
||||
while (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring."));
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
myGNSS.setUART1Output(COM_TYPE_RTCM3); // Configure UART1 to output RTCM3 only. Disable NMEA.
|
||||
myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
|
||||
bool response = true;
|
||||
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1077, COM_PORT_UART1, 1); //Enable message 1077 on UART1
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1087, COM_PORT_UART1, 1); //Enable message 1087 on UART1
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_1230, COM_PORT_UART1, 1); //Enable message 1230 on UART1
|
||||
response &= myGNSS.enableRTCMmessage(UBX_RTCM_4072_0, COM_PORT_UART1, 1); //Enable message 4072.0 on UART1
|
||||
|
||||
response &= myGNSS.disableSurveyMode(); //Essential - we need to set TMODE3 to Disabled to allow 4072.0 to be output
|
||||
|
||||
if (response == true)
|
||||
{
|
||||
Serial.println(F("RTCM messages enabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("RTCM failed to enable. Are you sure you have an NEO-M8P?"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
myGNSS.checkUblox(); //See if new data is available. Process bytes as they come in.
|
||||
|
||||
delay(250); //Don't pound too hard on the I2C bus
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Display the relative position of a NEO-M8P-2 rover
|
||||
By: Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: March 20th, 2023
|
||||
License: MIT. See license file for more information.
|
||||
|
||||
This example shows how to query the module for RELPOS information in the NED frame.
|
||||
It assumes you already have RTCM correction data being fed to the receiver on UART1.
|
||||
Connect UART1 TX on the base to UART1 RX on the rover. Also connect GND to GND.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a RedBoard Qwiic or BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Connect UART1 TX on the base to UART1 RX on the rover. Also connect GND to GND.
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("u-blox NEO-M8P Rover Example");
|
||||
|
||||
Wire.begin();
|
||||
|
||||
while (myGNSS.begin() == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring."));
|
||||
}
|
||||
|
||||
// Uncomment the next line if you want to reset your module back to the default settings with 1Hz navigation rate
|
||||
//myGNSS.factoryDefault(); delay(5000);
|
||||
|
||||
// By default, UART1 Protocol In is set to NMEA + UBX + RTCM3. No changes are necessary. But we can manually configure the port if required.
|
||||
Serial.print(myGNSS.setPortInput(COM_PORT_UART1, COM_TYPE_UBX | COM_TYPE_RTCM3)); //Enable UBX and RTCM3 input on UART1
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save the communications port settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// The data from getRELPOSNED (UBX-NAV-RELPOSNED) is returned in UBX_NAV_RELPOSNED_t packetUBXNAVRELPOSNED
|
||||
// Please see u-blox_structs.h for the full definition of UBX_NAV_RELPOSNED_t
|
||||
// You can either read the data from packetUBXNAVRELPOSNED directly
|
||||
// or can use the helper functions: getRelPosN/E/D; getRelPosAccN/E/D
|
||||
// Note that NEO-M8P RELPOSNED is different to ZED-F9P. It does not contain the relative length and heading.
|
||||
if (myGNSS.getRELPOSNED() == true)
|
||||
{
|
||||
Serial.print("relPosN: ");
|
||||
Serial.println(myGNSS.getRelPosN(), 4); // Use the helper functions to get the rel. pos. as m
|
||||
Serial.print("relPosE: ");
|
||||
Serial.println(myGNSS.getRelPosE(), 4);
|
||||
Serial.print("relPosD: ");
|
||||
Serial.println(myGNSS.getRelPosD(), 4);
|
||||
|
||||
Serial.print("relPosHPN: ");
|
||||
Serial.println((float)myGNSS.packetUBXNAVRELPOSNED->data.relPosHPN / 10, 1); //High-precision component. Convert to mm
|
||||
Serial.print("relPosHPE: ");
|
||||
Serial.println((float)myGNSS.packetUBXNAVRELPOSNED->data.relPosHPE / 10, 1);
|
||||
Serial.print("relPosHPD: ");
|
||||
Serial.println((float)myGNSS.packetUBXNAVRELPOSNED->data.relPosHPD / 10, 1);
|
||||
|
||||
Serial.print("accN: ");
|
||||
Serial.println(myGNSS.getRelPosAccN(), 4); // Use the helper functions to get the rel. pos. accuracy as m
|
||||
Serial.print("accE: ");
|
||||
Serial.println(myGNSS.getRelPosAccE(), 4);
|
||||
Serial.print("accD: ");
|
||||
Serial.println(myGNSS.getRelPosAccD(), 4);
|
||||
|
||||
Serial.print("gnssFixOk: ");
|
||||
if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.gnssFixOK == true)
|
||||
Serial.println("x");
|
||||
else
|
||||
Serial.println("");
|
||||
|
||||
Serial.print("diffSolution: ");
|
||||
if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.diffSoln == true)
|
||||
Serial.println("x");
|
||||
else
|
||||
Serial.println("");
|
||||
|
||||
Serial.print("relPosValid: ");
|
||||
if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.relPosValid == true)
|
||||
Serial.println("x");
|
||||
else
|
||||
Serial.println("");
|
||||
|
||||
Serial.print("carrier Solution Type: ");
|
||||
if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.carrSoln == 0)
|
||||
Serial.println("None");
|
||||
else if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.carrSoln == 1)
|
||||
Serial.println("Float");
|
||||
else if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.carrSoln == 2)
|
||||
Serial.println("Fixed");
|
||||
|
||||
Serial.print("isMoving: ");
|
||||
if (myGNSS.packetUBXNAVRELPOSNED->data.flags.bits.isMoving == true)
|
||||
Serial.println("x");
|
||||
else
|
||||
Serial.println("");
|
||||
}
|
||||
else
|
||||
Serial.println("RELPOS request failed");
|
||||
|
||||
Serial.println("");
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
Reading lat and long via UBX binary commands over SPI
|
||||
By: Andrew Berridge
|
||||
Date: 27th June 2021
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to query a u-blox module for its lat/long/altitude over SPI. We also
|
||||
turn off the NMEA output on the SPI port. This decreases the amount of SPI traffic
|
||||
dramatically.
|
||||
|
||||
Note: Long/lat are large numbers because they are * 10^7. To convert lat/long
|
||||
to something google maps understands simply divide the numbers by 10,000,000. We
|
||||
do this so that we don't have to use floating point numbers.
|
||||
|
||||
Leave NMEA parsing behind. Now you can simply ask the module for the datums you want!
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
NEO-M9N: https://www.sparkfun.com/products/17285
|
||||
|
||||
Hardware Connections:
|
||||
You need to connect the SPI pins from your microcontroller to the specific pins on your SparkFun product.
|
||||
Connections will vary based on your microcontroller, but for reference please refer to this tutorial on SPI:
|
||||
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all
|
||||
|
||||
Most new boards now use the terms:
|
||||
CS - Chip Select
|
||||
COPI - Controller Out, Peripheral In
|
||||
CIPO - Controller in, Peripheral Out
|
||||
SCK - Serial Clock
|
||||
|
||||
You can choose any pin for Chip Select, but the others are likely either defined by the library you are using
|
||||
(see here for the standard Arduino one: https://www.arduino.cc/en/reference/SPI) or the microcontroller. The
|
||||
ESP32 has two standard, selectable SPI ports, for example.
|
||||
|
||||
To enable SPI communication, you will need to solder the DSEL/SPI jumper closed on your u-blox board.
|
||||
|
||||
IMPORTANT: there have been reports that some u-blox devices do not respond to the UBX protocol over SPI
|
||||
with the factory settings. You may find you need to connect to the device via USB and u-center and set
|
||||
the incoming protocol to UBX only. Make sure you disable all other protocols as inputs if you can't
|
||||
get things to work! Hopefully this is just a bug in the u-blox firmware that will be fixed soon ;-)
|
||||
|
||||
*/
|
||||
|
||||
#include <SPI.h> //Needed for SPI to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// #########################################
|
||||
|
||||
// Instantiate an instance of the SPI class.
|
||||
// Your configuration may be different, depending on the microcontroller you are using!
|
||||
|
||||
#define spiPort SPI // This is the SPI port on standard Ardino boards. Comment this line if you want to use a different port.
|
||||
|
||||
//SPIClass spiPort (HSPI); // This is the default SPI interface on some ESP32 boards. Uncomment this line if you are using ESP32.
|
||||
|
||||
// #########################################
|
||||
|
||||
const uint8_t csPin = 10; // On ATmega328 boards, SPI Chip Select is usually pin 10. Change this to match your board.
|
||||
|
||||
// #########################################
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount of SPI traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println(F("SparkFun u-blox Example"));
|
||||
|
||||
spiPort.begin(); // begin the SPI port
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial
|
||||
|
||||
// Connect to the u-blox module using SPI port, csPin and speed setting
|
||||
// ublox devices generally work up to 5MHz. We'll use 4MHz for this example:
|
||||
if (myGNSS.begin(spiPort, csPin, 4000000) == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected on SPI bus. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults
|
||||
|
||||
myGNSS.setPortOutput(COM_PORT_SPI, COM_TYPE_UBX); //Set the SPI port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause SPI traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
Configuring the GNSS to automatically send position reports over SPI
|
||||
Based on code by: Nathan Seidle and Thorsten von Eicken
|
||||
SparkFun Electronics
|
||||
Date: January 3rd, 2019
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to configure the U-Blox GNSS the send navigation reports automatically
|
||||
and retrieving the latest one via getPVT. This eliminates the blocking in getPVT while the GNSS
|
||||
produces a fresh navigation solution at the expense of returning a slighly old solution.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
NEO-M8U: https://www.sparkfun.com/products/16329
|
||||
NEO-M9N: https://www.sparkfun.com/products/17285
|
||||
|
||||
Hardware Connections:
|
||||
You need to connect the SPI pins from your microcontroller to the specific pins on your SparkFun product.
|
||||
Connections will vary based on your microcontroller, but for reference please refer to this tutorial on SPI:
|
||||
https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi/all
|
||||
|
||||
Most new boards now use the terms:
|
||||
CS - Chip Select
|
||||
COPI - Controller Out, Peripheral In
|
||||
CIPO - Controller in, Peripheral Out
|
||||
SCK - Serial Clock
|
||||
|
||||
You can choose any pin for Chip Select, but the others are likely either defined by the library you are using
|
||||
(see here for the standard Arduino one: https://www.arduino.cc/en/reference/SPI) or the microcontroller. The
|
||||
ESP32 has two standard, selectable SPI ports, for example.
|
||||
|
||||
To enable SPI communication, you will need to solder the DSEL/SPI jumper closed on your u-blox board.
|
||||
|
||||
IMPORTANT: there have been reports that some u-blox devices do not respond to the UBX protocol over SPI
|
||||
with the factory settings. You may find you need to connect to the device via USB and u-center and set
|
||||
the incoming protocol to UBX only. Make sure you disable all other protocols as inputs if you can't
|
||||
get things to work! Hopefully this is just a bug in the u-blox firmware that will be fixed soon ;-)
|
||||
|
||||
*/
|
||||
|
||||
#include <SPI.h> //Needed for SPI to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
// #########################################
|
||||
|
||||
// Instantiate an instance of the SPI class.
|
||||
// Your configuration may be different, depending on the microcontroller you are using!
|
||||
|
||||
#define spiPort SPI // This is the SPI port on standard Ardino boards. Comment this line if you want to use a different port.
|
||||
|
||||
//SPIClass spiPort (HSPI); // This is the default SPI interface on some ESP32 boards. Uncomment this line if you are using ESP32.
|
||||
|
||||
// #########################################
|
||||
|
||||
const uint8_t csPin = 10; // On ATmega328 boards, SPI Chip Select is usually pin 10. Change this to match your board.
|
||||
|
||||
// #########################################
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
Serial.println("SparkFun u-blox Example");
|
||||
|
||||
spiPort.begin(); // begin the SPI port
|
||||
|
||||
//myGNSS.enableDebugging(); // Uncomment this line to see helpful debug messages on Serial
|
||||
|
||||
// Connect to the u-blox module using SPI port, csPin and speed setting
|
||||
// ublox devices generally work up to 5MHz. We'll use 4MHz for this example:
|
||||
if (myGNSS.begin(spiPort, csPin, 4000000) == false)
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected on SPI bus. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
//myGNSS.factoryDefault(); delay(5000); // Uncomment this line to reset the module back to its factory defaults
|
||||
|
||||
myGNSS.setPortOutput(COM_PORT_SPI, COM_TYPE_UBX); //Set the SPI port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); //Save (only) the communications port settings to flash and BBR
|
||||
|
||||
myGNSS.setNavigationFrequency(2); //Produce two solutions per second
|
||||
myGNSS.setAutoPVT(true); //Tell the GNSS to "send" each solution
|
||||
//myGNSS.saveConfiguration(); //Optional: Save _all_ the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Calling getPVT returns true if there actually is a fresh navigation solution available.
|
||||
// Start the reading only when valid LLH is available
|
||||
if (myGNSS.getPVT() && (myGNSS.getInvalidLlh() == false))
|
||||
{
|
||||
Serial.println();
|
||||
long latitude = myGNSS.getLatitude();
|
||||
Serial.print(F("Lat: "));
|
||||
Serial.print(latitude);
|
||||
|
||||
long longitude = myGNSS.getLongitude();
|
||||
Serial.print(F(" Long: "));
|
||||
Serial.print(longitude);
|
||||
Serial.print(F(" (degrees * 10^-7)"));
|
||||
|
||||
long altitude = myGNSS.getAltitude();
|
||||
Serial.print(F(" Alt: "));
|
||||
Serial.print(altitude);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
byte SIV = myGNSS.getSIV();
|
||||
Serial.print(F(" SIV: "));
|
||||
Serial.print(SIV);
|
||||
|
||||
int PDOP = myGNSS.getPDOP();
|
||||
Serial.print(F(" PDOP: "));
|
||||
Serial.print(PDOP);
|
||||
Serial.print(F(" (10^-2)"));
|
||||
|
||||
int nedNorthVel = myGNSS.getNedNorthVel();
|
||||
Serial.print(F(" VelN: "));
|
||||
Serial.print(nedNorthVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int nedEastVel = myGNSS.getNedEastVel();
|
||||
Serial.print(F(" VelE: "));
|
||||
Serial.print(nedEastVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int nedDownVel = myGNSS.getNedDownVel();
|
||||
Serial.print(F(" VelD: "));
|
||||
Serial.print(nedDownVel);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int verticalAccEst = myGNSS.getVerticalAccEst();
|
||||
Serial.print(F(" VAccEst: "));
|
||||
Serial.print(verticalAccEst);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
int horizontalAccEst = myGNSS.getHorizontalAccEst();
|
||||
Serial.print(F(" HAccEst: "));
|
||||
Serial.print(horizontalAccEst);
|
||||
Serial.print(F(" (mm)"));
|
||||
|
||||
int speedAccEst = myGNSS.getSpeedAccEst();
|
||||
Serial.print(F(" SpeedAccEst: "));
|
||||
Serial.print(speedAccEst);
|
||||
Serial.print(F(" (mm/s)"));
|
||||
|
||||
int headAccEst = myGNSS.getHeadingAccEst();
|
||||
Serial.print(F(" HeadAccEst: "));
|
||||
Serial.print(headAccEst);
|
||||
Serial.print(F(" (degrees * 10^-5)"));
|
||||
|
||||
if (myGNSS.getHeadVehValid() == true) {
|
||||
int headVeh = myGNSS.getHeadVeh();
|
||||
Serial.print(F(" HeadVeh: "));
|
||||
Serial.print(headVeh);
|
||||
Serial.print(F(" (degrees * 10^-5)"));
|
||||
|
||||
int magDec = myGNSS.getMagDec();
|
||||
Serial.print(F(" MagDec: "));
|
||||
Serial.print(magDec);
|
||||
Serial.print(F(" (degrees * 10^-2)"));
|
||||
|
||||
int magAcc = myGNSS.getMagAcc();
|
||||
Serial.print(F(" MagAcc: "));
|
||||
Serial.print(magAcc);
|
||||
Serial.print(F(" (degrees * 10^-2)"));
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(".");
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
Get the high precision geodetic solution for latitude and longitude
|
||||
By: Nathan Seidle
|
||||
Modified by: Steven Rowland and Paul Clark
|
||||
SparkFun Electronics
|
||||
Date: April 17th, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to inspect the accuracy of the high-precision
|
||||
positional solution. Please see below for information about the units.
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and a BlackBoard
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> //Needed for I2C to GNSS
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
|
||||
Wire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(Serial);
|
||||
|
||||
if (myGNSS.begin(Wire) == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1);
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
myGNSS.setNavigationFrequency(20); //Set output to 20 times a second
|
||||
|
||||
byte rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
|
||||
Serial.print("Current update rate: ");
|
||||
Serial.println(rate);
|
||||
|
||||
//myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second. Doing it more often will just cause I2C traffic.
|
||||
//The module only responds when a new position is available
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
// getHighResLatitude: returns the latitude from HPPOSLLH as an int32_t in degrees * 10^-7
|
||||
// getHighResLatitudeHp: returns the high resolution component of latitude from HPPOSLLH as an int8_t in degrees * 10^-9
|
||||
// getHighResLongitude: returns the longitude from HPPOSLLH as an int32_t in degrees * 10^-7
|
||||
// getHighResLongitudeHp: returns the high resolution component of longitude from HPPOSLLH as an int8_t in degrees * 10^-9
|
||||
// getElipsoid: returns the height above ellipsoid as an int32_t in mm
|
||||
// getElipsoidHp: returns the high resolution component of the height above ellipsoid as an int8_t in mm * 10^-1
|
||||
// getMeanSeaLevel: returns the height above mean sea level as an int32_t in mm
|
||||
// getMeanSeaLevelHp: returns the high resolution component of the height above mean sea level as an int8_t in mm * 10^-1
|
||||
// getHorizontalAccuracy: returns the horizontal accuracy estimate from HPPOSLLH as an uint32_t in mm * 10^-1
|
||||
|
||||
// If you want to use the high precision latitude and longitude with the full 9 decimal places
|
||||
// you will need to use a 64-bit double - which is not supported on all platforms
|
||||
|
||||
// To allow this example to run on standard platforms, we cheat by converting lat and lon to integer and fractional degrees
|
||||
|
||||
// The high resolution altitudes can be converted into standard 32-bit float
|
||||
|
||||
// First, let's collect the position data
|
||||
int32_t latitude = myGNSS.getHighResLatitude();
|
||||
int8_t latitudeHp = myGNSS.getHighResLatitudeHp();
|
||||
int32_t longitude = myGNSS.getHighResLongitude();
|
||||
int8_t longitudeHp = myGNSS.getHighResLongitudeHp();
|
||||
int32_t ellipsoid = myGNSS.getElipsoid();
|
||||
int8_t ellipsoidHp = myGNSS.getElipsoidHp();
|
||||
int32_t msl = myGNSS.getMeanSeaLevel();
|
||||
int8_t mslHp = myGNSS.getMeanSeaLevelHp();
|
||||
uint32_t accuracy = myGNSS.getHorizontalAccuracy();
|
||||
|
||||
// Defines storage for the lat and lon units integer and fractional parts
|
||||
int32_t lat_int; // Integer part of the latitude in degrees
|
||||
int32_t lat_frac; // Fractional part of the latitude
|
||||
int32_t lon_int; // Integer part of the longitude in degrees
|
||||
int32_t lon_frac; // Fractional part of the longitude
|
||||
|
||||
// Calculate the latitude and longitude integer and fractional parts
|
||||
lat_int = latitude / 10000000; // Convert latitude from degrees * 10^-7 to Degrees
|
||||
lat_frac = latitude - (lat_int * 10000000); // Calculate the fractional part of the latitude
|
||||
lat_frac = (lat_frac * 100) + latitudeHp; // Now add the high resolution component
|
||||
if (lat_frac < 0) // If the fractional part is negative, remove the minus sign
|
||||
{
|
||||
lat_frac = 0 - lat_frac;
|
||||
}
|
||||
lon_int = longitude / 10000000; // Convert latitude from degrees * 10^-7 to Degrees
|
||||
lon_frac = longitude - (lon_int * 10000000); // Calculate the fractional part of the longitude
|
||||
lon_frac = (lon_frac * 100) + longitudeHp; // Now add the high resolution component
|
||||
if (lon_frac < 0) // If the fractional part is negative, remove the minus sign
|
||||
{
|
||||
lon_frac = 0 - lon_frac;
|
||||
}
|
||||
|
||||
// Print the lat and lon
|
||||
Serial.print("Lat (deg): ");
|
||||
Serial.print(lat_int); // Print the integer part of the latitude
|
||||
Serial.print(".");
|
||||
printFractional(lat_frac, 9); // Print the fractional part of the latitude with leading zeros
|
||||
Serial.print(", Lon (deg): ");
|
||||
Serial.print(lon_int); // Print the integer part of the latitude
|
||||
Serial.print(".");
|
||||
printFractional(lon_frac, 9); // Print the fractional part of the latitude with leading zeros
|
||||
Serial.println();
|
||||
|
||||
// Now define float storage for the heights and accuracy
|
||||
float f_ellipsoid;
|
||||
float f_msl;
|
||||
float f_accuracy;
|
||||
|
||||
// Calculate the height above ellipsoid in mm * 10^-1
|
||||
f_ellipsoid = (ellipsoid * 10) + ellipsoidHp;
|
||||
// Now convert to m
|
||||
f_ellipsoid = f_ellipsoid / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Calculate the height above mean sea level in mm * 10^-1
|
||||
f_msl = (msl * 10) + mslHp;
|
||||
// Now convert to m
|
||||
f_msl = f_msl / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Convert the horizontal accuracy (mm * 10^-1) to a float
|
||||
f_accuracy = accuracy;
|
||||
// Now convert to m
|
||||
f_accuracy = f_accuracy / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Finally, do the printing
|
||||
Serial.print("Ellipsoid (m): ");
|
||||
Serial.print(f_ellipsoid, 4); // Print the ellipsoid with 4 decimal places
|
||||
|
||||
Serial.print(", Mean Sea Level(m): ");
|
||||
Serial.print(f_msl, 4); // Print the mean sea level with 4 decimal places
|
||||
|
||||
Serial.print(", Accuracy (m): ");
|
||||
Serial.println(f_accuracy, 4); // Print the accuracy with 4 decimal places
|
||||
}
|
||||
}
|
||||
|
||||
// Pretty-print the fractional part with leading zeros - without using printf
|
||||
// (Only works with positive numbers)
|
||||
void printFractional(int32_t fractional, uint8_t places)
|
||||
{
|
||||
if (places > 1)
|
||||
{
|
||||
for (uint8_t place = places - 1; place > 0; place--)
|
||||
{
|
||||
if (fractional < pow(10, place))
|
||||
{
|
||||
Serial.print("0");
|
||||
}
|
||||
}
|
||||
}
|
||||
Serial.print(fractional);
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Get the high precision geodetic solution for latitude and longitude using double
|
||||
By: Nathan Seidle
|
||||
Modified by: Paul Clark (PaulZC)
|
||||
SparkFun Electronics
|
||||
Date: April 17th, 2020
|
||||
License: MIT. See license file for more information but you can
|
||||
basically do whatever you want with this code.
|
||||
|
||||
This example shows how to inspect the accuracy of the high-precision
|
||||
positional solution. Please see below for information about the units.
|
||||
|
||||
** This example will only work correctly on platforms which support 64-bit double **
|
||||
|
||||
Feel like supporting open source hardware?
|
||||
Buy a board from SparkFun!
|
||||
ZED-F9P RTK2: https://www.sparkfun.com/products/15136
|
||||
NEO-M8P RTK: https://www.sparkfun.com/products/15005
|
||||
|
||||
Hardware Connections:
|
||||
Plug a Qwiic cable into the GNSS and (e.g.) a Redboard Artemis https://www.sparkfun.com/products/15444
|
||||
or an Artemis Thing Plus https://www.sparkfun.com/products/15574
|
||||
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||
Open the serial monitor at 115200 baud to see the output
|
||||
*/
|
||||
|
||||
#include <Wire.h> // Needed for I2C to GNSS
|
||||
|
||||
#define myWire Wire // This will work on the Redboard Artemis and the Artemis Thing Plus using Qwiic
|
||||
//#define myWire Wire1 // Uncomment this line if you are using the extra SCL1/SDA1 pins (D17 and D16) on the Thing Plus
|
||||
|
||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
|
||||
SFE_UBLOX_GNSS myGNSS;
|
||||
|
||||
long lastTime = 0; //Simple local timer. Limits amount if I2C traffic to u-blox module.
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); //Wait for user to open terminal
|
||||
|
||||
myWire.begin();
|
||||
|
||||
//myGNSS.enableDebugging(Serial); // Uncomment this line to enable debug messages
|
||||
|
||||
if (myGNSS.begin(myWire) == false) //Connect to the u-blox module using Wire port
|
||||
{
|
||||
Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Check that this platform supports 64-bit (8 byte) double
|
||||
if (sizeof(double) < 8)
|
||||
{
|
||||
Serial.println(F("Warning! Your platform does not support 64-bit double."));
|
||||
Serial.println(F("The latitude and longitude will be inaccurate."));
|
||||
}
|
||||
|
||||
myGNSS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise)
|
||||
|
||||
//myGNSS.setNavigationFrequency(20); //Set output to 20 times a second
|
||||
|
||||
byte rate = myGNSS.getNavigationFrequency(); //Get the update rate of this module
|
||||
Serial.print("Current update rate: ");
|
||||
Serial.println(rate);
|
||||
|
||||
//myGNSS.saveConfiguration(); //Save the current settings to flash and BBR
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//Query module only every second.
|
||||
//The module only responds when a new position is available.
|
||||
if (millis() - lastTime > 1000)
|
||||
{
|
||||
lastTime = millis(); //Update the timer
|
||||
|
||||
// getHighResLatitude: returns the latitude from HPPOSLLH as an int32_t in degrees * 10^-7
|
||||
// getHighResLatitudeHp: returns the high resolution component of latitude from HPPOSLLH as an int8_t in degrees * 10^-9
|
||||
// getHighResLongitude: returns the longitude from HPPOSLLH as an int32_t in degrees * 10^-7
|
||||
// getHighResLongitudeHp: returns the high resolution component of longitude from HPPOSLLH as an int8_t in degrees * 10^-9
|
||||
// getElipsoid: returns the height above ellipsoid as an int32_t in mm
|
||||
// getElipsoidHp: returns the high resolution component of the height above ellipsoid as an int8_t in mm * 10^-1
|
||||
// getMeanSeaLevel: returns the height above mean sea level as an int32_t in mm
|
||||
// getMeanSeaLevelHp: returns the high resolution component of the height above mean sea level as an int8_t in mm * 10^-1
|
||||
// getHorizontalAccuracy: returns the horizontal accuracy estimate from HPPOSLLH as an uint32_t in mm * 10^-1
|
||||
|
||||
// First, let's collect the position data
|
||||
int32_t latitude = myGNSS.getHighResLatitude();
|
||||
int8_t latitudeHp = myGNSS.getHighResLatitudeHp();
|
||||
int32_t longitude = myGNSS.getHighResLongitude();
|
||||
int8_t longitudeHp = myGNSS.getHighResLongitudeHp();
|
||||
int32_t ellipsoid = myGNSS.getElipsoid();
|
||||
int8_t ellipsoidHp = myGNSS.getElipsoidHp();
|
||||
int32_t msl = myGNSS.getMeanSeaLevel();
|
||||
int8_t mslHp = myGNSS.getMeanSeaLevelHp();
|
||||
uint32_t accuracy = myGNSS.getHorizontalAccuracy();
|
||||
|
||||
// Defines storage for the lat and lon as double
|
||||
double d_lat; // latitude
|
||||
double d_lon; // longitude
|
||||
|
||||
// Assemble the high precision latitude and longitude
|
||||
d_lat = ((double)latitude) / 10000000.0; // Convert latitude from degrees * 10^-7 to degrees
|
||||
d_lat += ((double)latitudeHp) / 1000000000.0; // Now add the high resolution component (degrees * 10^-9 )
|
||||
d_lon = ((double)longitude) / 10000000.0; // Convert longitude from degrees * 10^-7 to degrees
|
||||
d_lon += ((double)longitudeHp) / 1000000000.0; // Now add the high resolution component (degrees * 10^-9 )
|
||||
|
||||
// Print the lat and lon
|
||||
Serial.print("Lat (deg): ");
|
||||
Serial.print(d_lat, 9);
|
||||
Serial.print(", Lon (deg): ");
|
||||
Serial.print(d_lon, 9);
|
||||
|
||||
// Now define float storage for the heights and accuracy
|
||||
float f_ellipsoid;
|
||||
float f_msl;
|
||||
float f_accuracy;
|
||||
|
||||
// Calculate the height above ellipsoid in mm * 10^-1
|
||||
f_ellipsoid = (ellipsoid * 10) + ellipsoidHp;
|
||||
// Now convert to m
|
||||
f_ellipsoid = f_ellipsoid / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Calculate the height above mean sea level in mm * 10^-1
|
||||
f_msl = (msl * 10) + mslHp;
|
||||
// Now convert to m
|
||||
f_msl = f_msl / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Convert the horizontal accuracy (mm * 10^-1) to a float
|
||||
f_accuracy = accuracy;
|
||||
// Now convert to m
|
||||
f_accuracy = f_accuracy / 10000.0; // Convert from mm * 10^-1 to m
|
||||
|
||||
// Finally, do the printing
|
||||
Serial.print(", Ellipsoid (m): ");
|
||||
Serial.print(f_ellipsoid, 4); // Print the ellipsoid with 4 decimal places
|
||||
|
||||
Serial.print(", Mean Sea Level (m): ");
|
||||
Serial.print(f_msl, 4); // Print the mean sea level with 4 decimal places
|
||||
|
||||
Serial.print(", Accuracy (m): ");
|
||||
Serial.println(f_accuracy, 4); // Print the accuracy with 4 decimal places
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue