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"
|
||||
|
||||
Ticker validityTimer;
|
||||
uint32_t valid_count;
|
||||
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;
|
||||
uint32_t bad_checksum_count;
|
||||
uint32_t req_count;
|
||||
uint32_t rsp_count;
|
||||
int8_t precision;
|
||||
volatile uint32_t dispersion;
|
||||
|
||||
volatile time_t seconds;
|
||||
|
||||
volatile uint32_t last_micros;
|
||||
volatile uint32_t micros_wraps;
|
||||
volatile uint32_t min_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];
|
||||
MicroNMEA nmea(nmeaBuffer, NMEA_BUFFER_SIZE);
|
||||
|
||||
#if defined(USE_OLED_DISPLAY)
|
||||
SSD1306Wire display(0x3c, SDA, SCL);
|
||||
#endif
|
||||
|
||||
#ifdef NTP_PACKET_DEBUG
|
||||
void dumpNTPPacket(NTPPacket* ntp)
|
||||
|
|
@ -83,19 +85,45 @@ void dumpNTPPacket(NTPPacket* ntp)
|
|||
#define dumpNTPPacket(x)
|
||||
#endif
|
||||
|
||||
void validityCheck()
|
||||
void invalidate()
|
||||
{
|
||||
valid = false;
|
||||
gps_valid = false;
|
||||
last_micros = 0;
|
||||
}
|
||||
|
||||
void oneSecondInterrupt()
|
||||
{
|
||||
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.
|
||||
//
|
||||
validityTimer.attach_ms(VALIDITY_CHECK_MS, &validityCheck);
|
||||
validityTimer.attach_ms(VALIDITY_CHECK_MS, &invalidate);
|
||||
|
||||
//
|
||||
// increment seconds
|
||||
|
|
@ -111,11 +139,6 @@ void oneSecondInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (cur_micros < last_micros)
|
||||
{
|
||||
++micros_wraps;
|
||||
}
|
||||
|
||||
uint32_t micros_count = cur_micros - last_micros;
|
||||
last_micros = cur_micros;
|
||||
|
||||
|
|
@ -163,7 +186,6 @@ void getNTPTime(NTPTime *time)
|
|||
}
|
||||
|
||||
double percent = us2s(micros_delta);
|
||||
//dbprintf("micros_delta: %lu percent: %lf\n", micros_delta, percent);
|
||||
time->fraction = (uint32_t)(percent * (double)4294967296L);
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +211,8 @@ void recievePacket(AsyncUDPPacket aup)
|
|||
void recievePacket()
|
||||
#endif
|
||||
{
|
||||
static NTPPacket ntp;
|
||||
++req_count;
|
||||
NTPPacket ntp;
|
||||
NTPTime recv_time;
|
||||
getNTPTime(&recv_time);
|
||||
#if defined(USE_ASYNC_UDP)
|
||||
|
|
@ -257,6 +280,7 @@ void recievePacket()
|
|||
ntp.xmit_time.fraction = htonl(ntp.xmit_time.fraction);
|
||||
#if defined(USE_ASYNC_UDP)
|
||||
aup.write((uint8_t*)&ntp, sizeof(ntp));
|
||||
++rsp_count;
|
||||
#else
|
||||
IPAddress address = udp.remoteIP();
|
||||
uint16_t port = udp.remotePort();
|
||||
|
|
@ -269,21 +293,21 @@ void recievePacket()
|
|||
|
||||
void badChecksum(MicroNMEA& mn)
|
||||
{
|
||||
const char* s = mn.getSentence();
|
||||
dbprintf("badChecksum: (length:%d 1stbyte:%02x) '%s'\n", strlen(s), s[0], s);
|
||||
++bad_checksum_count;
|
||||
dbprintf("badChecksum: '%s'\n", mn.getSentence());
|
||||
}
|
||||
|
||||
void unknownSentence(MicroNMEA& mn)
|
||||
{
|
||||
const char* sentence = mn.getSentence();
|
||||
dbprintf("unknownSentence: %s\n", sentence);
|
||||
|
||||
if (!strncmp("$PMTK", sentence, 5))
|
||||
{
|
||||
dbprintf("unknownSentence: %s\n", sentence);
|
||||
return;
|
||||
}
|
||||
|
||||
sentence_unknown = true;
|
||||
dbprintf("unknownSentence: %s\n", sentence);
|
||||
}
|
||||
|
||||
void resetGPS()
|
||||
|
|
@ -291,12 +315,15 @@ void resetGPS()
|
|||
dbprintln("resetGPS: starting!");
|
||||
// Empty input buffer
|
||||
while (gps.available())
|
||||
{
|
||||
gps.read();
|
||||
}
|
||||
|
||||
digitalWrite(GPS_EN_PIN, LOW);
|
||||
delay(100);
|
||||
digitalWrite(GPS_EN_PIN, HIGH);
|
||||
|
||||
#if 0
|
||||
dbprintln("resetGPS: waiting on first sentence");
|
||||
dbflush();
|
||||
|
||||
|
|
@ -316,22 +343,37 @@ void resetGPS()
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void processGPS()
|
||||
{
|
||||
static boolean last_valid;
|
||||
if (last_valid && !valid)
|
||||
static boolean last_valid = false;
|
||||
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!");
|
||||
}
|
||||
else if (!last_valid && valid)
|
||||
{
|
||||
dbprintln("VALID!");
|
||||
}
|
||||
last_valid = valid;
|
||||
last_gps_valid = gps_valid;
|
||||
|
||||
while (gps.available() > 0)
|
||||
{
|
||||
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;
|
||||
tm.tm_year = nmea.getYear() - 1900;
|
||||
|
|
@ -346,21 +388,17 @@ void processGPS()
|
|||
if (old_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
|
||||
last_micros = 0;
|
||||
min_micros = 0;
|
||||
max_micros = 0;
|
||||
valid = true;
|
||||
++valid_count;
|
||||
dbprintln("VALID!");
|
||||
gps_valid = true;
|
||||
pps_valid_count = PPS_VALID_COUNT;
|
||||
dbprintln("gps valid!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -379,6 +417,7 @@ void sendSentence(const char* sentence)
|
|||
|
||||
void setup()
|
||||
{
|
||||
delay(5000); // delay for IDE to re-open serial
|
||||
dbbegin(115200);
|
||||
dbprintln("\n\nStartup!");
|
||||
|
||||
|
|
@ -400,19 +439,17 @@ void setup()
|
|||
|
||||
#if !defined(USE_NO_WIFI)
|
||||
WiFiManager wifi;
|
||||
//wifi.setDebugOutput(false);
|
||||
wifi.setDebugOutput(false);
|
||||
String ssid = "SynchroClock" + String(ESP.getChipId());
|
||||
wifi.autoConnect(ssid.c_str(), NULL);
|
||||
#endif
|
||||
|
||||
#if defined(USE_OLED_DISPLAY)
|
||||
if (!display.init())
|
||||
{
|
||||
dbprintln("display.init() failed!");
|
||||
}
|
||||
display.flipScreenVertically();
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
#endif
|
||||
|
||||
gps.begin(9600);
|
||||
nmea.setBadChecksumHandler(&badChecksum);
|
||||
|
|
@ -425,9 +462,11 @@ void setup()
|
|||
// initialize UDP handler
|
||||
//
|
||||
#if defined(USE_ASYNC_UDP)
|
||||
while(!udp.listen(NTP_PORT)) {
|
||||
while (!udp.listen(NTP_PORT))
|
||||
{
|
||||
#else
|
||||
while(!udp.begin(NTP_PORT)) {
|
||||
while(!udp.begin(NTP_PORT))
|
||||
{
|
||||
#endif
|
||||
dbprintf("setup: failed to listen on port %d! Will retry in a bit...\n", NTP_PORT);
|
||||
delay(1000);
|
||||
|
|
@ -459,7 +498,9 @@ void loop()
|
|||
}
|
||||
|
||||
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)
|
||||
|
|
@ -480,11 +521,15 @@ void loop()
|
|||
#endif
|
||||
double disp = us2s(MAX(abs(MICROS_PER_SEC-max_micros), abs(MICROS_PER_SEC-min_micros)));
|
||||
dispersion = (uint32_t)(disp * 65536.0);
|
||||
dbprintf("min:%lu max:%lu jitter:%lu valid_count:%lu valid:%s heap:%ld\n",
|
||||
min_micros, max_micros, max_micros-min_micros,
|
||||
valid_count, valid?"true":"false", ESP.getFreeHeap());
|
||||
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,
|
||||
max_micros - min_micros, valid_count, valid ? "true" : "false", nmea.getNumSatellites(), ESP.getFreeHeap(), pps_valid_count,
|
||||
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
|
||||
|
|
@ -492,12 +537,16 @@ void loop()
|
|||
display.clear();
|
||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display.setFont(ArialMT_Plain_10);
|
||||
const char* s = ctime(&last_seconds);
|
||||
display.drawString(0, 0, WiFi.localIP().toString());
|
||||
display.drawString(0, 10, s);
|
||||
display.drawString(0, 20, "Heap Free:"+String(ESP.getFreeHeap()));
|
||||
const char* current_time = ctime(&last_seconds);
|
||||
display.drawString(0, 0, current_time);
|
||||
display.drawString(0, 10, "Address: "+WiFi.localIP().toString());
|
||||
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
|
||||
display.display();
|
||||
}
|
||||
|
||||
last_seconds = seconds;
|
||||
delay(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
*/
|
||||
|
||||
#define USE_ASYNC_UDP
|
||||
#define USE_OLED_DISPLAY
|
||||
//#define USE_NO_WIFI
|
||||
|
||||
#ifndef _ESPNTPServer_H_
|
||||
|
|
@ -35,9 +34,7 @@
|
|||
#include "MicroNMEA.h"
|
||||
#include <time.h>
|
||||
|
||||
#if defined(USE_OLED_DISPLAY)
|
||||
#include "SSD1306Wire.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_ASYNC_UDP)
|
||||
#include "ESPAsyncUDP.h"
|
||||
|
|
@ -63,6 +60,7 @@
|
|||
#define SERIAL_BUFFER_SIZE 128
|
||||
#define NMEA_BUFFER_SIZE 128
|
||||
#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 us2s(x) (((double)x)/(double)MICROS_PER_SEC) // microseconds to seconds
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user