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(); TickType_t startTime = xTaskGetTickCount();
uint8_t sec = second(t); uint8_t sec = second(t);
ESP_LOGD (TAG, "DCF second %d", sec);
// induce 10 pulses // induce 10 pulses
for (uint8_t pulse = 0; pulse <= 9; pulse++) { for (uint8_t pulse = 0; pulse <= 9; pulse++) {

View File

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

View File

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

View File

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