Skip to content

Commit 7eecfd1

Browse files
committed
Filling out GPS request polling and adding GPS request example.
1 parent debbfe3 commit 7eecfd1

File tree

4 files changed

+184
-10
lines changed

4 files changed

+184
-10
lines changed

examples/04_GPS_Interface/04_GPS_Interface.ino

Whitespace-only changes.
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
Use the GPS Request feature to request GPS data and receive it in a callback
3+
By: Jim Lindblom
4+
SparkFun Electronics
5+
Date: November 1, 2018
6+
License: This code is public domain but you buy me a beer if you use this
7+
and we meet someday (Beerware license).
8+
Feel like supporting our work? Buy a board from SparkFun!
9+
https://www.sparkfun.com/products/14997
10+
11+
This example demonstrates how to use the gpsRequest feature
12+
13+
Before beginning, you should have your shield connected to a supported u-blox
14+
GPS module via the I2C (DDC) port.
15+
Supported GPS modules include:
16+
https://www.sparkfun.com/products/15005
17+
18+
Once programmed, open the serial monitor, set the baud rate to 9600,
19+
and hit enter to watch GPS data begin to stream by.
20+
21+
Hardware Connections:
22+
Attach the SparkFun LTE Cat M1/NB-IoT Shield to your Arduino
23+
Power the shield with your Arduino -- ensure the PWR_SEL switch is in
24+
the "ARDUINO" position.
25+
*/
26+
27+
//Click here to get the library: http://librarymanager/All#SparkFun_LTE_Shield_Arduino_Library
28+
#include <SparkFun_LTE_Shield_Arduino_Library.h>
29+
30+
// Create a SoftwareSerial object to pass to the LTE_Shield library
31+
SoftwareSerial lteSerial(8, 9);
32+
// Create a LTE_Shield object to use throughout the sketch
33+
LTE_Shield lte;
34+
35+
boolean requestingGPS = false;
36+
unsigned long lastRequest = 0;
37+
#define MIN_REQUEST_INTERVAL 60000 // How often we'll get GPS in loop (in ms)
38+
39+
#define GPS_REQUEST_TIMEOUT 30 // Time to turn on GPS module and get a fix (in s)
40+
#define GPS_REQUEST_ACCURACY 1 // Desired accuracy from GPS module (in meters)
41+
42+
void processGpsRead(ClockData clck, PositionData gps,
43+
SpeedData spd, unsigned long uncertainty) {
44+
45+
Serial.println();
46+
Serial.println();
47+
Serial.println(F("GPS Data Received"));
48+
Serial.println(F("================="));
49+
Serial.println("Date: " + String(clck.date.month) + "/" +
50+
String(clck.date.day) + "/" + String(clck.date.year));
51+
Serial.println("Time: " + String(clck.time.hour) + ":" +
52+
String(clck.time.minute) + ":" + String(clck.time.second) + "." + String(clck.time.ms));
53+
Serial.println("Lat/Lon: " + String(gps.lat, 7) + "/" + String(gps.lon, 7));
54+
Serial.println("Alt: " + String(gps.alt));
55+
Serial.println("Uncertainty: " + String(uncertainty));
56+
Serial.println("Speed: " + String(spd.speed) + " @ " + String(spd.tack));
57+
Serial.println();
58+
59+
requestingGPS = false;
60+
}
61+
62+
void setup() {
63+
Serial.begin(9600);
64+
65+
// Wait for user to press key in terminal to begin
66+
Serial.println("Press any key to begin GPS'ing");
67+
while (!Serial.available()) ;
68+
while (Serial.available()) Serial.read();
69+
70+
// Initialize the LTE Shield
71+
if ( lte.begin(lteSerial, 9600) ) {
72+
Serial.println(F("LTE Shield connected!"));
73+
}
74+
// Set a callback to return GPS data once requested
75+
lte.setGpsReadCallback(&processGpsRead);
76+
}
77+
78+
void loop() {
79+
// Poll as often as possible
80+
lte.poll();
81+
82+
if (!requestingGPS) {
83+
if ((lastRequest == 0) || (lastRequest + MIN_REQUEST_INTERVAL < millis())) {
84+
Serial.println(F("Requesting GPS data...this can take up to 10 seconds"));
85+
if (lte.gpsRequest(GPS_REQUEST_TIMEOUT, GPS_REQUEST_ACCURACY) == LTE_SHIELD_SUCCESS) {
86+
Serial.println(F("GPS data requested."));
87+
Serial.println("Wait up to " + String(GPS_REQUEST_TIMEOUT) + " seconds");
88+
requestingGPS = true;
89+
lastRequest = millis();
90+
} else {
91+
Serial.println(F("Error requesting GPS"));
92+
}
93+
}
94+
} else {
95+
// Print a '.' every ~1 second if requesting GPS data
96+
// (Hopefully this doesn't mess with poll too much)
97+
if ((millis() % 1000) == 0) {
98+
Serial.print('.');
99+
delay(1);
100+
}
101+
}
102+
103+
104+
}

