update xsns_60_GPS.ino

This commit is contained in:
Staars 2020-04-06 19:24:11 +02:00
parent 17c605ac6a
commit cefc278bdf
2 changed files with 99 additions and 61 deletions

View File

@ -17,63 +17,81 @@
bool NtpServer::beginListening() bool NtpServer::beginListening()
{ {
if (timeServerPort_.begin(NTP_PORT)){ if (timeServerPort_.begin(NTP_PORT)){
return true; return true;
} }
return false; return false;
} }
bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs) bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs)
{ {
// We need the time we've received the packet in our response. // millisecs is millis() at the time of the last iTOW reception, where iTOW%1000 == 0
uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF; uint32_t refMillis = millis()-millisecs;
double recvFractDouble = (double)millisecs/0.00023283064365386963; // millisec/((10^6)/(2^32)) if (refMillis>999){
uint32_t recvFract = (double)recvFractDouble; //TODO: really handle this!!! utc++;
bool processed = false; refMillis = refMillis%1000;
}
int packetDataSize = timeServerPort_.parsePacket();
if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
{
// Received what is probably an NTP packet. Read it in and verify
// that it's legit.
NtpPacket packet;
timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
// TODO: verify packet.
// Populate response. bool processed = false;
packet.swapEndian();
packet.leapIndicator(0); int packetDataSize = timeServerPort_.parsePacket();
packet.versionNumber(4); if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
packet.mode(4); {
packet.stratum = 2; // I guess stratum 1 is too optimistic // We need the time we've received the packet in our response.
packet.poll = 10; // 6-10 per RFC 5905. uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
packet.precision = -21; // ~0.5 microsecond precision.
packet.rootDelay = 0; //60 * (0xFFFF / 1000); // ~60 milliseconds, TBD uint64_t recvFract64 = refMillis;
packet.rootDispersion = 0; //10 * (0xFFFF / 1000); // ~10 millisecond dispersion, TBD recvFract64 <<= 32;
packet.referenceId[0] = 'G'; recvFract64 /= 1000;
packet.referenceId[1] = 'P'; uint32_t recvFract = recvFract64 & 0xffffffff;
packet.referenceId[2] = 'S'; // is equal to:
packet.referenceId[3] = 0; // uint32_t recvFract = (double)(refMillis)/0.00000023283064365386963;
packet.referenceTimestampSeconds = utc;
packet.referenceTimestampFraction = recvFract; // Received what is probably an NTP packet. Read it in and verify
packet.originTimestampSeconds = packet.transmitTimestampSeconds; // that it's legit.
packet.originTimestampFraction = packet.transmitTimestampFraction; NtpPacket packet;
packet.receiveTimestampSeconds = recvSecs; timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
packet.receiveTimestampFraction = recvFract; // TODO: verify packet.
// ...and the transmit time. // Populate response.
// timeSource_.now(&packet.transmitTimestampSeconds, &packet.transmitTimestampFraction); packet.swapEndian();
packet.leapIndicator(0);
// Now transmit the response to the client. packet.versionNumber(4);
packet.swapEndian(); packet.mode(4);
timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort()); packet.stratum = 1; // >1 will lead to misinterpretation of refId
for (int count = 0; count < NtpPacket::PACKET_SIZE; count++) packet.poll = 10; // 6-10 per RFC 5905.
{ packet.precision = -21; // ~0.5 microsecond precision.
timeServerPort_.write(packet.packet()[count]); packet.rootDelay = 100 * (0xFFFF / 1000); //~100 milliseconds
} packet.rootDispersion = 50 * (0xFFFF / 1000);; //~50 millisecond dispersion
timeServerPort_.endPacket(); packet.referenceId[0] = 'G';
processed = true; packet.referenceId[1] = 'P';
} packet.referenceId[2] = 'S';
packet.referenceId[3] = 0;
return processed; packet.referenceTimestampSeconds = recvSecs;
packet.referenceTimestampFraction = 0; // the "click" of the GPS
packet.originTimestampSeconds = packet.transmitTimestampSeconds;
packet.originTimestampFraction = packet.transmitTimestampFraction;
packet.receiveTimestampSeconds = recvSecs;
packet.receiveTimestampFraction = recvFract;
// ...and the transmit time.
// the latency has been between 135 and 175 microseconds in internal testing, so we harcode 150
uint32_t transFract = recvFract+(150*(10^3)/(2^32)); // microsec/((10^3)/(2^32))
if (recvFract>transFract){
recvSecs++; //overflow
}
packet.transmitTimestampSeconds = recvSecs;
packet.transmitTimestampFraction = transFract;
// Now transmit the response to the client.
packet.swapEndian();
timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
timeServerPort_.write(packet.packet(), NtpPacket::PACKET_SIZE);
timeServerPort_.endPacket();
processed = true;
}
return processed;
} }

View File

