| 
 | 1 | +/*  | 
 | 2 | +  Get the RTCM 1005 sentence using a callback  | 
 | 3 | +  By: Paul Clark  | 
 | 4 | +  SparkFun Electronics  | 
 | 5 | +  Date: May 4th, 2023  | 
 | 6 | +  License: MIT. See license file for more information.  | 
 | 7 | +
  | 
 | 8 | +  This example shows how to perform a survey-in and then enable RTCM sentences over I2C.  | 
 | 9 | +  It then demonstrates how to use a callback to retrieve the latest RTCM 1005 message.  | 
 | 10 | +
  | 
 | 11 | +  Feel like supporting open source hardware?  | 
 | 12 | +  Buy a board from SparkFun!  | 
 | 13 | +  SparkFun GPS-RTK2 - ZED-F9P (GPS-15136)    https://www.sparkfun.com/products/15136  | 
 | 14 | +  SparkFun GPS-RTK-SMA - ZED-F9P (GPS-16481) https://www.sparkfun.com/products/16481  | 
 | 15 | +
  | 
 | 16 | +  Hardware Connections:  | 
 | 17 | +  Plug a Qwiic cable into the GNSS and a RedBoard  | 
 | 18 | +  If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)  | 
 | 19 | +  Open the serial monitor at 115200 baud to see the output  | 
 | 20 | +*/  | 
 | 21 | + | 
 | 22 | +#include <Wire.h> //Needed for I2C to GNSS  | 
 | 23 | + | 
 | 24 | +#include <SparkFun_u-blox_GNSS_v3.h> //Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS_v3  | 
 | 25 | +SFE_UBLOX_GNSS myGNSS;  | 
 | 26 | + | 
 | 27 | +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 28 | + | 
 | 29 | +// Callback: newRTCM1005 will be called when new RTCM 1005 data arrives  | 
 | 30 | +// See u-blox_structs.h for the full definition of RTCM_1005_data_t  | 
 | 31 | +//         _____  You can use any name you like for the callback. Use the same name when you call setRTCM1005callbackPtr  | 
 | 32 | +//        /             _____  This _must_ be RTCM_1005_data_t  | 
 | 33 | +//        |            /                _____ You can use any name you like for the struct  | 
 | 34 | +//        |            |               /  | 
 | 35 | +//        |            |               |  | 
 | 36 | +void newRTCM1005(RTCM_1005_data_t *rtcmStruct)  | 
 | 37 | +{  | 
 | 38 | +  Serial.println();  | 
 | 39 | + | 
 | 40 | +  double x = rtcmStruct->AntennaReferencePointECEFX;  | 
 | 41 | +  x /= 10000.0; // Convert to m  | 
 | 42 | +  double y = rtcmStruct->AntennaReferencePointECEFY;  | 
 | 43 | +  y /= 10000.0; // Convert to m  | 
 | 44 | +  double z = rtcmStruct->AntennaReferencePointECEFZ;  | 
 | 45 | +  z /= 10000.0; // Convert to m  | 
 | 46 | + | 
 | 47 | +  Serial.print(F("New RTCM "));  | 
 | 48 | +  Serial.print(rtcmStruct->MessageNumber);  | 
 | 49 | +  Serial.print(F(" data:  ARP ECEF-X: "));  | 
 | 50 | +  Serial.print(x, 4); // 4 decimal places  | 
 | 51 | +  Serial.print(F("  Y: "));  | 
 | 52 | +  Serial.print(y, 4); // 4 decimal places  | 
 | 53 | +  Serial.print(F("  Z: "));  | 
 | 54 | +  Serial.print(z, 4); // 4 decimal places  | 
 | 55 | + | 
 | 56 | +  Serial.println();  | 
 | 57 | +}  | 
 | 58 | + | 
 | 59 | +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 60 | + | 
 | 61 | +void setup()  | 
 | 62 | +{  | 
 | 63 | + | 
 | 64 | +  delay(1000);  | 
 | 65 | + | 
 | 66 | +  Serial.begin(115200);  | 
 | 67 | +  Serial.println(F("SparkFun u-blox GNSS Example"));  | 
 | 68 | + | 
 | 69 | +  Wire.begin();  | 
 | 70 | + | 
 | 71 | +  //myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial  | 
 | 72 | + | 
 | 73 | +  while (myGNSS.begin() == false)  | 
 | 74 | +  {  | 
 | 75 | +    Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring."));  | 
 | 76 | +    delay(1000);  | 
 | 77 | +  }  | 
 | 78 | + | 
 | 79 | +  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 80 | + | 
 | 81 | +  //We need to do a survey-in before the ZED will generate RTCM 1005  | 
 | 82 | + | 
 | 83 | +  //Check if Survey is in Progress before initiating one  | 
 | 84 | +  bool response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (request can take a long time)  | 
 | 85 | +    | 
 | 86 | +  if (response == false) // Check if fresh data was received  | 
 | 87 | +  {  | 
 | 88 | +    Serial.println(F("Failed to get Survey In status. Freezing..."));  | 
 | 89 | +    while (1); //Freeze  | 
 | 90 | +  }  | 
 | 91 | + | 
 | 92 | +  if (myGNSS.getSurveyInActive() == true) // Use the helper function  | 
 | 93 | +  {  | 
 | 94 | +    Serial.print(F("Survey already in progress."));  | 
 | 95 | +  }  | 
 | 96 | +  else  | 
 | 97 | +  {  | 
 | 98 | +    //Start survey - define the minimum observationTime and requiredAccuracy  | 
 | 99 | +    uint32_t observationTime = 60; float requiredAccuracy = 5.0; //  60 seconds, 5.0m  | 
 | 100 | +      | 
 | 101 | +    response = myGNSS.enableSurveyModeFull(observationTime, requiredAccuracy, VAL_LAYER_RAM); //Enable Survey in. Save setting in RAM layer only (not BBR)  | 
 | 102 | + | 
 | 103 | +    if (response == false)  | 
 | 104 | +    {  | 
 | 105 | +      Serial.println(F("Survey start failed. Freezing..."));  | 
 | 106 | +      while (1); //Freeze  | 
 | 107 | +    }  | 
 | 108 | + | 
 | 109 | +    Serial.println(F("Survey started."));  | 
 | 110 | +    Serial.print(F("This will run until "));  | 
 | 111 | +    Serial.print(observationTime);  | 
 | 112 | +    Serial.print(F("s have passed _and_ better than "));  | 
 | 113 | +    Serial.print(requiredAccuracy, 2);  | 
 | 114 | +    Serial.println(F("m accuracy is achieved."));  | 
 | 115 | +    Serial.println();  | 
 | 116 | +  }  | 
 | 117 | + | 
 | 118 | +  while(Serial.available()) Serial.read(); //Clear buffer  | 
 | 119 | +    | 
 | 120 | +  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 121 | + | 
 | 122 | +  //Wait for survey to complete  | 
 | 123 | + | 
 | 124 | +  while (myGNSS.getSurveyInValid() == false) // Call the helper function  | 
 | 125 | +  {  | 
 | 126 | +    if(Serial.available())  | 
 | 127 | +    {  | 
 | 128 | +      byte incoming = Serial.read();  | 
 | 129 | +      if (incoming == 'x')  | 
 | 130 | +      {  | 
 | 131 | +        //Stop survey mode  | 
 | 132 | +        response = myGNSS.disableSurveyMode(); //Disable survey  | 
 | 133 | +        Serial.println(F("Survey stopped"));  | 
 | 134 | +        break;  | 
 | 135 | +      }  | 
 | 136 | +    }  | 
 | 137 | + | 
 | 138 | +    response = myGNSS.getSurveyStatus(2000); //Query module for SVIN status with 2000ms timeout (req can take a long time)  | 
 | 139 | +      | 
 | 140 | +    if (response == true) // Check if fresh data was received  | 
 | 141 | +    {  | 
 | 142 | +      Serial.print(F("\r\nPress x to end survey - "));  | 
 | 143 | +      Serial.print(F("Time elapsed: "));  | 
 | 144 | +      Serial.print((String)myGNSS.getSurveyInObservationTimeFull()); // Call the helper function  | 
 | 145 | +      Serial.print(F(" ("));  | 
 | 146 | +      Serial.print((String)myGNSS.packetUBXNAVSVIN->data.dur); // Read the survey-in duration directly from packetUBXNAVSVIN  | 
 | 147 | + | 
 | 148 | +      Serial.print(F(") Accuracy: "));  | 
 | 149 | +      Serial.print((String)myGNSS.getSurveyInMeanAccuracy()); // Call the helper function  | 
 | 150 | +      Serial.print(F(" ("));  | 
 | 151 | +      // Read the mean accuracy directly from packetUBXNAVSVIN and manually convert from mm*0.1 to m  | 
 | 152 | +      float meanAcc = ((float)myGNSS.packetUBXNAVSVIN->data.meanAcc) / 10000.0;  | 
 | 153 | +      Serial.print((String)meanAcc);   | 
 | 154 | +      Serial.println(F(")"));  | 
 | 155 | +    }  | 
 | 156 | +    else  | 
 | 157 | +    {  | 
 | 158 | +      Serial.println(F("\r\nSVIN request failed"));  | 
 | 159 | +    }  | 
 | 160 | +  }  | 
 | 161 | + | 
 | 162 | +  Serial.println(F("Base survey complete. Configuring RTCM."));  | 
 | 163 | + | 
 | 164 | +  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 165 | + | 
 | 166 | +  //Disable or enable various RTCM sentences over the I2C interface  | 
 | 167 | + | 
 | 168 | +  myGNSS.setI2COutput(COM_TYPE_NMEA | COM_TYPE_UBX | COM_TYPE_RTCM3); // Turn on UBX, NMEA and RTCM sentences on I2C  | 
 | 169 | + | 
 | 170 | +  myGNSS.newCfgValset(VAL_LAYER_RAM); // Use cfgValset to disable / enable individual RTCM messages. Save setting in RAM layer only (not BBR)  | 
 | 171 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1005_I2C, 1); // Enable RTCM 1005 (Stationary Antenna Reference Point, No Height Information) at current navigation rate  | 
 | 172 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1074_I2C, 1); // Enable RTCM 1074 (GPS MSM4). RTCM 1077 (GPS MSM7) is higher resolution but is almost twice as many bytes  | 
 | 173 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1084_I2C, 1); // Enable RTCM 1084 (GLONASS MSM4). RTCM 1087 (GLONASS MSM7) is higher resolution  | 
 | 174 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1094_I2C, 1); // Enable RTCM 1094 (Galileo MSM4). RTCM 1097 (Galileo MSM7) is higher resolution  | 
 | 175 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1124_I2C, 1); // Enable RTCM 1124 (BeiDou MSM4). RTCM 1127 (BeiDou MSM7) is higher resolution  | 
 | 176 | +  myGNSS.addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_I2C, 10); // Enable RTCM message 1230 (GLONASS L1 and L2 Code-Phase Biases) every 10 seconds  | 
 | 177 | +  if (myGNSS.sendCfgValset()) // Send the configuration VALSET  | 
 | 178 | +    Serial.println(F("RTCM messages were configured successfully"));  | 
 | 179 | +  else  | 
 | 180 | +    Serial.println(F("RTCM message configuration failed!"));  | 
 | 181 | + | 
 | 182 | +  //myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save only the ioPort and message settings to NVM  | 
 | 183 | + | 
 | 184 | +  //myGNSS.setRTCMOutputPort(Serial); // Uncomment this line to echo all RTCM data to Serial for debugging  | 
 | 185 | + | 
 | 186 | +  myGNSS.setRTCM1005callbackPtr(&newRTCM1005); //Set up the callback  | 
 | 187 | + | 
 | 188 | +  if (sizeof(double) != 8) // Check double is 64-bit  | 
 | 189 | +    Serial.println(F("double is not 64-bit. ECEF resolution may be limited!"));  | 
 | 190 | +}  | 
 | 191 | + | 
 | 192 | +// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-  | 
 | 193 | + | 
 | 194 | +void loop()  | 
 | 195 | +{  | 
 | 196 | +  myGNSS.checkUblox(); // Check for the arrival of new data and process it.  | 
 | 197 | +  myGNSS.checkCallbacks(); // Check if any callbacks are waiting to be processed.  | 
 | 198 | + | 
 | 199 | +  Serial.print(".");  | 
 | 200 | +  delay(50);  | 
 | 201 | +}  | 
0 commit comments