Skip to content

Commit 232dc1a

Browse files
committed
GPS - Begin UBX implementation
1 parent e115785 commit 232dc1a

File tree

6 files changed

+101
-43
lines changed

6 files changed

+101
-43
lines changed

platformio.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ lib_deps =
9292
https://github.com/adafruit/RTClib.git
9393
https://github.com/bblanchon/ArduinoStreamUtils.git
9494
https://github.com/Sensirion/arduino-i2c-scd4x.git
95+
https://github.com/sparkfun/SparkFun_u-blox_GNSS_v3.git
96+
https://github.com/stevemarple/MicroNMEA.git
9597
adafruit/Adafruit GPS Library
9698

9799
; Common build environment for ESP32 platform

src/components/gps/hardware.cpp

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,20 @@ GPSHardware::GPSHardware() {
2828
* @brief Destructor
2929
*/
3030
GPSHardware::~GPSHardware() {
31-
// Clean up GPS instance
31+
_iface_type = GPS_IFACE_NONE;
32+
_driver_type = GPS_DRV_NONE;
3233
if (_ada_gps) {
3334
delete _ada_gps;
3435
_ada_gps = nullptr;
3536
}
37+
if (_sfe_gps) {
38+
delete _sfe_gps;
39+
_sfe_gps = nullptr;
40+
}
3641
}
3742

3843
/*!
39-
* @brief Reads and discards data requested by the I2C bus.
44+
* @brief Helper function that reads and discards data requested by the I2C bus.
4045
*/
4146
void GPSHardware::I2cReadDiscard() {
4247
_wire->flush();
@@ -57,20 +62,13 @@ bool GPSHardware::Handle_GPSConfig(wippersnapper_gps_GPSConfig *gps_config) {
5762
WS_DEBUG_PRINTLN("[gps] Handling GPSConfig message...");
5863
if (gps_config == nullptr)
5964
return false;
60-
// Set the polling period for GPS data
65+
// Set the module's polling period for GPS data
6166
SetPollPeriod(gps_config->period);
6267

6368
// Attempt to decode the GPSConfig message
6469
if (_driver_type == GPS_DRV_MTK) {
6570
WS_DEBUG_PRINTLN("[gps] Handling GPSConfig for MediaTek driver...");
66-
if (gps_config == nullptr) {
67-
WS_DEBUG_PRINTLN("[gps] ERROR: No GPSConfig message found!");
68-
return false;
69-
}
70-
7171
// Iterate through the command sentences and send them to the GPS module
72-
// TODO: We may want to break this out into a generic function that supports
73-
// MTK, Ublox, etc...
7472
for (size_t i = 0; i < gps_config->commands_count; i++) {
7573
// Build the PMTK ACK response for the command
7674
char msg_resp[MAX_NEMA_SENTENCE_LEN];
@@ -103,11 +101,16 @@ bool GPSHardware::Handle_GPSConfig(wippersnapper_gps_GPSConfig *gps_config) {
103101
return false;
104102
}
105103
}
104+
} else if (_driver_type == GPS_DRV_UBLOX) {
105+
WS_DEBUG_PRINTLN("[gps] Handling GPSConfig for MediaTek driver...");
106+
// Iterate through the command sentences and send them to the GPS module
107+
for (size_t i = 0; i < gps_config->commands_count; i++) {
108+
// TODO
109+
}
106110
} else {
107111
WS_DEBUG_PRINTLN("[gps] ERROR: Unsupported GPS driver type!");
108112
return false;
109113
}
110-
111114
return true;
112115
}
113116

@@ -159,7 +162,43 @@ bool GPSHardware::begin() {
159162
return false;
160163
}
161164
WS_DEBUG_PRINTLN("[gps] Module detected, ready for commands!");
165+
return true;
166+
}
162167

168+
/*!
169+
* @brief Attempts to detect and initialize a MediaTek GPS module over I2C
170+
* @returns True if a MediaTek GPS module was detected and initialized, False
171+
* otherwise.
172+
*/
173+
bool GPSHardware::DetectMtkI2C(uint32_t addr) {
174+
if (_addr != PA1010D_I2C_ADDRESS) {
175+
WS_DEBUG_PRINTLN(
176+
"[gps] ERROR: Only PA1010D i2c module is supported at this time!");
177+
return false;
178+
}
179+
_ada_gps = new Adafruit_GPS(_wire);
180+
if (!_ada_gps->begin(_addr))
181+
return false;
182+
_driver_type = GPS_DRV_MTK;
183+
return true;
184+
}
185+
186+
/*!
187+
* @brief Attempts to detect and initialize a U-Blox GPS module over I2C
188+
* @param addr
189+
* The I2C address of the GPS module.
190+
* @returns True if a u-blox GPS module was detected and initialized, False
191+
* otherwise.
192+
*/
193+
bool GPSHardware::DetectUbxI2C(uint32_t addr) {
194+
if (addr != UBX_I2C_ADDRESS) {
195+
WS_DEBUG_PRINTLN("[gps] ERROR: Invalid U-Blox I2C address!");
196+
return false;
197+
}
198+
_sfe_gps = new SFE_UBLOX_GNSS();
199+
if (!_sfe_gps->begin(*_wire, _addr))
200+
return false;
201+
_driver_type = GPS_DRV_UBLOX;
163202
return true;
164203
}
165204

@@ -170,10 +209,9 @@ bool GPSHardware::begin() {
170209
*/
171210
bool GPSHardware::QueryModuleType() {
172211
WS_DEBUG_PRINTLN("[gps] Attempting to detect GPS module type...");
173-
174212
if (_iface_type == GPS_IFACE_UART_HW) {
175213
// Try to detect MediaTek GPS module
176-
if (DetectMediatek()) {
214+
if (DetectMtkUart()) {
177215
WS_DEBUG_PRINTLN("[gps] Using MediaTek GPS driver!");
178216
return true;
179217
}
@@ -195,18 +233,22 @@ bool GPSHardware::QueryModuleType() {
195233
} else if (_iface_type == GPS_IFACE_I2C) {
196234
if (_addr == PA1010D_I2C_ADDRESS) {
197235
WS_DEBUG_PRINT("[gps] Attempting to use PA1010D driver...");
198-
// Attempt to use Adafruit_GPS I2c interface
199-
_ada_gps = new Adafruit_GPS(_wire);
200-
if (!_ada_gps->begin(_addr)) {
201-
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to initialize Mediatek!");
236+
if (!DetectMtkI2C(_addr)) {
237+
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to init PA1010D module!");
238+
return false;
239+
}
240+
WS_DEBUG_PRINTLN("ok!");
241+
return true;
242+
} else if (_addr == UBX_I2C_ADDRESS) {
243+
WS_DEBUG_PRINT("[gps] Attempting to use u-blox driver...");
244+
if (!DetectUbxI2C(_addr)) {
245+
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to init u-blox module!");
202246
return false;
203247
}
204248
WS_DEBUG_PRINTLN("ok!");
205-
_driver_type = GPS_DRV_MTK;
206249
return true;
207250
} else {
208-
WS_DEBUG_PRINTLN(
209-
"[gps] ERROR: Only PA1010D i2c module is supported at this time!");
251+
WS_DEBUG_PRINTLN("[gps] ERROR: Uknown I2C address provided!");
210252
return false;
211253
}
212254
}
@@ -219,7 +261,7 @@ bool GPSHardware::QueryModuleType() {
219261
* firmware version.
220262
* @returns True if a MediaTek GPS module was detected, False otherwise.
221263
*/
222-
bool GPSHardware::DetectMediatek() {
264+
bool GPSHardware::DetectMtkUart() {
223265
if (_iface_type != GPS_IFACE_UART_HW) {
224266
WS_DEBUG_PRINTLN("[gps] ERROR: MediaTek GPS module only supports Hardware "
225267
"Serial interface!");

src/components/gps/hardware.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#define WS_GPS_HARDWARE_H
1717
#include "Wippersnapper_V2.h"
1818
#include <Adafruit_GPS.h>
19+
#include <MicroNMEA.h>
20+
#include <SparkFun_u-blox_GNSS_v3.h>
1921

2022
#define CMD_MTK_QUERY_FW \
2123
"$PMTK605*31" ///< Request to query MediaTek firmware version
@@ -27,6 +29,7 @@
2729
#define DEFAULT_MTK_NMEA_BAUD_RATE 9600 ///< Default NMEA baud rate in bits per
2830
#define MAX_NEMA_SENTENCE_LEN 82 ///< Maximum length of a NMEA sentence
2931
#define PA1010D_I2C_ADDRESS 0x10 ///< I2C address for PA1010D GPS module
32+
#define UBX_I2C_ADDRESS 0x42 ///< I2C address for all u-Blox GPS products
3033

3134
class Wippersnapper_V2; ///< Forward declaration
3235
class UARTHardware; ///< Forward declaration
@@ -77,19 +80,25 @@ class GPSHardware {
7780

7881
private:
7982
bool QueryModuleType();
80-
bool DetectMediatek();
83+
bool DetectMtkUart();
84+
bool DetectMtkI2C(uint32_t addr);
85+
bool DetectUbxI2C(uint32_t addr);
8186
bool BuildPmtkAck(char *msg_cmd, char *msg_resp);
8287
GpsInterfaceType _iface_type; ///< Type of interface used by GPS
83-
GpsDriverType _driver_type; ///< Type of GPS driver used
84-
HardwareSerial *_hw_serial = nullptr; ///< HardwareSerial instance for GPS;
85-
TwoWire *_wire = nullptr; ///< TwoWire instance for I2C GPS
86-
Adafruit_GPS *_ada_gps = nullptr; ///< Adafruit GPS instance
87-
uint32_t _addr; ///< I2C address for GPS device
88+
GpsDriverType _driver_type; ///< Type of GPS driver used by GPS
89+
HardwareSerial *_hw_serial = nullptr; ///< Optional HardwareSerial instance
90+
TwoWire *_wire = nullptr; ///< Optional TwoWire instance
91+
Adafruit_GPS *_ada_gps = nullptr; ///< Optional Adafruit GPS instance
92+
SFE_UBLOX_GNSS *_sfe_gps; ///< Optional Sparkfun u-blox GPS instance
93+
uint32_t _addr; ///< Optional i2c address
8894
ulong _period; ///< Polling period for GPS data (Specified by IO), in ms
8995
ulong _period_prv; ///< Previous period for GPS data (Specified by IO), in ms
9096
ulong _kat_prv; ///< Last time the GPS hardware was polled, in ms
9197
int _nmea_update_rate; ///< NMEA update rate for GPS data, in Hz
9298
int _nmea_baud_rate; ///< NMEA baud rate for GPS data, in bits per second
99+
MicroNMEA
100+
*_micro_nmea; ///< Optional MicroNMEA instance for parsing NMEA sentences
101+
char _micro_nmea_buf[100]; ///< Optional Buffer for MicroNMEA parsing
93102
};
94103
extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance
95104
#endif // WS_GPS_HARDWARE_H

src/protos/gps.pb.h

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515
Since GPS devices can output lots of data, this message allows users to select which data they want to receive
1616
and a resulting command string to initialize the GPS device with the selected options will be generated. */
1717
typedef struct _wippersnapper_gps_GPSConfig {
18-
/* Baud rate is not included here as it is included in the UartAdd->UartSerialConfig message. */
19-
pb_size_t commands_count;
20-
char commands[16][90]; /* * List of commands to configure the GPS * */
21-
int32_t period; /* * The period to poll the GPS module, in milliseconds */
18+
/* NOTE: Baud rate is not included here as it is included in the UartAdd->UartSerialConfig message. */
19+
pb_size_t commands_pmtks_count;
20+
char commands_pmtks[16][90]; /* * List of PMTK commands in string format. * */
21+
pb_callback_t commands_ubxes; /* * List of UBX commands in bytes format. * */
22+
int32_t period; /* * Desired period to poll the GPS module, in milliseconds */
2223
} wippersnapper_gps_GPSConfig;
2324

2425
/* * GPSDateTime represents the date and time information from a GPRMC/GPGGA string * */
@@ -74,20 +75,21 @@ extern "C" {
7475
#endif
7576

7677
/* Initializer values for message structs */
77-
#define wippersnapper_gps_GPSConfig_init_default {0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, 0}
78+
#define wippersnapper_gps_GPSConfig_init_default {0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {{NULL}, NULL}, 0}
7879
#define wippersnapper_gps_GPSDateTime_init_default {0, 0, 0, 0, 0, 0, 0}
7980
#define wippersnapper_gps_GPSRMCResponse_init_default {false, wippersnapper_gps_GPSDateTime_init_default, "", "", "", "", "", "", ""}
8081
#define wippersnapper_gps_GPGGAResponse_init_default {false, wippersnapper_gps_GPSDateTime_init_default, "", "", "", "", 0, 0, "", "", ""}
8182
#define wippersnapper_gps_GPSEvent_init_default {0, {wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default, wippersnapper_gps_GPSRMCResponse_init_default}, 0, {wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default, wippersnapper_gps_GPGGAResponse_init_default}}
82-
#define wippersnapper_gps_GPSConfig_init_zero {0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, 0}
83+
#define wippersnapper_gps_GPSConfig_init_zero {0, {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}, {{NULL}, NULL}, 0}
8384
#define wippersnapper_gps_GPSDateTime_init_zero {0, 0, 0, 0, 0, 0, 0}
8485
#define wippersnapper_gps_GPSRMCResponse_init_zero {false, wippersnapper_gps_GPSDateTime_init_zero, "", "", "", "", "", "", ""}
8586
#define wippersnapper_gps_GPGGAResponse_init_zero {false, wippersnapper_gps_GPSDateTime_init_zero, "", "", "", "", 0, 0, "", "", ""}
8687
#define wippersnapper_gps_GPSEvent_init_zero {0, {wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero, wippersnapper_gps_GPSRMCResponse_init_zero}, 0, {wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero, wippersnapper_gps_GPGGAResponse_init_zero}}
8788

8889
/* Field tags (for use in manual encoding/decoding) */
89-
#define wippersnapper_gps_GPSConfig_commands_tag 1
90-
#define wippersnapper_gps_GPSConfig_period_tag 2
90+
#define wippersnapper_gps_GPSConfig_commands_pmtks_tag 1
91+
#define wippersnapper_gps_GPSConfig_commands_ubxes_tag 2
92+
#define wippersnapper_gps_GPSConfig_period_tag 3
9193
#define wippersnapper_gps_GPSDateTime_hour_tag 1
9294
#define wippersnapper_gps_GPSDateTime_minute_tag 2
9395
#define wippersnapper_gps_GPSDateTime_seconds_tag 3
@@ -118,9 +120,10 @@ extern "C" {
118120

119121
/* Struct field encoding specification for nanopb */
120122
#define wippersnapper_gps_GPSConfig_FIELDLIST(X, a) \
121-
X(a, STATIC, REPEATED, STRING, commands, 1) \
122-
X(a, STATIC, SINGULAR, INT32, period, 2)
123-
#define wippersnapper_gps_GPSConfig_CALLBACK NULL
123+
X(a, STATIC, REPEATED, STRING, commands_pmtks, 1) \
124+
X(a, CALLBACK, REPEATED, BYTES, commands_ubxes, 2) \
125+
X(a, STATIC, SINGULAR, INT32, period, 3)
126+
#define wippersnapper_gps_GPSConfig_CALLBACK pb_default_field_callback
124127
#define wippersnapper_gps_GPSConfig_DEFAULT NULL
125128

126129
#define wippersnapper_gps_GPSDateTime_FIELDLIST(X, a) \
@@ -184,9 +187,9 @@ extern const pb_msgdesc_t wippersnapper_gps_GPSEvent_msg;
184187
#define wippersnapper_gps_GPSEvent_fields &wippersnapper_gps_GPSEvent_msg
185188

186189
/* Maximum encoded size of messages (where known) */
190+
/* wippersnapper_gps_GPSConfig_size depends on runtime parameters */
187191
#define WIPPERSNAPPER_GPS_GPS_PB_H_MAX_SIZE wippersnapper_gps_GPSEvent_size
188192
#define wippersnapper_gps_GPGGAResponse_size 168
189-
#define wippersnapper_gps_GPSConfig_size 1467
190193
#define wippersnapper_gps_GPSDateTime_size 77
191194
#define wippersnapper_gps_GPSEvent_size 3130
192195
#define wippersnapper_gps_GPSRMCResponse_size 139

src/protos/i2c.pb.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,14 @@ extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceOutputWrite_msg;
349349
#define wippersnapper_i2c_I2cBusDescriptor_size 32
350350
#define wippersnapper_i2c_I2cBusScan_size 42
351351
#define wippersnapper_i2c_I2cBusScanned_size 6242
352-
#define wippersnapper_i2c_I2cDeviceAddOrReplace_size 1597
353352
#define wippersnapper_i2c_I2cDeviceAddedOrReplaced_size 56
354353
#define wippersnapper_i2c_I2cDeviceDescriptor_size 50
355354
#define wippersnapper_i2c_I2cDeviceOutputWrite_size 569
356355
#define wippersnapper_i2c_I2cDeviceRemove_size 54
357356
#define wippersnapper_i2c_I2cDeviceRemoved_size 54
357+
#if defined(wippersnapper_gps_GPSConfig_size)
358+
#define wippersnapper_i2c_I2cDeviceAddOrReplace_size (133 + wippersnapper_gps_GPSConfig_size)
359+
#endif
358360
#if defined(wippersnapper_sensor_SensorEvent_size)
359361
#define wippersnapper_i2c_I2cDeviceEvent_size (142 + 15*wippersnapper_sensor_SensorEvent_size)
360362
#endif

src/protos/signal.pb.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,13 +270,13 @@ extern const pb_msgdesc_t wippersnapper_signal_DeviceToBroker_msg;
270270
#define wippersnapper_signal_DeviceToBroker_fields &wippersnapper_signal_DeviceToBroker_msg
271271

272272
/* Maximum encoded size of messages (where known) */
273-
#if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UartAdd_size) && defined(wippersnapper_uart_UartWrite_size)
274-
union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UartAdd_size)]; char f82[(7 + wippersnapper_uart_UartWrite_size)]; char f0[1601];};
273+
#if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UartAdd_size) && defined(wippersnapper_uart_UartWrite_size) && defined(wippersnapper_i2c_I2cDeviceAddOrReplace_size)
274+
union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UartAdd_size)]; char f82[(7 + wippersnapper_uart_UartWrite_size)]; char f91[(7 + wippersnapper_i2c_I2cDeviceAddOrReplace_size)]; char f0[573];};
275275
#endif
276276
#if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_analogio_AnalogIOEvent_size) && defined(wippersnapper_ds18x20_Ds18x20Event_size) && defined(wippersnapper_uart_UartInputEvent_size) && defined(wippersnapper_i2c_I2cDeviceEvent_size)
277277
union wippersnapper_signal_DeviceToBroker_payload_size_union {char f10[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f20[(7 + wippersnapper_analogio_AnalogIOEvent_size)]; char f80[(7 + wippersnapper_ds18x20_Ds18x20Event_size)]; char f92[(7 + wippersnapper_uart_UartInputEvent_size)]; char f113[(7 + wippersnapper_i2c_I2cDeviceEvent_size)]; char f0[6246];};
278278
#endif
279-
#if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UartAdd_size) && defined(wippersnapper_uart_UartWrite_size)
279+
#if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UartAdd_size) && defined(wippersnapper_uart_UartWrite_size) && defined(wippersnapper_i2c_I2cDeviceAddOrReplace_size)
280280
#define WIPPERSNAPPER_SIGNAL_SIGNAL_PB_H_MAX_SIZE wippersnapper_signal_BrokerToDevice_size
281281
#define wippersnapper_signal_BrokerToDevice_size (0 + sizeof(union wippersnapper_signal_BrokerToDevice_payload_size_union))
282282
#endif

0 commit comments

Comments
 (0)