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": [ "cSpell.words": [
"Blox", "Blox",
"Meshtastic", "Meshtastic",
"NEMAGPS",
"Ublox", "Ublox",
"descs", "descs",
"protobufs" "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. 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 - increase preamble length? - will break other clients? so all devices must update
- enable BLE DFU somehow - enable BLE DFU somehow
- set appversion/hwversion - set appversion/hwversion

View File

@ -74,6 +74,7 @@ lib_deps =
https://github.com/meshtastic/arduino-fsm.git https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
https://github.com/meshtastic/RadioLib.git https://github.com/meshtastic/RadioLib.git
https://github.com/meshtastic/TinyGPSPlus.git
; Common settings for ESP targes, mixin with extends = esp32_base ; Common settings for ESP targes, mixin with extends = esp32_base
[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> #include <time.h>
uint32_t getTime() 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 /// 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(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 /// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero
uint32_t getTime(); uint32_t getTime();
@ -37,7 +38,10 @@ class GPS : public Observable<void *>
/** /**
* Returns true if we succeeded * 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. /// Returns ture if we have acquired GPS lock.
bool hasLock() const { return hasValidLocation; } 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() bool UBloxGPS::setup()
{ {
PeriodicTask::setup();
#ifdef GPS_RX_PIN #ifdef GPS_RX_PIN
_serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN); _serial_gps.begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
#else #else
@ -30,18 +28,18 @@ bool UBloxGPS::setup()
if (isConnected) { if (isConnected) {
DEBUG_MSG("Connected to UBLOX GPS successfully\n"); DEBUG_MSG("Connected to UBLOX GPS successfully\n");
bool factoryReset = false; bool factoryReset = true;
bool ok; bool ok;
if (factoryReset) { if (factoryReset) {
// It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have // It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have
// GPS_TX connected) // GPS_TX connected)
ublox.factoryReset(); ublox.factoryReset();
delay(2000); delay(3000);
isConnected = ublox.begin(_serial_gps); isConnected = ublox.begin(_serial_gps);
DEBUG_MSG("Factory reset success=%d\n", isConnected); DEBUG_MSG("Factory reset success=%d\n", isConnected);
if (isConnected) { ok = ublox.saveConfiguration(3000);
ublox.assumeAutoPVT(true, true); // Just parse NEMA for now assert(ok);
} return false;
} else { } else {
ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API
assert(ok); assert(ok);
@ -57,12 +55,10 @@ bool UBloxGPS::setup()
ok = ublox.saveConfiguration(3000); ok = ublox.saveConfiguration(3000);
assert(ok); assert(ok);
PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device
return true; return true;
} else { } 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; return false;
} }
} }
@ -80,26 +76,24 @@ void UBloxGPS::doTask()
{ {
uint8_t fixtype = 3; // If we are only using the RX pin, assume we have a 3d fix 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 // Consume all characters that have arrived
ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
// If we don't have a fix (a quick check), don't try waiting for a solution) // getPVT automatically calls checkUblox
// Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions ublox.checkUblox(); // See if new data is available. Process bytes as they come in.
// turn off for now
// fixtype = ublox.getFixType(); // If we don't have a fix (a quick check), don't try waiting for a solution)
DEBUG_MSG("fix type %d\n", fixtype); // Hmmm my fix type reading returns zeros for fix, which doesn't seem correct, because it is still sptting out positions
} // turn off for now
// fixtype = ublox.getFixType();
DEBUG_MSG("fix type %d\n", fixtype);
// DEBUG_MSG("sec %d\n", ublox.getSecond()); // DEBUG_MSG("sec %d\n", ublox.getSecond());
// DEBUG_MSG("lat %d\n", ublox.getLatitude()); // DEBUG_MSG("lat %d\n", ublox.getLatitude());
// any fix that has time // any fix that has time
if (ublox.getT()) { if (ublox.getT()) {
struct timeval tv;
/* Convert to unix time /* 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 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). (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_mon = ublox.getMonth() - 1;
t.tm_year = ublox.getYear() - 1900; t.tm_year = ublox.getYear() - 1900;
t.tm_isdst = false; t.tm_isdst = false;
time_t res = mktime(&t); perhapsSetRTC(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);
} }
if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only if ((fixtype >= 3 && fixtype <= 4) && ublox.getP()) // rd fixes only

View File

@ -23,6 +23,7 @@
#include "MeshRadio.h" #include "MeshRadio.h"
#include "MeshService.h" #include "MeshService.h"
#include "NEMAGPS.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "Periodic.h" #include "Periodic.h"
#include "PowerFSM.h" #include "PowerFSM.h"
@ -193,7 +194,12 @@ void setup()
// Init GPS - first try ublox // Init GPS - first try ublox
gps = new UBloxGPS(); gps = new UBloxGPS();
if (!gps->setup()) { 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(); 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? 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(); router.loop();
powerFSM.run_machine(); powerFSM.run_machine();
service.loop(); service.loop();