Skip to content

Commit 727e1b0

Browse files
authored
Merge pull request #129 from sparkfun/release_candidate
v2.2.6
2 parents a710360 + b54006e commit 727e1b0

File tree

11 files changed

+393
-1
lines changed

11 files changed

+393
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
Use ESP32 WiFi to get AssistNow Online (MGA) data from PointPerfect (broker) as a Client using MQTT
3+
By: Paul Clark / SparkFun
4+
Date: March 9th, 2022
5+
Based on original code by: u-blox AG / Michael Ammann
6+
License: MIT. See license file for more information but you can
7+
basically do whatever you want with this code.
8+
9+
This example shows how to obtain AssistNow Online (MGA) data from a PointPerfect Broker over WiFi
10+
and push it over I2C to a ZED-F9x.
11+
It's confusing, but the Arduino is acting as a 'client' to the PointPerfect service.
12+
13+
You will need to have a valid u-blox Thingstream account and have a PointPerfect Thing and payed plan.
14+
To sign up, go to: https://portal.thingstream.io/app/location-services/things
15+
16+
This is a proof of concept to show how to connect via MQTT to get AssistNow MGA data.
17+
18+
For more information about MQTT, SPARTN and PointPerfect Correction Services
19+
please see: https://www.u-blox.com/en/product/pointperfect
20+
21+
Feel like supporting open source hardware?
22+
Buy a board from SparkFun!
23+
SparkFun Thing Plus - ESP32 WROOM: https://www.sparkfun.com/products/15663
24+
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
25+
SparkFun GPS Breakout - ZOE-M8Q (Qwiic): https://www.sparkfun.com/products/15193
26+
27+
Hardware Connections:
28+
Plug a Qwiic cable into the GNSS and a ESP32 Thing Plus
29+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
30+
Open the serial monitor at 115200 baud to see the output
31+
*/
32+
#include <WiFi.h>
33+
#include <WiFiClientSecure.h>
34+
#include <ArduinoMqttClient.h> // Click here to get the library: http://librarymanager/All#ArduinoMqttClient
35+
#include "secrets.h"
36+
37+
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> // Click here to get the library: http://librarymanager/All#SparkFun_u-blox_GNSS
38+
SFE_UBLOX_GNSS myGNSS;
39+
40+
//Global variables
41+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
42+
long lastReceived_ms = 0; //5 RTCM messages take approximately ~300ms to arrive at 115200bps
43+
int maxTimeBeforeHangup_ms = 10000; //If we fail to get a complete RTCM frame after 10s, then disconnect from caster
44+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
45+
46+
void setup()
47+
{
48+
Serial.begin(115200);
49+
while (!Serial);
50+
Serial.println(F("PointPerfect AssistNow testing"));
51+
52+
Wire.begin(); //Start I2C
53+
54+
if (myGNSS.begin() == false) //Connect to the Ublox module using Wire port
55+
{
56+
Serial.println(F("u-blox GPS not detected at default I2C address. Please check wiring. Freezing."));
57+
while (1);
58+
}
59+
60+
Serial.println(F("u-blox module connected"));
61+
myGNSS.setI2COutput(COM_TYPE_UBX); //Turn off NMEA noise
62+
myGNSS.setPortInput(COM_PORT_I2C, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_SPARTN);
63+
64+
myGNSS.setNavigationFrequency(1); //Set output in Hz.
65+
66+
Serial.print(F("Connecting to local WiFi"));
67+
WiFi.begin(ssid, password);
68+
while (WiFi.status() != WL_CONNECTED) {
69+
delay(500);
70+
Serial.print(F("."));
71+
}
72+
Serial.println();
73+
74+
Serial.print(F("WiFi connected with IP: "));
75+
Serial.println(WiFi.localIP());
76+
77+
while (Serial.available()) Serial.read();
78+
}
79+
80+
void loop()
81+
{
82+
if (Serial.available())
83+
{
84+
beginClient();
85+
while (Serial.available()) Serial.read(); //Empty buffer of any newline chars
86+
}
87+
88+
Serial.println(F("Press any key to start MQTT Client."));
89+
90+
delay(1000);
91+
}
92+
93+
WiFiClientSecure wifiClient = WiFiClientSecure();
94+
MqttClient mqttClient(wifiClient);
95+
96+
void mqttMessageHandler(int messageSize) {
97+
uint8_t mgaData[512 * 4]; //Most incoming data is around 500 bytes but may be larger
98+
int mgaCount = 0;
99+
Serial.print(F("Pushed data from "));
100+
Serial.print(mqttClient.messageTopic());
101+
Serial.println(F(" topic to ZED"));
102+
while (mqttClient.available())
103+
{
104+
char ch = mqttClient.read();
105+
//Serial.write(ch); //Pipe to serial port is fine but beware, it's a lot of binary data
106+
mgaData[mgaCount++] = ch;
107+
if (mgaCount == sizeof(mgaData))
108+
break;
109+
}
110+
111+
if (mgaCount > 0)
112+
{
113+
//Push MGA data to GNSS module over I2C
114+
myGNSS.pushRawData(mgaData, mgaCount, false);
115+
lastReceived_ms = millis();
116+
}
117+
}
118+
119+
//Connect to MQTT broker, receive MGA, and push to ZED module over I2C
120+
void beginClient()
121+
{
122+
Serial.println(F("Subscribing to Broker. Press key to stop"));
123+
delay(10); //Wait for any serial to arrive
124+
while (Serial.available()) Serial.read(); //Flush
125+
126+
while (Serial.available() == 0)
127+
{
128+
//Connect if we are not already
129+
if (wifiClient.connected() == false)
130+
{
131+
// Connect to AWS IoT
132+
wifiClient.setCACert(AWS_CERT_CA);
133+
wifiClient.setCertificate(AWS_CERT_CRT);
134+
wifiClient.setPrivateKey(AWS_CERT_PRIVATE);
135+
mqttClient.setId(MQTT_CLIENT_ID);
136+
mqttClient.setKeepAliveInterval(60*1000);
137+
mqttClient.setConnectionTimeout( 5*1000);
138+
if (!mqttClient.connect(AWS_IOT_ENDPOINT, AWS_IOT_PORT)) {
139+
Serial.print(F("MQTT connection failed! Error code = "));
140+
Serial.println(mqttClient.connectError());
141+
return;
142+
} else {
143+
Serial.println(F("You're connected to the PointPerfect MQTT broker: "));
144+
Serial.println(AWS_IOT_ENDPOINT);
145+
// Subscribe to MQTT and register a callback
146+
Serial.println(F("Subscribe to Topics"));
147+
mqttClient.onMessage(mqttMessageHandler);
148+
mqttClient.subscribe(MQTT_TOPIC_ASSISTNOW);
149+
lastReceived_ms = millis();
150+
} //End attempt to connect
151+
} //End connected == false
152+
else {
153+
mqttClient.poll();
154+
}
155+
//Close socket if we don't have new data for 10s
156+
if (millis() - lastReceived_ms > maxTimeBeforeHangup_ms)
157+
{
158+
Serial.println(F("Timeout. Disconnecting..."));
159+
if (mqttClient.connected() == true)
160+
mqttClient.stop();
161+
return;
162+
}
163+
164+
delay(10);
165+
}
166+
167+
Serial.println(F("User pressed a key"));
168+
Serial.println(F("Disconnecting..."));
169+
wifiClient.stop();
170+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//Your WiFi credentials
2+
const char ssid[] = "<YOUR SSID>";
3+
const char password[] = "<YOUR PASSWORD>";
4+
5+
// Below infomation you can set after signing up with u-blox Thingstream portal
6+
// and after add a new New PointPerfect Thing
7+
// https://portal.thingstream.io/app/location-services/things
8+
// in the new PointPerfect Thing you go to the credentials page and copy past the values and certificate into this.
9+
10+
// <Your PointPerfect Thing> -> Credentials -> Hostname
11+
const char AWS_IOT_ENDPOINT[] = "pp.services.u-blox.com";
12+
const unsigned short AWS_IOT_PORT = 8883;
13+
// <Your PointPerfect Thing> -> Credentials -> AssistNow (MGA) topic
14+
const char MQTT_TOPIC_ASSISTNOW[] = "/pp/ubx/mga";
15+
16+
// <Your PointPerfect Thing> -> Credentials -> Client Id
17+
static const char MQTT_CLIENT_ID[] = "<ADD YOUR CLIENT ID HERE>";
18+
19+
// <Your PointPerfect Thing> -> Credentials -> Amazon Root Certificate
20+
static const char AWS_CERT_CA[] PROGMEM = R"EOF(
21+
-----BEGIN CERTIFICATE-----
22+
<ADD YOUR CERTICICATE HERE>
23+
-----END CERTIFICATE-----
24+
)EOF";
25+
26+
// <Your PointPerfect Thing> -> Credentials -> Client Certificate
27+
static const char AWS_CERT_CRT[] PROGMEM = R"KEY(
28+
-----BEGIN CERTIFICATE-----
29+
<ADD YOUR CERTICICATE HERE>
30+
-----END CERTIFICATE-----
31+
)KEY";
32+
33+
// Get this from Thingstream Portal
34+
// <Your PointPerfect Thing> -> Credentials -> Client Key
35+
static const char AWS_CERT_PRIVATE[] PROGMEM = R"KEY(
36+
-----BEGIN RSA PRIVATE KEY-----
37+
<ADD YOUR KEY HERE>
38+
-----END RSA PRIVATE KEY-----
39+
)KEY";