@ -129,6 +129,7 @@ const char kUBXTypes[] PROGMEM = "UBX";
#define UBX_SERIAL_BUFFER_SIZE 256 #define UBX_SERIAL_BUFFER_SIZE 256
#define UBX_TCP_PORT 1234 #define UBX_TCP_PORT 1234
#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds
/********************************************************************************************\ /********************************************************************************************\
| *globals | *globals
@ -251,7 +252,8 @@ struct UBX_t {
uint32_t last_vAcc; uint32_t last_vAcc;
uint8_t gpsFix; uint8_t gpsFix;
uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA
uint16_t log_interval; // in tenth of seconds uint16_t log_interval; // in tenth of seconds
int32_t timeOffset; // roughly computed offset millis() - iTOW
} state; } state;
struct { struct {
@ -260,6 +262,7 @@ struct UBX_t {
uint32_t send_when_new:1; // no teleinterval uint32_t send_when_new:1; // no teleinterval
uint32_t send_UI_only:1; uint32_t send_UI_only:1;
uint32_t runningNTP:1; uint32_t runningNTP:1;
// uint32_t blockedNTP:1;
uint32_t forceUTCupdate:1; uint32_t forceUTCupdate:1;
uint32_t runningVPort:1; uint32_t runningVPort:1;
// TODO: more to come // TODO: more to come
@ -322,6 +325,15 @@ void UBXinitCFG(void)
DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA"));
} }
void UBXsendCFGLine(uint8_t _line)
{
if (_line>sizeof(UBLOX_INIT)/16) return;
for (uint32_t i = 0; i < 16; i++) {
UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) );
}
DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line);
}
void UBXTriggerTele(void) void UBXTriggerTele(void)
{ {
mqtt_data[0] = '\0'; mqtt_data[0] = '\0';
@ -583,6 +595,8 @@ void UBXSelectMode(uint16_t mode)
break; break;
case 10: case 10:
UBX.mode.runningNTP = false; UBX.mode.runningNTP = false;
UBXsendCFGLine(10); //NAV-POSLLH on
UBXsendCFGLine(11); //NAV-STATUS on
break; break;
case 11: case 11:
UBX.mode.forceUTCupdate = true; UBX.mode.forceUTCupdate = true;
@ -604,7 +618,6 @@ void UBXSelectMode(uint16_t mode)
break; break;
default: default:
if (mode>1000 && mode <1066) { if (mode>1000 && mode <1066) {
// UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz
UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65
} }
break; break;
@ -629,13 +642,16 @@ bool UBXHandlePOSLLH()
UBX.rec_buffer.values.lon = UBX.Message.navPosllh.lon; UBX.rec_buffer.values.lon = UBX.Message.navPosllh.lon;
DEBUG_SENSOR_LOG(PSTR("UBX: lat/lon: %i / %i"), UBX.rec_buffer.values.lat, UBX.rec_buffer.values.lon); DEBUG_SENSOR_LOG(PSTR("UBX: lat/lon: %i / %i"), UBX.rec_buffer.values.lat, UBX.rec_buffer.values.lon);
DEBUG_SENSOR_LOG(PSTR("UBX: hAcc: %d"), UBX.Message.navPosllh.hAcc); DEBUG_SENSOR_LOG(PSTR("UBX: hAcc: %d"), UBX.Message.navPosllh.hAcc);
UBX.state.last_iTOW = UBX.Message.navPosllh.iTOW;
UBX.state.last_alt = UBX.Message.navPosllh.alt; UBX.state.last_alt = UBX.Message.navPosllh.alt;
UBX.state.last_vAcc = UBX.Message.navPosllh.vAcc; UBX.state.last_vAcc = UBX.Message.navPosllh.vAcc;
UBX.state.last_hAcc = UBX.Message.navPosllh.hAcc; UBX.state.last_hAcc = UBX.Message.navPosllh.hAcc;
if (UBX.mode.send_when_new) { if (UBX.mode.send_when_new) {
UBXTriggerTele(); UBXTriggerTele();
} }
if (UBX.mode.runningNTP){ // after receiving pos-data at least once -> go to pure NTP-mode
UBXsendCFGLine(7); //NAV-POSLLH off
UBXsendCFGLine(8); //NAV-STATUS off
}
return true; // new position return true; // new position
} else { } else {
DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data")); DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data"));
@ -657,9 +673,9 @@ void UBXHandleTIME()
{ {
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec);
if (UBX.Message.navTime.valid.UTC == 1) { if (UBX.Message.navTime.valid.UTC == 1) {
UBX.state.timeOffset = millis(); // iTOW%1000 should be 0 here, when NTP-server is enabled and in "pure mode"
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid")); DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid"));
if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate) { if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate || UBX.mode.runningNTP) {
AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
TIME_T gpsTime; TIME_T gpsTime;
gpsTime.year = UBX.Message.navTime.year - 1970; gpsTime.year = UBX.Message.navTime.year - 1970;
gpsTime.month = UBX.Message.navTime.month; gpsTime.month = UBX.Message.navTime.month;
@ -667,7 +683,11 @@ void UBXHandleTIME()
gpsTime.hour = UBX.Message.navTime.hour; gpsTime.hour = UBX.Message.navTime.hour;
gpsTime.minute = UBX.Message.navTime.min; gpsTime.minute = UBX.Message.navTime.min;
gpsTime.second = UBX.Message.navTime.sec; gpsTime.second = UBX.Message.navTime.sec;
Rtc.utc_time = MakeTime(gpsTime); UBX.rec_buffer.values.time = MakeTime(gpsTime);
if (UBX.mode.forceUTCupdate || Rtc.user_time_entry == false){
AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
Rtc.utc_time = UBX.rec_buffer.values.time;
}
Rtc.user_time_entry = true; Rtc.user_time_entry = true;
} }
} }
@ -705,7 +725,7 @@ void UBXLoop50msec(void)
} }
// handle NTP-server // handle NTP-server
if(UBX.mode.runningNTP){ if(UBX.mode.runningNTP){
timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000); timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET);
} }
} }