add distance interval
This commit is contained in:
parent
e61cec10a1
commit
5a2189be15
4 changed files with 48 additions and 37 deletions
|
@ -57,7 +57,7 @@ class TelnetPrint : public Print {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Is only called for Strings, not char arrays
|
||||
// Is only called for Strings, not char arrays?
|
||||
/*virtual size_t write(const char *buffer, size_t size) {
|
||||
for(uint8_t i = 0; i < MAX_TELNET_CLIENTS; i++){
|
||||
if (clients[i] && clients[i].connected()){
|
||||
|
|
8
config.h
8
config.h
|
@ -1,12 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
/* GENERAL */
|
||||
// interval of the measurements in ms. 0 for "as fast as possible"
|
||||
#define MEASUREMENT_INTERVAL 10000
|
||||
// interval of the measurements in millisec / meters
|
||||
#define MEASUREMENT_INTERVAL 10000 // 0 for "as fast as possible"
|
||||
#define MEASUREMENT_DISTANCE_ENABLED true
|
||||
#define MEASUREMENT_DISTANCE 25
|
||||
|
||||
// pull this pin down to disable measurements (eg for quickly bulk uploading stored measurements)
|
||||
#define PIN_MEASURE_MODE D14
|
||||
// pull this pin down to disable uploads (eg for higher measurement rates when no realtime data is required)
|
||||
#define PIN_UPLOAD_MODE D15
|
||||
|
||||
// should be higher than the number of sensors to avoid storage overflowing. tradeoff with the measurement interval
|
||||
#define MAX_UPLOADS_PER_CYCLE 4
|
||||
|
||||
|
|
25
gps.h
25
gps.h
|
@ -3,24 +3,22 @@
|
|||
#include <Time.h>
|
||||
#include "config.h"
|
||||
|
||||
// TODO: refactor updateXXX members to be protected and called by getXXX ?
|
||||
|
||||
class Gps {
|
||||
protected:
|
||||
TinyGPSPlus gps;
|
||||
|
||||
|
||||
public:
|
||||
void begin() {
|
||||
Serial.begin(GPS_BAUD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* parse all available bytes from the Serial input
|
||||
* should be called frequently to avoid buffer overflows
|
||||
*/
|
||||
void pollGPS() {
|
||||
while (Serial.available() > 0)
|
||||
gps.encode(Serial.read());
|
||||
gps.encode(Serial.read());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,14 +29,14 @@ class Gps {
|
|||
// abort if the GPS device does not push valid data within one update cycle
|
||||
static const unsigned int timeout = 2 * GPS_INTERVAL;
|
||||
unsigned long start = millis();
|
||||
|
||||
|
||||
do {
|
||||
pollGPS();
|
||||
if (millis() - start > timeout) return false;
|
||||
} while (!gps.location.isUpdated()); // TODO: check if is valid?
|
||||
} while (!gps.location.isUpdated() && !gps.location.isValid());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* poll until we have a valid date & time.
|
||||
* retries at most once, returns success state
|
||||
|
@ -48,23 +46,22 @@ class Gps {
|
|||
static const unsigned int timeout = 2 * GPS_INTERVAL;
|
||||
unsigned long start = millis();
|
||||
|
||||
// TODO: check if is valid?
|
||||
do {
|
||||
pollGPS();
|
||||
if (millis() - start > timeout) return false;
|
||||
} while ( !(gps.date.isUpdated() && gps.time.isUpdated()) );
|
||||
|
||||
} while ( !(gps.date.isUpdated() && gps.time.isUpdated() && gps.time.isValid() && gps.time.isValid()) );
|
||||
|
||||
// in case we didnt timeout, resync the local clock (Time.h)
|
||||
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(),
|
||||
gps.date.day(), gps.date.month(), gps.date.year());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TinyGPSLocation& getLocation() {
|
||||
return gps.location;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fill a char[20] with an iso8601 formatted date from now
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <TinyGPS++.h>
|
||||
#include "config.h"
|
||||
#include "gps.h"
|
||||
#include "wifi.h"
|
||||
|
@ -14,6 +15,10 @@ TelnetPrint telnet = TelnetPrint();
|
|||
OsemApi api = OsemApi();
|
||||
Gps gps = Gps();
|
||||
|
||||
unsigned long cycleStart;
|
||||
WifiState wifiState; // global, as both measure and upload need the state
|
||||
TinyGPSLocation location;
|
||||
|
||||
bool storeMeasurement(float lat, float lng, float value, const char* timeStamp, const char* sensorID) {
|
||||
Measurement m;
|
||||
m.lat = lat;
|
||||
|
@ -24,22 +29,21 @@ bool storeMeasurement(float lat, float lng, float value, const char* timeStamp,
|
|||
return storage.add(m);
|
||||
}
|
||||
|
||||
void measure(WifiState& wifiState) {
|
||||
void measure(WifiState& wifiState, TinyGPSLocation& loc) {
|
||||
char dateString[20];
|
||||
|
||||
// measure WiFi
|
||||
wifiState = wifi.scan(WIFI_SSID);
|
||||
|
||||
// update gps position
|
||||
// TODO: how to handle lost GPS fix?
|
||||
// TODO: check if is data is valid?
|
||||
// update gps position if we can't get a fix, skip the measurements
|
||||
if(!gps.updateLocation() || !gps.updateTime()) {
|
||||
DEBUG_OUT << "GPS timed out" << EOL;
|
||||
digitalWrite(BUILTIN_LED, LOW);
|
||||
} else {
|
||||
digitalWrite(BUILTIN_LED, HIGH);
|
||||
DEBUG_OUT << "GPS timed out, skipping measurements" << EOL;
|
||||
digitalWrite(BUILTIN_LED, LOW); // turn status LED on
|
||||
return;
|
||||
}
|
||||
TinyGPSLocation loc = gps.getLocation();
|
||||
|
||||
digitalWrite(BUILTIN_LED, HIGH);
|
||||
loc = gps.getLocation();
|
||||
gps.getISODate(dateString);
|
||||
|
||||
// print state
|
||||
|
@ -100,13 +104,22 @@ void upload(WifiState& wifiState) {
|
|||
// delay for a given duration (ms), rollover-safe implementation
|
||||
// offset may be a duration which has been "used up" before, so the delay is adaptive,
|
||||
// meaning that the interval of a adaptiveDelay() call is constant
|
||||
void adaptiveDelay(unsigned long ms, unsigned long offset = 0) {
|
||||
// returns earlier, if we moved more than MEASUREMENT_DISTANCE meters from our last fix
|
||||
void adaptiveDelay(unsigned long ms, TinyGPSLocation& lastLoc, unsigned long offset = 0) {
|
||||
unsigned long start = millis();
|
||||
for (;;) {
|
||||
// for some reason, operations have to be performed in this loop for
|
||||
// proper operation, so we just do the polling to be done anyway
|
||||
gps.pollGPS();
|
||||
telnet.pollClients();
|
||||
|
||||
// update our location. if we moved MEASUREMENT_DISTANCE meters or more, return
|
||||
TinyGPSLocation newLoc = gps.getLocation();
|
||||
double distanceToPrevLoc = TinyGPSPlus::distanceBetween(lastLoc.lat(), lastLoc.lng(), newLoc.lat(), newLoc.lng());
|
||||
if (MEASUREMENT_DISTANCE_ENABLED && distanceToPrevLoc >= MEASUREMENT_DISTANCE) {
|
||||
DEBUG_OUT << "moved " << distanceToPrevLoc << "m, delay stopped." << EOL;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long now = millis();
|
||||
unsigned long elapsed = now - start + offset;
|
||||
|
@ -135,6 +148,7 @@ void setup() {
|
|||
// wait until we got a first fix from GPS, and thus an initial time
|
||||
DEBUG_OUT << "Getting GPS fix..";
|
||||
while (!gps.updateLocation()) { DEBUG_OUT << "."; }
|
||||
location = gps.getLocation();
|
||||
DEBUG_OUT << " done!" << EOL;
|
||||
digitalWrite(BUILTIN_LED, HIGH);
|
||||
|
||||
|
@ -144,26 +158,22 @@ void setup() {
|
|||
DEBUG_OUT << "SPIFF bytes free: " << bytesFree << EOL << EOL;
|
||||
}
|
||||
|
||||
unsigned long cycleStart;
|
||||
WifiState wifiState; // global, as both measure and upload need the state
|
||||
|
||||
void loop() {
|
||||
cycleStart = millis();
|
||||
|
||||
if (digitalRead(PIN_MEASURE_MODE) == HIGH)
|
||||
measure(wifiState);
|
||||
measure(wifiState, location);
|
||||
|
||||
if (digitalRead(PIN_UPLOAD_MODE) == HIGH)
|
||||
upload(wifiState);
|
||||
|
||||
if (digitalRead(PIN_MEASURE_MODE) == HIGH) {
|
||||
// run the measurements in a fixed interval, using an adaptive delay
|
||||
// IDEA: dont use time but distance interval? -> TinyGPSPlus::distanceBetween()
|
||||
adaptiveDelay(MEASUREMENT_INTERVAL, millis() - cycleStart);
|
||||
} else {
|
||||
// run as fast as possible when not measuring.
|
||||
// adaptiveDelay has to be called anyway, as some polling functions are run within
|
||||
adaptiveDelay(0);
|
||||
// the interval is defined by a duration and/or distance from our last fix
|
||||
return adaptiveDelay(MEASUREMENT_INTERVAL, location, millis() - cycleStart);
|
||||
}
|
||||
// run as fast as possible when not measuring.
|
||||
// smartDelay has to be called anyway, as some polling functions are run within
|
||||
adaptiveDelay(0, location);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue