Skip to content

v2.2.7 #130

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 15 commits into from
Mar 18, 2022
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
Expand Up @@ -93,27 +93,43 @@ void loop()
WiFiClientSecure wifiClient = WiFiClientSecure();
MqttClient mqttClient(wifiClient);

void mqttMessageHandler(int messageSize) {
uint8_t mgaData[512 * 4]; //Most incoming data is around 500 bytes but may be larger
int mgaCount = 0;
Serial.print(F("Pushed data from "));
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())
{
char ch = mqttClient.read();
//Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data
mgaData[mgaCount++] = ch;
if (mgaCount == sizeof(mgaData))
break;
}
uint16_t mqttCount = 0;

if (mgaCount > 0)
{
//Push MGA data to GNSS module over I2C
myGNSS.pushRawData(mgaData, mgaCount, false);
lastReceived_ms = millis();
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
Expand Down
2 changes: 1 addition & 1 deletion examples/Example30_NEO-D9S/Example30_NEO-D9S.ino
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Feel like supporting open source hardware?
Buy a board from SparkFun!
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
NEO-D9S: Coming soon!
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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
Expand All @@ -44,10 +45,137 @@
#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
#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

//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

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// 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)
{
double latitude = ubxDataStruct->lat; // Print the latitude
Serial.print(F("Lat: "));
Serial.print(latitude / 10000000.0, 7);

double longitude = ubxDataStruct->lon; // Print the longitude
Serial.print(F(" Long: "));
Serial.print(longitude / 10000000.0, 7);

double altitude = ubxDataStruct->hMSL; // Print the height above mean sea level
Serial.print(F(" Height: "));
Serial.print(altitude / 1000.0, 3);

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();
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// Callback: printRXMCOR will be called when new RXM COR data arrives
// See u-blox_structs.h for the full definition of UBX_RXM_COR_data_t
// _____ You can use any name you like for the callback. Use the same name when you call setRXMCORcallbackPtr
// / _____ This _must_ be UBX_RXM_COR_data_t
// | / _____ You can use any name you like for the struct
// | | /
// | | |
void printRXMCOR(UBX_RXM_COR_data_t *ubxDataStruct)
{
Serial.print(F("UBX-RXM-COR: ebno: "));
Serial.print(ubxDataStruct->ebno);

Serial.print(F(" protocol: "));
if (ubxDataStruct->statusInfo.bits.protocol == 1)
Serial.print(F("RTCM3"));
else if (ubxDataStruct->statusInfo.bits.protocol == 2)
Serial.print(F("SPARTN"));
else if (ubxDataStruct->statusInfo.bits.protocol == 29)
Serial.print(F("PMP (SPARTN)"));
else if (ubxDataStruct->statusInfo.bits.protocol == 30)
Serial.print(F("QZSSL6"));
else
Serial.print(F("Unknown"));

Serial.print(F(" errStatus: "));
if (ubxDataStruct->statusInfo.bits.errStatus == 1)
Serial.print(F("Error-free"));
else if (ubxDataStruct->statusInfo.bits.errStatus == 2)
Serial.print(F("Erroneous"));
else
Serial.print(F("Unknown"));

Serial.print(F(" msgUsed: "));
if (ubxDataStruct->statusInfo.bits.msgUsed == 1)
Serial.print(F("Not used"));
else if (ubxDataStruct->statusInfo.bits.msgUsed == 2)
Serial.print(F("Used"));
else
Serial.print(F("Unknown"));

Serial.print(F(" msgEncrypted: "));
if (ubxDataStruct->statusInfo.bits.msgEncrypted == 1)
Serial.print(F("Not encrypted"));
else if (ubxDataStruct->statusInfo.bits.msgEncrypted == 2)
Serial.print(F("Encrypted"));
else
Serial.print(F("Unknown"));

Serial.print(F(" msgDecrypted: "));
if (ubxDataStruct->statusInfo.bits.msgDecrypted == 1)
Serial.print(F("Not decrypted"));
else if (ubxDataStruct->statusInfo.bits.msgDecrypted == 2)
Serial.print(F("Successfully decrypted"));
else
Serial.print(F("Unknown"));

Serial.println();
}

//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

void setup()
Expand All @@ -58,17 +186,32 @@ void setup()

Wire.begin(); //Start I2C

if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
//myGNSS.enableDebugging(); // Uncomment this line to enable debug messages on Serial

while (myGNSS.begin() == false) //Connect to the u-blox 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 GNSS module not detected at default I2C address. Please check wiring."));
delay(2000);
}

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); // Be sure SPARTN input is enabled.

