Create Example19_LBand_Corrections_with_NEO-D9S.ino
This commit is contained in:
+199
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
Use the NEO-D9S L-Band receiver to provide corrections to a ZED-F9x via UBX-RXM-PMP messages
|
||||||
|
By: SparkFun Electronics / Paul Clark
|
||||||
|
Based on original code by: u-blox AG / Michael Ammann
|
||||||
|
Date: February 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 obtain SPARTN correction data from a NEO-D9S L-Band receiver and push it over I2C to a ZED-F9x.
|
||||||
|
|
||||||
|
This is a proof of concept to show how the UBX-RXM-PMP corrections control the accuracy.
|
||||||
|
|
||||||
|
Feel like supporting open source hardware?
|
||||||
|
Buy a board from SparkFun!
|
||||||
|
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
|
||||||
|
NEO-D9S: Coming soon!
|
||||||
|
|
||||||
|
Hardware Connections:
|
||||||
|
Use Qwiic cables to connect the NEO-D9S and ZED-F9x GNSS 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 myGNSS; // ZED-F9x
|
||||||
|
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: pushRXMPMP 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 setAutoRXMPMPcallbackPtr
|
||||||
|
// / _____ This _must_ be UBX_RXM_PMP_data_t
|
||||||
|
// | / _____ You can use any name you like for the struct
|
||||||
|
// | | /
|
||||||
|
// | | |
|
||||||
|
void pushRXMPMP(UBX_RXM_PMP_data_t *pmpData)
|
||||||
|
{
|
||||||
|
//Push the PMP data to the GNSS
|
||||||
|
Serial.print(F("New RXM-PMP data received. Message version is 0x0"));
|
||||||
|
Serial.print(pmpData->version, HEX);
|
||||||
|
Serial.print(F(". numBytesUserData is "));
|
||||||
|
size_t numDataBytes = 504; // Version 0x00 messages always contain 504 bytes of userData
|
||||||
|
if (pmpData->version == 0x01)
|
||||||
|
numDataBytes = pmpData->numBytesUserData;
|
||||||
|
Serial.print(numDataBytes);
|
||||||
|
Serial.println(F(". Pushing them to the GNSS..."));
|
||||||
|
|
||||||
|
myGNSS.pushRawData(pmpData->userData, numDataBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
|
||||||
|
// 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 setAutoPVTcallbackPtr
|
||||||
|
// / _____ 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)
|
||||||
|
{
|
||||||
|
long latitude = ubxDataStruct->lat; // Print the latitude
|
||||||
|
Serial.print(F("Lat: "));
|
||||||
|
Serial.print(latitude / 10000000L);
|
||||||
|
Serial.print(F("."));
|
||||||
|
Serial.print(abs(latitude % 10000000L));
|
||||||
|
|
||||||
|
long longitude = ubxDataStruct->lon; // Print the longitude
|
||||||
|
Serial.print(F(" Long: "));
|
||||||
|
Serial.print(longitude / 10000000L);
|
||||||
|
Serial.print(F("."));
|
||||||
|
Serial.print(abs(longitude % 10000000L));
|
||||||
|
|
||||||
|
long altitude = ubxDataStruct->hMSL; // Print the height above mean sea level
|
||||||
|
Serial.print(F(" Height: "));
|
||||||
|
Serial.print(altitude);
|
||||||
|
Serial.print(F(" (mm)"));
|
||||||
|
|
||||||
|
uint8_t fixType = ubxDataStruct->fixType; // Print the fix type
|
||||||
|
Serial.print(F(" Fix: "));
|
||||||
|
Serial.print(fixType);
|
||||||
|
if (fixType == 0)
|
||||||
|
Serial.print(F(" (None)"));
|
||||||
|
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 == 3)
|
||||||
|
Serial.print(F(" (GNSS + Dead Reckoning)"));
|
||||||
|
else if (fixType == 5)
|
||||||
|
Serial.print(F(" (Time Only)"));
|
||||||
|
else
|
||||||
|
Serial.print(F(" (UNKNOWN)"));
|
||||||
|
|
||||||
|
uint8_t carrSoln = ubxDataStruct->flags.bits.carrSoln; // Print the carrier solution
|
||||||
|
Serial.print(F(" Carrier Solution: "));
|
||||||
|
Serial.print(carrSoln);
|
||||||
|
if (carrSoln == 0)
|
||||||
|
Serial.print(F(" (None)"));
|
||||||
|
else if (carrSoln == 1)
|
||||||
|
Serial.print(F(" (Floating)"));
|
||||||
|
else if (carrSoln == 2)
|
||||||
|
Serial.print(F(" (Fixed)"));
|
||||||
|
else
|
||||||
|
Serial.print(F(" (UNKNOWN)"));
|
||||||
|
|
||||||
|
uint32_t hAcc = ubxDataStruct->hAcc; // Print the horizontal accuracy estimate
|
||||||
|
Serial.print(F(" Horizontal Accuracy Estimate: "));
|
||||||
|
Serial.print(hAcc);
|
||||||
|
Serial.print(F(" (mm)"));
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println(F("NEO-D9S SPARTN Corrections"));
|
||||||
|
|
||||||
|
Wire.begin(); //Start I2C
|
||||||
|
|
||||||
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
// Begin and configure the ZED-F9x
|
||||||
|
|
||||||
|
//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 module not detected at default I2C address. Please check wiring."));
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
Serial.println(F("u-blox GNSS 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); //Be sure SPARTN input is enabled
|
||||||
|
|
||||||
|
myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible
|
||||||
|
|
||||||
|
myGNSS.setNavigationFrequency(1); //Set output in Hz.
|
||||||
|
|
||||||
|
myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed
|
||||||
|
|
||||||
|
//myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM
|
||||||
|
|
||||||
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
// 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.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port
|
||||||
|
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1
|
||||||
|
if (ok) ok = myLBand.setVal(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.setAutoRXMPMPcallbackPtr(&pushRXMPMP); // Call pushRXMPMP when new PMP data arrives. Push it to the GNSS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
myGNSS.checkUblox(); // Check for the arrival of new GNSS data and process it.
|
||||||
|
myGNSS.checkCallbacks(); // Check if any GNSS callbacks are waiting to be processed.
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user