src/SparkFun_LTE_Shield_Arduino_Library.cpp

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ boolean LTE_Shield::poll(void)
147147

148148
if (hwAvailable())
149149
{
150-
while (c != '\n') ///(avail < hwAvailable())
150+
while (c != '\n')
151151
{
152152
if (hwAvailable())
153153
{
@@ -197,16 +197,39 @@ boolean LTE_Shield::poll(void)
197197
}
198198
}
199199
{
200+
ClockData clck;
201+
PositionData gps;
202+
SpeedData spd;
203+
unsigned long uncertainty;
204+
int scanNum;
205+
unsigned int latH, lonH, altU, speedU, tackU;
206+
char latL[10], lonL[10];
207+
200208
if (strstr(lteShieldRXBuffer, "+UULOC"))
201209
{
202210
// Found a Location string!
203-
Serial.println("Found location string!");
204-
Serial.println(lteShieldRXBuffer);
211+
scanNum = sscanf(lteShieldRXBuffer,
212+
"+UULOC: %hhu/%hhu/%u,%hhu:%hhu:%hhu.%u,%u.%[^,],%u.%[^,],%u,%lu,%u,%u,*%s",
213+
&clck.date.day, &clck.date.month, &clck.date.year,
214+
&clck.time.hour, &clck.time.minute, &clck.time.second, &clck.time.ms,
215+
&latH, latL, &lonH, lonL, &altU, &uncertainty,
216+
&speedU, &tackU);
217+
if (scanNum < 13) return false; // Break out if we didn't find enough
218+
219+
gps.lat = (float) latH + ((float)atol(latL) / pow(10, strlen(latL)));
220+
gps.lon = (float) lonH + ((float)atol(lonL) / pow(10, strlen(lonL)));
221+
gps.alt = (float) altU;
222+
if (scanNum == 15) // If detailed response, get speed data
223+
{
224+
spd.speed = (float) speedU;
225+
spd.tack = (float) tackU;
226+
}
227+
228+
if (_gpsRequestCallback != NULL)
229+
{
230+
_gpsRequestCallback(clck, gps, spd, uncertainty);
231+
}
205232
}
206-
// Look for +UULOC
207-
// Either: +UULOC: DD/MM/YYYY,HH:MM:SS.sss,lat.lat,lon.lon,alt,uncertainty,
208-
// speed,direction,vertical_acc,sv_used,antenna_status,jamming_status
209-
// Or: DD/MM/YYYY,HH:MM:SS.sss,lat.lat,lon.lon,alt,uncertainty
210233
}
211234

212235
if ( (handled == false) && (strlen(lteShieldRXBuffer) > 2) )
@@ -231,6 +254,12 @@ void LTE_Shield::setSocketCloseCallback(void (*socketCloseCallback)(int))
231254
_socketCloseCallback = socketCloseCallback;
232255
}
233256

257+
void LTE_Shield::setGpsReadCallback(void (*gpsRequestCallback)(ClockData time,
258+
PositionData gps, SpeedData spd, unsigned long uncertainty))
259+
{
260+
_gpsRequestCallback = gpsRequestCallback;
261+
}
262+
234263
size_t LTE_Shield::write(uint8_t c)
235264
{
236265
if (_hardSerial != NULL)
@@ -864,6 +893,36 @@ IPAddress LTE_Shield::lastRemoteIP(void)
864893
return _lastRemoteIP;
865894
}
866895

896+
boolean LTE_Shield::gpsOn(void)
897+
{
898+
LTE_Shield_error_t err;
899+
char * command;
900+
char * response;
901+
boolean on = false;
902+
903+
command = lte_calloc_char(strlen(LTE_SHIELD_GPS_POWER) + 2);
904+
if (command == NULL) return LTE_SHIELD_ERROR_OUT_OF_MEMORY;
905+
sprintf(command, "%s?", LTE_SHIELD_GPS_POWER);
906+
907+
response = lte_calloc_char(24);
908+
if (response == NULL) return LTE_SHIELD_ERROR_OUT_OF_MEMORY;
909+
910+
err = sendCommandWithResponse(command, LTE_SHIELD_RESPONSE_OK, response,
911+
LTE_SHIELD_STANDARD_RESPONSE_TIMEOUT);
912+
913+
if (err == LTE_SHIELD_ERROR_SUCCESS)
914+
{
915+
// Example response: "+UGPS: 0" for off "+UGPS: 1,0,1" for on
916+
// May be too lazy/simple, but just search for a '1'
917+
if (strchr(response, '1') != NULL) on = true;
918+
}
919+
920+
free(command);
921+
free(response);
922+
923+
return on;
924+
}
925+
867926
LTE_Shield_error_t LTE_Shield::gpsPower(boolean enable, gnss_system_t gnss_sys)
868927
{
869928
LTE_Shield_error_t err;
@@ -953,6 +1012,12 @@ LTE_Shield_error_t LTE_Shield::gpsRequest(unsigned int timeout, unsigned int acc
9531012
LTE_Shield_error_t err;
9541013
char * command;
9551014

1015+
// This function will only work if the GPS module is initially turned off.
1016+
if (gpsOn())
1017+
{
1018+
gpsPower(false);
1019+
}
1020+
9561021
if (timeout > 999) timeout = 999;
9571022
if (accuracy > 999999) accuracy = 999999;
9581023

src/SparkFun_LTE_Shield_Arduino_Library.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,14 @@ typedef enum {
9393
struct DateData {
9494
uint8_t day;
9595
uint8_t month;
96-
uint8_t year;
96+
unsigned int year;
9797
};
9898

9999
struct TimeData {
100100
uint8_t hour;
101101
uint8_t minute;
102102
uint8_t second;
103+
unsigned int ms;
103104
uint8_t tzh;
104105
uint8_t tzm;
105106
};
@@ -148,6 +149,8 @@ class LTE_Shield : public Print {
148149
boolean poll(void);
149150
void setSocketReadCallback(void (*socketReadCallback)(int, String));
150151
void setSocketCloseCallback(void (*socketCloseCallback)(int));
152+
void setGpsReadCallback(void (*gpsRequestCallback)(ClockData time,
153+
PositionData gps, SpeedData spd, unsigned long uncertainty));
151154

152155
// Direct write/print to cell serial port
153156
virtual size_t write(uint8_t c);
@@ -164,6 +167,7 @@ class LTE_Shield : public Print {
164167
// Control and status AT commands
165168
LTE_Shield_error_t reset(void);
166169
String clock(void);
170+
// TODO: Return a clock struct
167171
LTE_Shield_error_t clock(uint8_t * y, uint8_t * mo, uint8_t * d,
168172
uint8_t * h, uint8_t * min, uint8_t * s, uint8_t * tz);
169173
LTE_Shield_error_t autoTimeZone(boolean enable);
@@ -238,6 +242,7 @@ class LTE_Shield : public Print {
238242
GNSS_SYSTEM_QZSS = 32,
239243
GNSS_SYSTEM_GLONASS = 64
240244
} gnss_system_t;
245+
boolean gpsOn(void);
241246
LTE_Shield_error_t gpsPower(boolean enable = true,
242247
gnss_system_t gnss_sys = GNSS_SYSTEM_GPS);
243248
LTE_Shield_error_t gpsEnableClock(boolean enable = true);
@@ -256,7 +261,7 @@ class LTE_Shield : public Print {
256261
LTE_Shield_error_t gpsEnableSpeed(boolean enable = true);
257262
LTE_Shield_error_t gpsGetSpeed(struct SpeedData * speed);
258263

259-
LTE_Shield_error_t gpsRequest(unsigned int timeout, unsigned int accuracy, boolean detailed);
264+
LTE_Shield_error_t gpsRequest(unsigned int timeout, unsigned int accuracy, boolean detailed = true);
260265

261266
private:
262267

@@ -273,7 +278,7 @@ class LTE_Shield : public Print {
273278

274279
void (*_socketReadCallback)(int, String);
275280
void (*_socketCloseCallback)(int);
276-
void (*_gpsRequestCallback)(ClockData time, PositionData gps, unsigned long uncertainty);
281+
void (*_gpsRequestCallback)(ClockData, PositionData, SpeedData, unsigned long);
277282

278283
typedef enum {
279284
LTE_SHIELD_INIT_STANDARD,

0 commit comments

Comments
 (0)