Skip to content

Convert to polymorphic class #207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
}
21 changes: 18 additions & 3 deletions src/SparkFun_u-blox_GNSS_Arduino_Library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2288,13 +2288,18 @@ bool SFE_UBLOX_GNSS::processThisNMEA()
// This is the default or generic NMEA processor. We're only going to pipe the data to serial port so we can see it.
// User could overwrite this function to pipe characters to nmea.process(c) of tinyGPS or MicroNMEA
// Or user could pipe each character to a buffer, radio, etc.
void SFE_UBLOX_GNSS::processNMEA(char incoming)
void SFE_UBLOX_GNSS::processNMEA_v(char incoming)
{
// If user has assigned an output port then pipe the characters there
if (_nmeaOutputPort != NULL)
_nmeaOutputPort->write(incoming); // Echo this byte to the serial port
}

void SFE_UBLOX_GNSS::processNMEA(char incoming)
{
processNMEA_v(incoming);
}

#ifndef SFE_UBLOX_DISABLE_AUTO_NMEA
// Check if the NMEA message (in nmeaAddressField) is "auto" (i.e. has RAM allocated for it)
bool SFE_UBLOX_GNSS::isThisNMEAauto()
Expand Down Expand Up @@ -2882,7 +2887,7 @@ nmeaAutomaticFlags *SFE_UBLOX_GNSS::getNMEAFlagsPtr()
// Byte 2: 10-bits of length of this packet including the first two-ish header bytes, + 6.
// byte 3 + 4 bits: Msg type 12 bits
// Example: D3 00 7C 43 F0 ... / 0x7C = 124+6 = 130 bytes in this packet, 0x43F = Msg type 1087
SFE_UBLOX_GNSS::sfe_ublox_sentence_types_e SFE_UBLOX_GNSS::processRTCMframe(uint8_t incoming, uint16_t *rtcmFrameCounter)
SFE_UBLOX_GNSS::sfe_ublox_sentence_types_e SFE_UBLOX_GNSS::processRTCMframe_v(uint8_t incoming, uint16_t *rtcmFrameCounter)
{
static uint16_t rtcmLen = 0;

Expand Down Expand Up @@ -2912,10 +2917,15 @@ SFE_UBLOX_GNSS::sfe_ublox_sentence_types_e SFE_UBLOX_GNSS::processRTCMframe(uint
return (*rtcmFrameCounter == rtcmLen) ? SFE_UBLOX_SENTENCE_TYPE_NONE : SFE_UBLOX_SENTENCE_TYPE_RTCM;
}

SFE_UBLOX_GNSS::sfe_ublox_sentence_types_e SFE_UBLOX_GNSS::processRTCMframe(uint8_t incoming, uint16_t *rtcmFrameCounter)
{
return processRTCMframe_v(incoming, rtcmFrameCounter);
}

// This function is called for each byte of an RTCM frame
// Ths user can overwrite this function and process the RTCM frame as they please
// Bytes can be piped to Serial or other interface. The consumer could be a radio or the internet (Ntrip broadcaster)
void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming)
void SFE_UBLOX_GNSS::processRTCM_v(uint8_t incoming)
{
// Radio.sendReliable((String)incoming); //An example of passing this byte to a radio

Expand All @@ -2930,6 +2940,11 @@ void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming)
(void)incoming; // Do something with incoming just to get rid of the pesky compiler warning!
}

void SFE_UBLOX_GNSS::processRTCM(uint8_t incoming)
{
processRTCM_v(incoming);
}

// Given a character, file it away into the uxb packet structure
// Set valid to VALID or NOT_VALID once sentence is completely received and passes or fails CRC
// The payload portion of the packet can be 100s of bytes but the max array size is packetCfgPayloadSize bytes.
Expand Down
5 changes: 4 additions & 1 deletion src/SparkFun_u-blox_GNSS_Arduino_Library.h
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ class SFE_UBLOX_GNSS
{
public:
SFE_UBLOX_GNSS(void);
~SFE_UBLOX_GNSS(void);
virtual ~SFE_UBLOX_GNSS(void);

// Depending on the sentence type the processor will load characters into different arrays
enum sfe_ublox_sentence_types_e
Expand Down Expand Up @@ -764,8 +764,11 @@ class SFE_UBLOX_GNSS

void process(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Processes NMEA and UBX binary sentences one byte at a time
void processNMEA(char incoming) __attribute__((weak)); // Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries
virtual void processNMEA_v(char incoming); // Given a NMEA character, do something with it. User can overwrite if desired to use something like tinyGPS or MicroNMEA libraries
sfe_ublox_sentence_types_e processRTCMframe(uint8_t incoming, uint16_t *rtcmFrameCounter) __attribute__((weak)); // Monitor the incoming bytes for start and length bytes
virtual sfe_ublox_sentence_types_e processRTCMframe_v(uint8_t incoming, uint16_t *rtcmFrameCounter); // Monitor the incoming bytes for start and length bytes
void processRTCM(uint8_t incoming) __attribute__((weak)); // Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc.
virtual void processRTCM_v(uint8_t incoming); // Given rtcm byte, do something with it. User can overwrite if desired to pipe bytes to radio, internet, etc.
void processUBX(uint8_t incoming, ubxPacket *incomingUBX, uint8_t requestedClass, uint8_t requestedID); // Given a character, file it away into the uxb packet structure
void processUBXpacket(ubxPacket *msg); // Once a packet has been received and validated, identify this packet's class/id and update internal flags

Expand Down