myGNSS.setNavigationFrequency(1); //Set output in Hz.
Serial.println(F("u-blox GNSS module connected"));

uint8_t ok = myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
if (ok) ok = myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN); // Be sure SPARTN input is enabled.

if (ok) ok = myGNSS.setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED); // Set the differential mode - ambiguities are fixed whenever possible
if (ok) ok = myGNSS.setNavigationFrequency(1); //Set output in Hz.
if (ok) ok = myGNSS.setVal8(UBLOX_CFG_SPARTN_USE_SOURCE, 0); // Use IP source (default). Change this to 1 for L-Band (PMP)

if (ok) ok = myGNSS.setAutoPVTcallbackPtr(&printPVTdata); // Enable automatic NAV PVT messages with callback to printPVTdata so we can watch the carrier solution go to fixed

if (ok) ok = myGNSS.setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C, 1); // Enable UBX-RXM-COR messages on I2C
if (ok) ok = myGNSS.setRXMCORcallbackPtr(&printRXMCOR); // Print the contents of UBX-RXM-COR messages so we can check if the SPARTN data is being decrypted successfully

//if (ok) ok = myGNSS.saveConfiguration(VAL_CFG_SUBSEC_IOPORT | VAL_CFG_SUBSEC_MSGCONF); //Optional: Save the ioPort and message settings to NVM

Serial.print(F("GNSS: configuration "));
Serial.println(OK(ok));

Serial.print(F("Connecting to local WiFi"));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Expand All @@ -81,45 +224,66 @@ void setup()
Serial.println(WiFi.localIP());

while (Serial.available()) Serial.read();

Serial.println(F("Press any key to start MQTT/SPARTN Client."));

}

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/SPARTN Client."));
}

Serial.println(F("Press any key to start MQTT/SPARTN Client."));

delay(1000);
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.
}

WiFiClientSecure wifiClient = WiFiClientSecure();
MqttClient mqttClient(wifiClient);

void mqttMessageHandler(int messageSize) {
uint8_t spartnData[512 * 4]; //Most incoming data is around 500 bytes but may be larger
int spartnCount = 0;
Serial.print(F("Pushed data from "));
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())
{
char ch = mqttClient.read();
//Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data
spartnData[spartnCount++] = ch;
if (spartnCount == sizeof(spartnData))
break;
}
uint16_t mqttCount = 0;

if (spartnCount > 0)
{
//Push KEYS or SPARTN data to GNSS module over I2C
myGNSS.pushRawData(spartnData, spartnCount, false);
lastReceived_ms = millis();
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 STARTN MQTT broker, receive RTCM, and push to ZED module over I2C
Expand Down Expand Up @@ -153,12 +317,14 @@ void beginClient()
mqttClient.onMessage(mqttMessageHandler);
mqttClient.subscribe(MQTT_TOPIC_KEY);
mqttClient.subscribe(MQTT_TOPIC_SPARTN);
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)
{
Expand All @@ -168,6 +334,9 @@ void beginClient()
return;
}

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.

delay(10);
}

Expand Down
10 changes: 7 additions & 3 deletions examples/ZED-F9P/Example18_PointPerfectClient/secrets.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@ 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.
// in the new PointPerfect Thing you go to the credentials page and copy paste 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 -> IP key distribution topic
const char MQTT_TOPIC_KEY[] = "/pp/key/ip";
const char MQTT_TOPIC_KEY[] = "/pp/ubx/0236/ip"; // This topic provides the IP only dynamic keys in UBX format
//const char MQTT_TOPIC_KEY[] = "/pp/ubx/0236/Lb"; // This topic provides the L-Band + IP dynamic keys in UBX format
// <Your PointPerfect Thing> -> Credentials -> IP correction topic for EU/US region
const char MQTT_TOPIC_SPARTN[] = "/pp/ip/us"; // choice of {eu, us}
const char MQTT_TOPIC_SPARTN[] = "/pp/ip/us"; // This topic provides the SPARTN corrections for IP only: choice of {eu, us}
//const char MQTT_TOPIC_SPARTN[] = "/pp/Lb/us"; // This topic provides the SPARTN corrections for L-Band and L-Band + IP: choice of {eu, us}
// <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>";
Expand Down
Loading