Add the new callback example
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
The library includes a getLatestNMEAGNGGA function too.
|
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 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 GPGGA.
|
This example turns off all sentences except for GGA.
|
||||||
|
|
||||||
Feel like supporting open source hardware?
|
Feel like supporting open source hardware?
|
||||||
Buy a board from SparkFun!
|
Buy a board from SparkFun!
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Get the latest GPGGA / GNGGA NMEA sentence using callbacks
|
||||||
|
By: Paul Clark
|
||||||
|
SparkFun Electronics
|
||||||
|
Date: January 12th, 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 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.setNMEAGPGGAcallback(&printGPGGA);
|
||||||
|
|
||||||
|
// Set up the callback for GNGGA
|
||||||
|
myGNSS.setNMEAGNGGAcallback(&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);
|
||||||
|
}
|
||||||
@@ -1712,6 +1712,13 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r
|
|||||||
memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy
|
memset(nmeaPtr, 0, nmeaMaxLength); // Clear the working copy
|
||||||
memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy
|
memcpy(nmeaPtr, &nmeaAddressField[0], 6); // Copy the start character and address field into the working copy
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if ((_printDebug == true) || (_printLimitedDebug == true)) // This is important. Print this if doing limited debugging
|
||||||
|
// {
|
||||||
|
// _debugSerial->println(F("process: non-auto NMEA message"));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
// We've just received the end of the address field. Check if it is selected for logging
|
// We've just received the end of the address field. Check if it is selected for logging
|
||||||
if (logThisNMEA())
|
if (logThisNMEA())
|
||||||
@@ -1804,7 +1811,7 @@ void SFE_UBLOX_GNSS::process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t r
|
|||||||
nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags
|
nmeaAutomaticFlags *flagsPtr = getNMEAFlagsPtr(); // Get a pointer to the flags
|
||||||
nmeaAutomaticFlags flagsCopy = *flagsPtr;
|
nmeaAutomaticFlags flagsCopy = *flagsPtr;
|
||||||
flagsCopy.flags.bits.completeCopyValid = 1; // Set the complete copy valid flag
|
flagsCopy.flags.bits.completeCopyValid = 1; // Set the complete copy valid flag
|
||||||
flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read/stale flag
|
flagsCopy.flags.bits.completeCopyRead = 0; // Clear the complete copy read flag
|
||||||
*flagsPtr = flagsCopy; // Update the flags
|
*flagsPtr = flagsCopy; // Update the flags
|
||||||
// Callback
|
// Callback
|
||||||
if (doesThisNMEAHaveCallback()) // Do we need to copy the data into the callback copy?
|
if (doesThisNMEAHaveCallback()) // Do we need to copy the data into the callback copy?
|
||||||
@@ -4628,7 +4635,7 @@ void SFE_UBLOX_GNSS::checkCallbacks(void)
|
|||||||
if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage
|
if ((storageNMEAGPGGA != NULL) // If RAM has been allocated for message storage
|
||||||
&& (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data
|
&& (storageNMEAGPGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data
|
||||||
&& (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined
|
&& (storageNMEAGPGGA->callbackPointer != NULL) // If the pointer to the callback has been defined
|
||||||
&& (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == true)) // If the copy of the data is valid
|
&& (storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid
|
||||||
{
|
{
|
||||||
// if (_printDebug == true)
|
// if (_printDebug == true)
|
||||||
// _debugSerial->println(F("checkCallbacks: calling callback for GPGGA"));
|
// _debugSerial->println(F("checkCallbacks: calling callback for GPGGA"));
|
||||||
@@ -4636,6 +4643,17 @@ void SFE_UBLOX_GNSS::checkCallbacks(void)
|
|||||||
storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale
|
storageNMEAGPGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((storageNMEAGNGGA != NULL) // If RAM has been allocated for message storage
|
||||||
|
&& (storageNMEAGNGGA->callbackCopy != NULL) // If RAM has been allocated for the copy of the data
|
||||||
|
&& (storageNMEAGNGGA->callbackPointer != NULL) // If the pointer to the callback has been defined
|
||||||
|
&& (storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid == 1)) // If the copy of the data is valid
|
||||||
|
{
|
||||||
|
// if (_printDebug == true)
|
||||||
|
// _debugSerial->println(F("checkCallbacks: calling callback for GNGGA"));
|
||||||
|
storageNMEAGNGGA->callbackPointer(*storageNMEAGNGGA->callbackCopy); // Call the callback
|
||||||
|
storageNMEAGNGGA->automaticFlags.flags.bits.callbackCopyValid = 0; // Mark the data as stale
|
||||||
|
}
|
||||||
|
|
||||||
checkCallbacksReentrant = false;
|
checkCallbacksReentrant = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1345,7 +1345,7 @@ public:
|
|||||||
uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data
|
uint8_t getLatestNMEAGPGGA(NMEA_GGA_data_t *data); // Return the most recent GPGGA: 0 = no data, 1 = stale data, 2 = fresh data
|
||||||
bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message
|
bool setNMEAGPGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message
|
||||||
uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data
|
uint8_t getLatestNMEAGNGGA(NMEA_GGA_data_t *data); // Return the most recent GNGGA: 0 = no data, 1 = stale data, 2 = fresh data
|
||||||
bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GPGGA message
|
bool setNMEAGNGGAcallback(void (*callbackPointer)(NMEA_GGA_data_t)); //Enable a callback on the arrival of a GNGGA message
|
||||||
|
|
||||||
// Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket
|
// Functions to extract signed and unsigned 8/16/32-bit data from a ubxPacket
|
||||||
// From v2.0: These are public. The user can call these to extract data from custom packets
|
// From v2.0: These are public. The user can call these to extract data from custom packets
|
||||||
|
|||||||
@@ -2242,7 +2242,7 @@ struct nmeaAutomaticFlags
|
|||||||
uint8_t all;
|
uint8_t all;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid/stale, 1 = valid/fresh
|
uint8_t completeCopyValid : 1; // Is the copy of the data struct used by the get function valid/fresh? 0 = invalid, 1 = valid
|
||||||
uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read
|
uint8_t completeCopyRead : 1; // Has the complete copy been read? 0 = unread, 1 = read
|
||||||
uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? 0 = invalid/stale, 1 = valid/fresh
|
uint8_t callbackCopyValid : 1; // Is the copy of the data struct used by the callback valid/fresh? 0 = invalid/stale, 1 = valid/fresh
|
||||||
} bits;
|
} bits;
|
||||||
@@ -2280,5 +2280,4 @@ typedef struct
|
|||||||
NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy
|
NMEA_GGA_data_t *callbackCopy; // The callback gets its own preserved copy of the complete copy
|
||||||
} NMEA_GNGGA_t;
|
} NMEA_GNGGA_t;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user