This commit is contained in:
geeksville 2020-05-04 17:39:57 -07:00
parent 101eef5495
commit c2be6c4068
9 changed files with 129 additions and 36 deletions

View File

@ -52,6 +52,7 @@
"cSpell.words": [
"Blox",
"Meshtastic",
"NEMAGPS",
"Ublox",
"descs",
"protobufs"

View File

@ -24,6 +24,7 @@ Minimum items needed to make sure hardware is good.
Needed to be fully functional at least at the same level of the ESP32 boards. At this point users would probably want them.
- stop polling for GPS characters, instead stay blocked on read in a thread
- increase preamble length? - will break other clients? so all devices must update
- enable BLE DFU somehow
- set appversion/hwversion

View File

@ -74,6 +74,7 @@ lib_deps =
https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
https://github.com/meshtastic/RadioLib.git
https://github.com/meshtastic/TinyGPSPlus.git
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]

View File

@ -50,6 +50,24 @@ void perhapsSetRTC(const struct timeval *tv)
}
}
void perhapsSetRTC(struct tm &t)
{
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
*/
time_t res = mktime(&t);
struct timeval tv;
tv.tv_sec = res;
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
if (t.tm_year < 0 || t.tm_year >= 300)
DEBUG_MSG("Ignoring invalid GPS time\n");
else
perhapsSetRTC(&tv);
}
#include <time.h>
uint32_t getTime()

View File

@ -6,6 +6,7 @@
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
void perhapsSetRTC(const struct timeval *tv);
void perhapsSetRTC(struct tm &t);
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
uint32_t getTime();
@ -37,7 +38,10 @@ class GPS : public Observable<void *>
/**
* Returns true if we succeeded
*/
virtual bool setup() = 0;
virtual bool setup() { return true; }
/// A loop callback for subclasses that need it. FIXME, instead just block on serial reads
virtual void loop() {}
/// Returns ture if we have acquired GPS lock.
bool hasLock() const { return hasValidLocation; }

56
src/gps/NEMAGPS.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "NEMAGPS.h"
#include "configuration.h"
static int32_t toDegInt(RawDegrees d)
{
int32_t degMult = 10000000; // 1e7
int32_t r = d.deg * degMult + d.billionths / 100;
if (d.negative)
r *= -1;
return r;
}
void NEMAGPS::loop()
{
while (_serial_gps.available() > 0) {
int c = _serial_gps.read();
Serial.write(c);
reader.encode(c);
}
auto ti = reader.time;
auto d = reader.date;
if (ti.isUpdated() && ti.isValid() && d.isValid()) {
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
*/
struct tm t;
t.tm_sec = ti.second();
t.tm_min = ti.minute();
t.tm_hour = ti.hour();
t.tm_mday = d.day();
t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900;
t.tm_isdst = false;
perhapsSetRTC(t);
}
if (reader.altitude.isUpdated() || reader.location.isUpdated()) { // probably get updated at the same time
if (reader.altitude.isValid())
altitude = reader.altitude.meters();
auto loc = reader.location;
if (loc.isValid()) {
latitude = toDegInt(loc.rawLat());
longitude = toDegInt(loc.rawLng());
}
// expect gps pos lat=37.520825, lon=-122.309162, alt=158
DEBUG_MSG("new NEMA GPS pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude);
hasValidLocation = (latitude != 0) || (longitude != 0); // bogus lat lon is reported as 0,0
if (hasValidLocation)
notifyObservers(NULL);
}
}

19
src/gps/NEMAGPS.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include "GPS.h"
#include "Observer.h"
#include "PeriodicTask.h"
#include "TinyGPS++.h"
/**
* A gps class thatreads from a NEMA GPS stream (and FIXME - eventually keeps the gps powered down except when reading)
*
* When new data is available it will notify observers.
*/
class NEMAGPS : public GPS
{
TinyGPSPlus reader;
public:
virtual void loop();
};

View File

@ -9,8 +9,6 @@ UBloxGPS::UBloxGPS() : PeriodicTask()
bool UBloxGPS::setup()
{
PeriodicTask::setup();
#ifdef GPS_RX_PIN
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
#else
@ -30,18 +28,18 @@ bool UBloxGPS::setup()
if (isConnected) {
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
bool factoryReset = false;
bool factoryReset = true;
bool ok;
if (factoryReset) {
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
// GPS_TX connected)
ublox.factoryReset();
delay(2000);
delay(3000);
isConnected = ublox.begin(_serial_gps);
DEBUG_MSG("Factory reset success=%d\n", isConnected);
if (isConnected) {
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now
}
ok = ublox.saveConfiguration(3000);
assert(ok);
return false;
} else {
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
assert(ok);
@ -57,12 +55,10 @@ bool UBloxGPS::setup()
ok = ublox.saveConfiguration(3000);
assert(ok);
PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
return true;
} else {
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
// assume NEMA at 9600 baud.
DEBUG_MSG("ERROR: No bidirectional GPS found, hoping that it still might work\n");
return false;
}
}
@ -80,7 +76,8 @@ void UBloxGPS::doTask()
{
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix
if (isConnected) {
assert(isConnected);
// Consume all characters that have arrived
// getPVT automatically calls checkUblox
@ -91,15 +88,12 @@ void UBloxGPS::doTask()
// turn off for now
// fixtype = ublox.getFixType();
DEBUG_MSG("fix type %d\n", fixtype);
}
// DEBUG_MSG("sec %d\n", ublox.getSecond());
// DEBUG_MSG("lat %d\n", ublox.getLatitude());
// any fix that has time
if (ublox.getT()) {
struct timeval tv;
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
(midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).
@ -112,15 +106,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_mon = ublox.getMonth() - 1;
t.tm_year = ublox.getYear() - 1900;
t.tm_isdst = false;
time_t res = mktime(&t);
tv.tv_sec = res;
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
if (t.tm_year < 0 || t.tm_year >= 300)
DEBUG_MSG("Ignoring invalid GPS time\n");
else
perhapsSetRTC(&tv);
perhapsSetRTC(t);
}
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only

View File

@ -23,6 +23,7 @@
#include "MeshRadio.h"
#include "MeshService.h"
#include "NEMAGPS.h"
#include "NodeDB.h"
#include "Periodic.h"
#include "PowerFSM.h"
@ -193,7 +194,12 @@ void setup()
// Init GPS - first try ublox
gps = new UBloxGPS();
if (!gps->setup()) {
// FIXME - fallback to NEMA
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
// assume NEMA at 9600 baud.
DEBUG_MSG("ERROR: No UBLOX GPS found, hoping that NEMA might work\n");
delete gps;
gps = new NEMAGPS();
gps->setup();
}
service.init();
@ -263,6 +269,7 @@ void loop()
{
uint32_t msecstosleep = 1000 * 30; // How long can we sleep before we again need to service the main loop?
gps->loop(); // FIXME, remove from main, instead block on read
router.loop();
powerFSM.run_machine();
service.loop();