we are not valid until 60 PPS cycles after we have a valid gps
This commit is contained in:
parent
adc4412326
commit
aa265b1280
137
ESPNTPServer.cpp
137
ESPNTPServer.cpp
|
|
@ -27,16 +27,20 @@
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
Ticker validityTimer;
|
Ticker validityTimer;
|
||||||
uint32_t valid_count;
|
|
||||||
bool valid;
|
bool valid;
|
||||||
|
bool gps_valid;
|
||||||
|
uint32_t pps_valid_count;
|
||||||
|
volatile uint32_t valid_count; // how many times we have gone from invalid to valid
|
||||||
bool sentence_unknown;
|
bool sentence_unknown;
|
||||||
|
uint32_t bad_checksum_count;
|
||||||
|
uint32_t req_count;
|
||||||
|
uint32_t rsp_count;
|
||||||
int8_t precision;
|
int8_t precision;
|
||||||
volatile uint32_t dispersion;
|
volatile uint32_t dispersion;
|
||||||
|
|
||||||
volatile time_t seconds;
|
volatile time_t seconds;
|
||||||
|
|
||||||
volatile uint32_t last_micros;
|
volatile uint32_t last_micros;
|
||||||
volatile uint32_t micros_wraps;
|
|
||||||
volatile uint32_t min_micros;
|
volatile uint32_t min_micros;
|
||||||
volatile uint32_t max_micros;
|
volatile uint32_t max_micros;
|
||||||
|
|
||||||
|
|
@ -56,9 +60,7 @@ SoftwareSerial gps(GPS_RX_PIN, GPS_TX_PIN, false, SERIAL_BUFFER_SIZE);
|
||||||
char nmeaBuffer[NMEA_BUFFER_SIZE];
|
char nmeaBuffer[NMEA_BUFFER_SIZE];
|
||||||
MicroNMEA nmea(nmeaBuffer, NMEA_BUFFER_SIZE);
|
MicroNMEA nmea(nmeaBuffer, NMEA_BUFFER_SIZE);
|
||||||
|
|
||||||
#if defined(USE_OLED_DISPLAY)
|
|
||||||
SSD1306Wire display(0x3c, SDA, SCL);
|
SSD1306Wire display(0x3c, SDA, SCL);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NTP_PACKET_DEBUG
|
#ifdef NTP_PACKET_DEBUG
|
||||||
void dumpNTPPacket(NTPPacket* ntp)
|
void dumpNTPPacket(NTPPacket* ntp)
|
||||||
|
|
@ -83,19 +85,45 @@ void dumpNTPPacket(NTPPacket* ntp)
|
||||||
#define dumpNTPPacket(x)
|
#define dumpNTPPacket(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void validityCheck()
|
void invalidate()
|
||||||
{
|
{
|
||||||
valid = false;
|
valid = false;
|
||||||
|
gps_valid = false;
|
||||||
|
last_micros = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void oneSecondInterrupt()
|
void oneSecondInterrupt()
|
||||||
{
|
{
|
||||||
uint32_t cur_micros = micros();
|
uint32_t cur_micros = micros();
|
||||||
|
|
||||||
|
//
|
||||||
|
// don't trust PPS if GPS is not valid.
|
||||||
|
//
|
||||||
|
if (!gps_valid)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// if we are still counting down then keep waiting
|
||||||
|
//
|
||||||
|
if (pps_valid_count)
|
||||||
|
{
|
||||||
|
--pps_valid_count;
|
||||||
|
if (pps_valid_count == 0)
|
||||||
|
{
|
||||||
|
// clear stats and mark us valid
|
||||||
|
min_micros = 0;
|
||||||
|
max_micros = 0;
|
||||||
|
valid = true;
|
||||||
|
++valid_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// restart the validity timer, if it runs out we invalidate our data.
|
// restart the validity timer, if it runs out we invalidate our data.
|
||||||
//
|
//
|
||||||
validityTimer.attach_ms(VALIDITY_CHECK_MS, &validityCheck);
|
validityTimer.attach_ms(VALIDITY_CHECK_MS, &invalidate);
|
||||||
|
|
||||||
//
|
//
|
||||||
// increment seconds
|
// increment seconds
|
||||||
|
|
@ -111,11 +139,6 @@ void oneSecondInterrupt()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_micros < last_micros)
|
|
||||||
{
|
|
||||||
++micros_wraps;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t micros_count = cur_micros - last_micros;
|
uint32_t micros_count = cur_micros - last_micros;
|
||||||
last_micros = cur_micros;
|
last_micros = cur_micros;
|
||||||
|
|
||||||
|
|
@ -163,7 +186,6 @@ void getNTPTime(NTPTime *time)
|
||||||
}
|
}
|
||||||
|
|
||||||
double percent = us2s(micros_delta);
|
double percent = us2s(micros_delta);
|
||||||
//dbprintf("micros_delta: %lu percent: %lf\n", micros_delta, percent);
|
|
||||||
time->fraction = (uint32_t)(percent * (double)4294967296L);
|
time->fraction = (uint32_t)(percent * (double)4294967296L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,7 +211,8 @@ void recievePacket(AsyncUDPPacket aup)
|
||||||
void recievePacket()
|
void recievePacket()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static NTPPacket ntp;
|
++req_count;
|
||||||
|
NTPPacket ntp;
|
||||||
NTPTime recv_time;
|
NTPTime recv_time;
|
||||||
getNTPTime(&recv_time);
|
getNTPTime(&recv_time);
|
||||||
#if defined(USE_ASYNC_UDP)
|
#if defined(USE_ASYNC_UDP)
|
||||||
|
|
@ -257,6 +280,7 @@ void recievePacket()
|
||||||
ntp.xmit_time.fraction = htonl(ntp.xmit_time.fraction);
|
ntp.xmit_time.fraction = htonl(ntp.xmit_time.fraction);
|
||||||
#if defined(USE_ASYNC_UDP)
|
#if defined(USE_ASYNC_UDP)
|
||||||
aup.write((uint8_t*)&ntp, sizeof(ntp));
|
aup.write((uint8_t*)&ntp, sizeof(ntp));
|
||||||
|
++rsp_count;
|
||||||
#else
|
#else
|
||||||
IPAddress address = udp.remoteIP();
|
IPAddress address = udp.remoteIP();
|
||||||
uint16_t port = udp.remotePort();
|
uint16_t port = udp.remotePort();
|
||||||
|
|
@ -269,21 +293,21 @@ void recievePacket()
|
||||||
|
|
||||||
void badChecksum(MicroNMEA& mn)
|
void badChecksum(MicroNMEA& mn)
|
||||||
{
|
{
|
||||||
const char* s = mn.getSentence();
|
++bad_checksum_count;
|
||||||
dbprintf("badChecksum: (length:%d 1stbyte:%02x) '%s'\n", strlen(s), s[0], s);
|
dbprintf("badChecksum: '%s'\n", mn.getSentence());
|
||||||
}
|
}
|
||||||
|
|
||||||
void unknownSentence(MicroNMEA& mn)
|
void unknownSentence(MicroNMEA& mn)
|
||||||
{
|
{
|
||||||
const char* sentence = mn.getSentence();
|
const char* sentence = mn.getSentence();
|
||||||
|
dbprintf("unknownSentence: %s\n", sentence);
|
||||||
|
|
||||||
if (!strncmp("$PMTK", sentence, 5))
|
if (!strncmp("$PMTK", sentence, 5))
|
||||||
{
|
{
|
||||||
dbprintf("unknownSentence: %s\n", sentence);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sentence_unknown = true;
|
sentence_unknown = true;
|
||||||
dbprintf("unknownSentence: %s\n", sentence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetGPS()
|
void resetGPS()
|
||||||
|
|
@ -291,12 +315,15 @@ void resetGPS()
|
||||||
dbprintln("resetGPS: starting!");
|
dbprintln("resetGPS: starting!");
|
||||||
// Empty input buffer
|
// Empty input buffer
|
||||||
while (gps.available())
|
while (gps.available())
|
||||||
|
{
|
||||||
gps.read();
|
gps.read();
|
||||||
|
}
|
||||||
|
|
||||||
digitalWrite(GPS_EN_PIN, LOW);
|
digitalWrite(GPS_EN_PIN, LOW);
|
||||||
delay(100);
|
delay(100);
|
||||||
digitalWrite(GPS_EN_PIN, HIGH);
|
digitalWrite(GPS_EN_PIN, HIGH);
|
||||||
|
|
||||||
|
#if 0
|
||||||
dbprintln("resetGPS: waiting on first sentence");
|
dbprintln("resetGPS: waiting on first sentence");
|
||||||
dbflush();
|
dbflush();
|
||||||
|
|
||||||
|
|
@ -316,22 +343,37 @@ void resetGPS()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void processGPS()
|
void processGPS()
|
||||||
{
|
{
|
||||||
static boolean last_valid;
|
static boolean last_valid = false;
|
||||||
if (last_valid && !valid)
|
static boolean last_gps_valid = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Print valid or invalid if stats has changed.
|
||||||
|
//
|
||||||
|
if ((last_valid && !valid) || (last_gps_valid && !gps_valid))
|
||||||
{
|
{
|
||||||
dbprintln("INVALID!");
|
dbprintln("INVALID!");
|
||||||
}
|
}
|
||||||
|
else if (!last_valid && valid)
|
||||||
|
{
|
||||||
|
dbprintln("VALID!");
|
||||||
|
}
|
||||||
last_valid = valid;
|
last_valid = valid;
|
||||||
|
last_gps_valid = gps_valid;
|
||||||
|
|
||||||
while (gps.available() > 0)
|
while (gps.available() > 0)
|
||||||
{
|
{
|
||||||
if (nmea.process(gps.read()))
|
if (nmea.process(gps.read()))
|
||||||
{
|
{
|
||||||
if (nmea.isValid() && nmea.getYear() > 2000)
|
//
|
||||||
|
// if it was a GGA and its valid then check and maybe update the time
|
||||||
|
//
|
||||||
|
const char * id = nmea.getMessageID();
|
||||||
|
if (nmea.isValid() && nmea.getYear() > 2000 && strcmp("GGA", id) == 0)
|
||||||
{
|
{
|
||||||
static struct tm tm;
|
static struct tm tm;
|
||||||
tm.tm_year = nmea.getYear() - 1900;
|
tm.tm_year = nmea.getYear() - 1900;
|
||||||
|
|
@ -346,21 +388,17 @@ void processGPS()
|
||||||
if (old_seconds != new_seconds)
|
if (old_seconds != new_seconds)
|
||||||
{
|
{
|
||||||
seconds = new_seconds;
|
seconds = new_seconds;
|
||||||
dbprintf("adjusting seconds from %lu to %lu\n", old_seconds, new_seconds);
|
dbprintf("%010lu: %s adjusting seconds from %lu to %lu\n", millis(), nmea.getMessageID(), old_seconds, new_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// if we were not valid, we are now
|
// if gps was not valid, it is now
|
||||||
//
|
//
|
||||||
if (!valid)
|
if (!gps_valid)
|
||||||
{
|
{
|
||||||
// clear stats and mark us valid
|
gps_valid = true;
|
||||||
last_micros = 0;
|
pps_valid_count = PPS_VALID_COUNT;
|
||||||
min_micros = 0;
|
dbprintln("gps valid!");
|
||||||
max_micros = 0;
|
|
||||||
valid = true;
|
|
||||||
++valid_count;
|
|
||||||
dbprintln("VALID!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -379,6 +417,7 @@ void sendSentence(const char* sentence)
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
|
delay(5000); // delay for IDE to re-open serial
|
||||||
dbbegin(115200);
|
dbbegin(115200);
|
||||||
dbprintln("\n\nStartup!");
|
dbprintln("\n\nStartup!");
|
||||||
|
|
||||||
|
|
@ -400,19 +439,17 @@ void setup()
|
||||||
|
|
||||||
#if !defined(USE_NO_WIFI)
|
#if !defined(USE_NO_WIFI)
|
||||||
WiFiManager wifi;
|
WiFiManager wifi;
|
||||||
//wifi.setDebugOutput(false);
|
wifi.setDebugOutput(false);
|
||||||
String ssid = "SynchroClock" + String(ESP.getChipId());
|
String ssid = "SynchroClock" + String(ESP.getChipId());
|
||||||
wifi.autoConnect(ssid.c_str(), NULL);
|
wifi.autoConnect(ssid.c_str(), NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_OLED_DISPLAY)
|
|
||||||
if (!display.init())
|
if (!display.init())
|
||||||
{
|
{
|
||||||
dbprintln("display.init() failed!");
|
dbprintln("display.init() failed!");
|
||||||
}
|
}
|
||||||
display.flipScreenVertically();
|
display.flipScreenVertically();
|
||||||
display.setFont(ArialMT_Plain_10);
|
display.setFont(ArialMT_Plain_10);
|
||||||
#endif
|
|
||||||
|
|
||||||
gps.begin(9600);
|
gps.begin(9600);
|
||||||
nmea.setBadChecksumHandler(&badChecksum);
|
nmea.setBadChecksumHandler(&badChecksum);
|
||||||
|
|
@ -425,9 +462,11 @@ void setup()
|
||||||
// initialize UDP handler
|
// initialize UDP handler
|
||||||
//
|
//
|
||||||
#if defined(USE_ASYNC_UDP)
|
#if defined(USE_ASYNC_UDP)
|
||||||
while(!udp.listen(NTP_PORT)) {
|
while (!udp.listen(NTP_PORT))
|
||||||
|
{
|
||||||
#else
|
#else
|
||||||
while(!udp.begin(NTP_PORT)) {
|
while(!udp.begin(NTP_PORT))
|
||||||
|
{
|
||||||
#endif
|
#endif
|
||||||
dbprintf("setup: failed to listen on port %d! Will retry in a bit...\n", NTP_PORT);
|
dbprintf("setup: failed to listen on port %d! Will retry in a bit...\n", NTP_PORT);
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
@ -459,7 +498,9 @@ void loop()
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t last_seconds;
|
static time_t last_seconds;
|
||||||
if (seconds != last_seconds && (seconds % 60) == 0)
|
if (seconds != last_seconds)
|
||||||
|
{
|
||||||
|
if (seconds != last_seconds && ((seconds % 60) == 0 || pps_valid_count))
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(MICROS_HISTORY_SIZE)
|
#if defined(MICROS_HISTORY_SIZE)
|
||||||
|
|
@ -480,11 +521,15 @@ void loop()
|
||||||
#endif
|
#endif
|
||||||
double disp = us2s(MAX(abs(MICROS_PER_SEC-max_micros), abs(MICROS_PER_SEC-min_micros)));
|
double disp = us2s(MAX(abs(MICROS_PER_SEC-max_micros), abs(MICROS_PER_SEC-min_micros)));
|
||||||
dispersion = (uint32_t)(disp * 65536.0);
|
dispersion = (uint32_t)(disp * 65536.0);
|
||||||
dbprintf("min:%lu max:%lu jitter:%lu valid_count:%lu valid:%s heap:%ld\n",
|
dbprintf("min:%lu max:%lu jitter:%lu valid_count:%lu valid:%s numsat:%d heap:%ld pps_valid_count:%d badcs: %lu\n", min_micros, max_micros,
|
||||||
min_micros, max_micros, max_micros-min_micros,
|
max_micros - min_micros, valid_count, valid ? "true" : "false", nmea.getNumSatellites(), ESP.getFreeHeap(), pps_valid_count,
|
||||||
valid_count, valid?"true":"false", ESP.getFreeHeap());
|
bad_checksum_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (seconds < last_seconds)
|
||||||
|
{
|
||||||
|
dbprintf("OOPS: time went backwards: last:%lu now:%lu\n", last_seconds, seconds);
|
||||||
}
|
}
|
||||||
last_seconds = seconds;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update the display
|
// Update the display
|
||||||
|
|
@ -492,12 +537,16 @@ void loop()
|
||||||
display.clear();
|
display.clear();
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
display.setFont(ArialMT_Plain_10);
|
display.setFont(ArialMT_Plain_10);
|
||||||
const char* s = ctime(&last_seconds);
|
const char* current_time = ctime(&last_seconds);
|
||||||
display.drawString(0, 0, WiFi.localIP().toString());
|
display.drawString(0, 0, current_time);
|
||||||
display.drawString(0, 10, s);
|
display.drawString(0, 10, "Address: "+WiFi.localIP().toString());
|
||||||
display.drawString(0, 20, "Heap Free:"+String(ESP.getFreeHeap()));
|
display.drawString(0, 20, "Sat Count: " + String(nmea.getNumSatellites()));
|
||||||
|
display.drawString(0, 30, "Requests: " + String(req_count));
|
||||||
|
display.drawString(0, 40, "Responses: " + String(rsp_count));
|
||||||
// write the buffer to the display
|
// write the buffer to the display
|
||||||
display.display();
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
last_seconds = seconds;
|
||||||
delay(1);
|
delay(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USE_ASYNC_UDP
|
#define USE_ASYNC_UDP
|
||||||
#define USE_OLED_DISPLAY
|
|
||||||
//#define USE_NO_WIFI
|
//#define USE_NO_WIFI
|
||||||
|
|
||||||
#ifndef _ESPNTPServer_H_
|
#ifndef _ESPNTPServer_H_
|
||||||
|
|
@ -35,9 +34,7 @@
|
||||||
#include "MicroNMEA.h"
|
#include "MicroNMEA.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#if defined(USE_OLED_DISPLAY)
|
|
||||||
#include "SSD1306Wire.h"
|
#include "SSD1306Wire.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_ASYNC_UDP)
|
#if defined(USE_ASYNC_UDP)
|
||||||
#include "ESPAsyncUDP.h"
|
#include "ESPAsyncUDP.h"
|
||||||
|
|
@ -63,6 +60,7 @@
|
||||||
#define SERIAL_BUFFER_SIZE 128
|
#define SERIAL_BUFFER_SIZE 128
|
||||||
#define NMEA_BUFFER_SIZE 128
|
#define NMEA_BUFFER_SIZE 128
|
||||||
#define VALIDITY_CHECK_MS 1100
|
#define VALIDITY_CHECK_MS 1100
|
||||||
|
#define PPS_VALID_COUNT 60 // must have at least this many "good" PPS interrupts to be valid
|
||||||
//#define MICROS_HISTORY_SIZE 1000
|
//#define MICROS_HISTORY_SIZE 1000
|
||||||
|
|
||||||
#define us2s(x) (((double)x)/(double)MICROS_PER_SEC) // microseconds to seconds
|
#define us2s(x) (((double)x)/(double)MICROS_PER_SEC) // microseconds to seconds
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user