LoRaWAN-Signal-Mapping/iot/main/gps.cpp

113 lines
3.1 KiB
C++
Raw Normal View History

2019-07-15 14:25:51 +00:00
#include <TinyGPS.h>
#include "gps.h"
#include "settings.h"
2019-07-15 14:25:51 +00:00
#include "power.h"
#include "storage.h"
SoftwareSerial gps_begin() {
// FUTURE: If this doesn't work as expected, we may want to find a more reliable SoftwareSerial library
SoftwareSerial serial_gps(PIN_GPS_RX, PIN_GPS_TX);
// Initialise the software-based serial connection to the GPS device
serial_gps.begin(BAUD_GPS);
return serial_gps;
}
GPSLocation gps_fetch() {
// The serial connection to the GPS module
SoftwareSerial serial_gps = gps_begin();
// The GPS message decoder
TinyGPS gps;
// The struct that will hold the result
GPSLocation result;
2019-07-02 13:07:11 +00:00
Serial.print(F("[gps] Working "));
uint32_t start = millis(), ms_last_update = millis();
2019-06-27 15:27:33 +00:00
uint8_t ticks = 0;
unsigned long fix_age = TinyGPS::GPS_INVALID_AGE;
unsigned long chars;
unsigned short sentences, failed_checksum;
// We WILL discover our location - if it's the last thing we do!
while(true) {
gps.stats(&chars, &sentences, &failed_checksum);
if(millis() - start > 5000 && chars < 10) {
2019-07-02 13:07:11 +00:00
Serial.println(F("\n[error/gps] Init failed"));
while(true) { delay(1); }
}
// Make sure there's something to read
if(serial_gps.available() <= 0)
continue;
// If it failed, go around again
if(!gps.encode(serial_gps.read()))
continue;
gps.f_get_position(&(result.lat), &(result.lng), &fix_age);
// If we haven't acquired a lock yet, go around again
if(fix_age == TinyGPS::GPS_INVALID_AGE) {
// NOTE: It can take a rather long time to get a lock. Just wait patiently :-)
2019-06-27 15:27:33 +00:00
if(millis() - ms_last_update > 500) {
ticks++;
Serial.print('.');
2019-06-27 15:27:33 +00:00
if(ticks > 80) {
Serial.println();
ticks = 0;
}
ms_last_update = millis();
2019-06-27 15:27:33 +00:00
}
continue;
}
// Hooray!
2019-06-24 14:47:00 +00:00
Serial.println(F("ok"));
// gps.f_get_position pushes the values into result directly
2019-07-15 14:25:51 +00:00
#ifdef GPS_DELTA_CHECK
float last_reading_lat = store_eeprom_float_retrieve(sizeof(uint32_t) * 2);
float last_reading_lng = store_eeprom_float_retrieve(sizeof(uint32_t) * 2 + sizeof(float));
// Serial.println(last_reading_lat);
// Serial.println(last_reading_lng);
// Serial.println(result.lat);
// Serial.println(result.lng);
if(abs(last_reading_lat - result.lat) < GPS_DELTA_MIN_LAT &&
abs(last_reading_lng - result.lng) < GPS_DELTA_MIN_LNG &&
last_reading_lat == last_reading_lat && // Ensure that the last readings aren't NaN
last_reading_lng == last_reading_lng) {
Serial.println(F("[gps] No movement detected"));
power_off();
}
// Save this location to EEPROM
store_eeprom_float_save(sizeof(uint32_t) * 2, result.lat);
store_eeprom_float_save(sizeof(uint32_t) * 2 + sizeof(float), result.lng);
#endif
// TODO: Don't send a message at night
#ifdef SD_DEBUG_ENABLED
int year;
byte month, day, hour, minute, second, _hundredths;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &_hundredths, &fix_age);
snprintf(result.time, 19, "%04d-%02d-%02d %02d:%02d:%02d",
year, month, day,
hour, minute, second
);
#endif
return result;
}
gps_end(serial_gps);
}
void gps_end(SoftwareSerial serial_gps) {
serial_gps.end();
}