timekeeper fixes (experimental)

This commit is contained in:
Klaus K Wilting 2019-02-27 22:40:58 +01:00
parent b2a563c84e
commit c489123e06
4 changed files with 45 additions and 49 deletions

View File

@ -22,6 +22,8 @@ void DCF77_Pulse(time_t t, uint8_t const *DCFpulse) {
TickType_t startTime = xTaskGetTickCount();
uint8_t sec = second(t);
ESP_LOGD (TAG, "DCF second %d", sec);
// induce 10 pulses
for (uint8_t pulse = 0; pulse <= 9; pulse++) {

View File

@ -92,14 +92,14 @@ time_t get_gpstime(void) {
time_t t = 0;
if ((gps.time.age() < gpsDelay_ms) && (gps.time.isValid())) {
if ((gps.time.age() < gpsDelay_ms) && (gps.time.isValid()) && (gps.date.isValid())) {
ESP_LOGD(TAG, "GPS time age: %dms, is valid: %s", gps.time.age(),
gps.time.isValid() ? "yes" : "no");
ESP_LOGD(TAG, "GPS time age: %dms, second: %d, is valid: %s", gps.time.age(), gps.time.second(),
gps.time.isValid() ? "yes" : "no");
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
gps.time.hour(), gps.time.minute(), gps.time.second());
}
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
gps.time.hour(), gps.time.minute(), gps.time.second());
}
return TimeIsValid(t);
} // get_gpstime()

View File