Diff for: examples/Example30_NEO-D9S/Example30_NEO-D9S.ino

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
NEO-D9S L-Band receiver example
3+
By: SparkFun Electronics / Paul Clark
4+
Date: March 7th, 2022
5+
License: MIT. See license file for more information but you can
6+
basically do whatever you want with this code.
7+
8+
This example shows how to display the NEO-D9S's received signal imbalance and magnitude, plus a summary of any received PMP data.
9+
10+
Feel like supporting open source hardware?
11+
Buy a board from SparkFun!
12+
ZED-F9P RTK2: https://www.sparkfun.com/products/16481
13+
NEO-D9S: Coming soon!
14+
15+
Hardware Connections:
16+
Use a Qwiic cable to connect the NEO-D9S L-Band corection data receiver to your board
17+
If you don't have a platform with a Qwiic connection use the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
18+
Open the serial monitor at 115200 baud to see the output
19+
*/
20+
21+
#include <SparkFun_u-blox_GNSS_Arduino_Library.h> //http://librarymanager/All#SparkFun_u-blox_GNSS
22+
SFE_UBLOX_GNSS myLBand; // NEO-D9S
23+
24+
const uint32_t myLBandFreq = 1556290000; // Uncomment this line to use the US SPARTN 1.8 service
25+
//const uint32_t myLBandFreq = 1545260000; // Uncomment this line to use the EU SPARTN 1.8 service
26+
27+
#define OK(ok) (ok ? F(" -> OK") : F(" -> ERROR!")) // Convert uint8_t into OK/ERROR
28+
29+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30+
31+
// Callback: printRXMPMP will be called when new PMP data arrives
32+
// See u-blox_structs.h for the full definition of UBX_RXM_PMP_data_t
33+
// _____ You can use any name you like for the callback. Use the same name when you call setRXMPMPcallbackPtr
34+
// / _____ This _must_ be UBX_RXM_PMP_data_t
35+
// | / _____ You can use any name you like for the struct
36+
// | | /
37+
// | | |
38+
void printRXMPMP(UBX_RXM_PMP_data_t *pmpData)
39+
{
40+
Serial.println(F("New PMP data received:"));
41+
42+
Serial.print(F("PMP message version: "));
43+
Serial.println(pmpData->version);
44+
45+
Serial.print(F("numBytesUserData : "));
46+
Serial.println(pmpData->numBytesUserData);
47+
48+
Serial.print(F("serviceIdentifier: "));
49+
Serial.println(pmpData->serviceIdentifier);
50+
51+
Serial.print(F("uniqueWordBitErrors: "));
52+
Serial.println(pmpData->uniqueWordBitErrors);
53+
54+
Serial.print(F("fecBits: "));
55+
Serial.println(pmpData->fecBits);
56+
57+
Serial.print(F("ebno: "));
58+
Serial.println(pmpData->ebno);
59+
60+
Serial.println();
61+
}
62+
63+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
64+
65+
void setup()
66+
{
67+
Serial.begin(115200);
68+
Serial.println(F("NEO-D9S Example"));
69+
70+
Wire.begin(); //Start I2C
71+
72+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
73+
// Begin and configure the NEO-D9S L-Band receiver
74+
75+
//myLBand.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
76+
77+
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)
78+
{
79+
Serial.println(F("u-blox NEO-D9S not detected at default I2C address. Please check wiring."));
80+
delay(2000);
81+
}
82+
Serial.println(F("u-blox NEO-D9S connected"));
83+
84+
uint8_t ok = myLBand.setVal32(UBLOX_CFG_PMP_CENTER_FREQUENCY, myLBandFreq); // Default 1539812500 Hz
85+
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz
86+
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1
87+
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821
88+
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps
89+
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1
90+
if (ok) ok = myLBand.setVal16(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560
91+
if (ok) ok = myLBand.setVal8(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0
92+
if (ok) ok = myLBand.setVal64(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull);
93+
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port
94+
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1
95+
if (ok) ok = myLBand.setVal(UBLOX_CFG_UART2OUTPROT_UBX, 1); // Enable UBX output on UART2
96+
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2
97+
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default
98+
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default
99+
100+
Serial.print(F("L-Band: configuration "));
101+
Serial.println(OK(ok));
102+
103+
myLBand.softwareResetGNSSOnly(); // Do a restart
104+
105+
myLBand.setRXMPMPcallbackPtr(&printRXMPMP); // Call printRXMPMP when new PMP data arrives
106+
}
107+
108+
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
109+
110+
void loop()
111+
{
112+
myLBand.checkUblox(); // Check for the arrival of new PMP data and process it.
113+
myLBand.checkCallbacks(); // Check if any LBand callbacks are waiting to be processed.
114+
115+
UBX_MON_HW2_data_t hwStatus; // Create storage for the HW2 extended hardware status
116+
if (myLBand.getHW2status(&hwStatus)) // Request the extended hardware status
117+
{
118+
// Print the signal imbalance and magnitude
119+
Serial.print(F("Signal imbalance and magnitude: ofsI: "));
120+
Serial.print(hwStatus.ofsI);
121+
Serial.print(F(" magI: "));
122+
Serial.print(hwStatus.magI);
123+
Serial.print(F(" ofsQ: "));
124+
Serial.print(hwStatus.ofsQ);
125+
Serial.print(F(" magQ: "));
126+
Serial.println(hwStatus.magQ);
127+
}
128+
}

Diff for: examples/ZED-F9P/Example18_PointPerfectClient/Example18_PointPerfectClient.ino

+3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ void beginClient()
138138
wifiClient.setCACert(AWS_CERT_CA);
139139
wifiClient.setCertificate(AWS_CERT_CRT);
140140
wifiClient.setPrivateKey(AWS_CERT_PRIVATE);
141+
mqttClient.setId(MQTT_CLIENT_ID);
142+
mqttClient.setKeepAliveInterval(60*1000);
143+
mqttClient.setConnectionTimeout( 5*1000);
141144
if (!mqttClient.connect(AWS_IOT_ENDPOINT, AWS_IOT_PORT)) {
142145
Serial.print(F("MQTT connection failed! Error code = "));
143146
Serial.println(mqttClient.connectError());

Diff for: examples/ZED-F9P/Example18_PointPerfectClient/secrets.h

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ const char MQTT_TOPIC_KEY[] = "/pp/key/ip";
1515
// <Your PointPerfect Thing> -> Credentials -> IP correction topic for EU/US region
1616
const char MQTT_TOPIC_SPARTN[] = "/pp/ip/us"; // choice of {eu, us}
1717

18+
// <Your PointPerfect Thing> -> Credentials -> Client Id
19+
static const char MQTT_CLIENT_ID[] = "<ADD YOUR CLIENT ID HERE>";
20+
1821
// <Your PointPerfect Thing> -> Credentials -> Amazon Root Certificate
1922
static const char AWS_CERT_CA[] PROGMEM = R"EOF(
2023
-----BEGIN CERTIFICATE-----

Diff for: examples/ZED-F9P/Example19_LBand_Corrections_with_NEO-D9S/Example19_LBand_Corrections_with_NEO-D9S.ino

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ void setup()
187187
if (ok) ok = myLBand.setVal64(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull);
188188
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_I2C, 1); // Ensure UBX-RXM-PMP is enabled on the I2C port
189189
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 1); // Output UBX-RXM-PMP on UART1
190+
if (ok) ok = myLBand.setVal(UBLOX_CFG_UART2OUTPROT_UBX, 1); // Enable UBX output on UART2
190191
if (ok) ok = myLBand.setVal(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART2, 1); // Output UBX-RXM-PMP on UART2
191192
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART1_BAUDRATE, 38400); // match baudrate with ZED default
192193
if (ok) ok = myLBand.setVal32(UBLOX_CFG_UART2_BAUDRATE, 38400); // match baudrate with ZED default

Diff for: keywords.txt

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ UBX_ESF_STATUS_sensorStatus_t KEYWORD1
1919
UBX_CFG_ITFM_data_t KEYWORD1
2020
UBX_MON_RF_data_t KEYWORD1
2121
UBX_MON_HW_data_t KEYWORD1
22+
UBX_MON_HW2_data_t KEYWORD1
2223

2324
UBX_NAV_POSECEF_data_t KEYWORD1
2425
UBX_NAV_STATUS_data_t KEYWORD1
@@ -195,6 +196,7 @@ setJammingConfiguration KEYWORD2
195196
getRFinformation KEYWORD2
196197

197198
getHWstatus KEYWORD2
199+
getHW2status KEYWORD2
198200

199201
getAckAiding KEYWORD2
200202
setAckAiding KEYWORD2

Diff for: library.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=SparkFun u-blox GNSS Arduino Library
2-
version=2.2.5
2+
version=2.2.6
33
author=SparkFun Electronics <[email protected]>
44
maintainer=SparkFun Electronics <sparkfun.com>
55
sentence=Library for I2C, Serial and SPI Communication with u-blox GNSS modules<br/><br/>

0 commit comments

Comments
 (0)