@ -27,11 +27,11 @@ Uused tasks and timers:
Task Core Prio Purpose
====================================================================================
clockloop 0 4 generates realtime telegrams for external clock
ledloop 0 3 blinks LEDs
spiloop 0 2 reads/writes data on spi interface
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
clockloop 1 4 generates realtime telegrams for external clock
looptask 1 1 arduino core -> runs the LMIC LoRa stack
irqhandler 1 1 executes tasks triggered by hw irq, see table below
gpsloop 1 2 reads data from GPS via serial or i2c
@ -362,7 +362,6 @@ void setup() {
ESP_LOGI(TAG, "Starting Timekeeper...");
assert(timepulse_init()); // setup timepulse
timepulse_start();
timeSync();
// start wifi in monitor mode and start channel rotation timer
ESP_LOGI(TAG, "Starting Wifi...");
@ -417,6 +416,7 @@ void setup() {
#if defined HAS_IF482 || defined HAS_DCF77
ESP_LOGI(TAG, "Starting Clock Controller...");
timeSync();
clock_init();
#endif

View File

@ -8,7 +8,6 @@ const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
getExternalTime TimeSourcePtr; // pointer to time source function
// syncs systime from external time source and sets/reads RTC, called by
// cyclic.cpp
void timeSync(void) {
@ -16,47 +15,36 @@ void timeSync(void) {
time_t t = 0;
#ifdef HAS_GPS
// do we have a valid GPS time?
if (get_gpstime()) { // then let's sync GPS time on top of second
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
vTaskDelay(gpsDelay_ticks);
t = get_gpstime(); // fetch time from recent NEMA record
if (t) {
t++; // gps time concerns past second, so we add one
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
setTime(t);
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1100)); // wait for pps
t = get_gpstime(); // fetch recent time from last NEMA record
if (t) {
/ t++; // last NMEA record concerns past second, so we add one
ESP_LOGD(TAG, "millis: %d, second: %d", millis(), second(t));
setTime(t);
#ifdef HAS_RTC
set_rtctime(t); // calibrate RTC
set_rtctime(t); // calibrate RTC
#endif
timeSource = _gps;
goto exit;
}
}
timeSource = _gps;
return;
}
#endif
// no GPS -> fallback to RTC time while trying lora sync
#ifdef HAS_RTC
t = get_rtctime();
if (t) {
setTime(t);
timeSource = _rtc;
} else
ESP_LOGW(TAG, "no confident RTC time");
t = get_rtctime();
if (t) {
setTime(t);
timeSource = _rtc;
}
#endif
// try lora sync if we have
#if defined HAS_LORA && defined TIME_SYNC_LORA
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
#endif
exit:
if (t)
ESP_LOGD(TAG, "Time was set by %c to %02d:%02d:%02d",
timeSetSymbols[timeSource], hour(t), minute(t), second(t));
else
timeSource = _unsynced;
if (!t)
timeSource = _unsynced;
} // timeSync()
@ -66,7 +54,7 @@ uint8_t timepulse_init() {
// use time pulse from GPS as time base with fixed 1Hz frequency
#ifdef GPS_INT
// setup external interupt pin for GPS INT output
// setup external interupt pin for rising edge GPS INT
pinMode(GPS_INT, INPUT_PULLDOWN);
// setup external rtc 1Hz clock as pulse per second clock
ESP_LOGI(TAG, "Timepulse: external (GPS)");
@ -75,7 +63,7 @@ uint8_t timepulse_init() {
// use pulse from on board RTC chip as time base with fixed frequency
#elif defined RTC_INT
// setup external interupt pin for active low RTC INT output
// setup external interupt pin for falling edge RTC INT
pinMode(RTC_INT, INPUT_PULLUP);
// setup external rtc 1Hz clock as pulse per second clock
@ -114,12 +102,15 @@ void timepulse_start(void) {
// interrupt service routine triggered by either pps or esp32 hardware timer
void IRAM_ATTR CLOCKIRQ(void) {
if (ClockTask != NULL)
xTaskNotifyFromISR(ClockTask, xTaskGetTickCountFromISR(), eSetBits, NULL);
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits, NULL);
#if defined GPS_INT || defined RTC_INT
xSemaphoreGiveFromISR(TimePulse, NULL);
xSemaphoreGiveFromISR(TimePulse, &xHigherPriorityTaskWoken);
TimePulseTick = !TimePulseTick; // flip ticker
#endif
portYIELD_FROM_ISR();
}
@ -181,7 +172,7 @@ void clock_init(void) {
(void *)1, // task parameter
4, // priority of the task
&ClockTask, // task handle
0); // CPU core
1); // CPU core
assert(ClockTask); // has clock task started?
} // clock_init
@ -191,10 +182,11 @@ void clock_loop(void *pvParameters) { // ClockTask
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
TickType_t wakeTime;
uint32_t ppstime;
time_t t;
#define t1(t) (t + DCF77_FRAME_SIZE + 1) // future time for next DCF77 frame
#define t2(t) (t + 1) // future time for sync with 1pps trigger
#define t1(t) (t + DCF77_FRAME_SIZE + 1) // future minute for next DCF77 frame
#define t2(t) (t + 1) // future second after sync with 1pps trigger
// preload first DCF frame before start
#ifdef HAS_DCF77
@ -204,14 +196,14 @@ void clock_loop(void *pvParameters) { // ClockTask
// output time telegram for second following sec beginning with timepulse
for (;;) {
xTaskNotifyWait(0x00, ULONG_MAX, &wakeTime,
xTaskNotifyWait(0x00, ULONG_MAX, &ppstime,
portMAX_DELAY); // wait for timepulse
// no confident time -> suppress clock output
if (timeStatus() == timeNotSet)
continue;
t = now(); // payload to send to clock
t = time_t(ppstime);
#if defined HAS_IF482
@ -222,8 +214,10 @@ void clock_loop(void *pvParameters) { // ClockTask
if (second(t) == DCF77_FRAME_SIZE - 1) // is it time to load new frame?
DCFpulse = DCF77_Frame(t1(t)); // generate next frame
if (DCFpulse[DCF77_FRAME_SIZE] ==
minute(t1(t))) // have recent frame? (pulses could be missed!)
if (DCFpulse[DCF77_FRAME_SIZE] !=
minute(t1(t))) // have recent frame? (timepulses could be missed!)
continue;
else
DCF77_Pulse(t2(t), DCFpulse); // then output next second of this frame
#endif