IF482 precision improvement
This commit is contained in:
parent
87378738d2
commit
035b7abe26
@ -23,6 +23,6 @@ float get_rtctemp(void);
|
|||||||
void IRAM_ATTR CLOCKIRQ();
|
void IRAM_ATTR CLOCKIRQ();
|
||||||
int timepulse_init(uint32_t pps_freq);
|
int timepulse_init(uint32_t pps_freq);
|
||||||
void timepulse_start();
|
void timepulse_start();
|
||||||
uint8_t sync_clock(time_t t);
|
time_t sync_clock(time_t t);
|
||||||
|
|
||||||
#endif // _RTCTIME_H
|
#endif // _RTCTIME_H
|
@ -88,10 +88,11 @@ time_t tmConvert_t(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh,
|
|||||||
|
|
||||||
// function to fetch current time from gps
|
// function to fetch current time from gps
|
||||||
time_t get_gpstime(void) {
|
time_t get_gpstime(void) {
|
||||||
// never call now() in this function, this would cause a recursion!
|
// never call now() in this function, this would break this function
|
||||||
|
// to use as SyncProvider due to recursive call to now()
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
if ((gps.time.age() < 1500) && (gps.time.isValid())) {
|
if ((gps.time.age() < 1500) && (gps.time.isValid())) {
|
||||||
t = tmConvert_t(gps.date.year(), gps.date.month(), gps.date.day(),
|
t = 1 + tmConvert_t(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());
|
||||||
ESP_LOGD(TAG, "GPS time: %4d/%02d/%02d %02d:%02d:%02d", year(t), month(t),
|
ESP_LOGD(TAG, "GPS time: %4d/%02d/%02d %02d:%02d:%02d", year(t), month(t),
|
||||||
day(t), hour(t), minute(t), second(t));
|
day(t), hour(t), minute(t), second(t));
|
||||||
|
@ -115,19 +115,19 @@ int if482_init(void) {
|
|||||||
"if482loop", // name of task
|
"if482loop", // name of task
|
||||||
2048, // stack size of task
|
2048, // stack size of task
|
||||||
(void *)1, // parameter of the task
|
(void *)1, // parameter of the task
|
||||||
3, // priority of the task
|
4, // priority of the task
|
||||||
&ClockTask, // task handle
|
&ClockTask, // task handle
|
||||||
0); // CPU core
|
0); // CPU core
|
||||||
|
|
||||||
assert(ClockTask); // has clock task started?
|
assert(ClockTask); // has clock task started?
|
||||||
timepulse_start(); // start pulse
|
// timepulse_start(); // start pulse
|
||||||
|
|
||||||
return 1; // success
|
return 1; // success
|
||||||
} // if482_init
|
} // if482_init
|
||||||
|
|
||||||
String IF482_Out(time_t tt) {
|
String IF482_Out(time_t tt) {
|
||||||
|
|
||||||
time_t t = myTZ.toLocal(tt);
|
time_t t = 1 + myTZ.toLocal(tt);
|
||||||
char mon, buf[14], out[IF482_FRAME_SIZE];
|
char mon, buf[14], out[IF482_FRAME_SIZE];
|
||||||
|
|
||||||
switch (timeStatus()) { // indicates if time has been set and recently synced
|
switch (timeStatus()) { // indicates if time has been set and recently synced
|
||||||
@ -159,18 +159,32 @@ void if482_loop(void *pvParameters) {
|
|||||||
|
|
||||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||||
|
|
||||||
|
time_t tOut;
|
||||||
TickType_t wakeTime;
|
TickType_t wakeTime;
|
||||||
const TickType_t timeOffset =
|
const TickType_t tTx = tx_time(HAS_IF482); // duration of telegram transmit
|
||||||
tx_time(HAS_IF482); // duration of telegram transmit
|
|
||||||
const TickType_t startTime = xTaskGetTickCount(); // now
|
|
||||||
|
|
||||||
sync_clock(now()); // wait until begin of a new second
|
|
||||||
BitsPending = true; // start blink in display
|
BitsPending = true; // start blink in display
|
||||||
|
|
||||||
// take timestamp at moment of start of new second
|
// phase 1: sync task on top of second
|
||||||
const TickType_t shotTime = xTaskGetTickCount() - startTime - timeOffset;
|
|
||||||
|
|
||||||
// task remains in blocked state until it is notified by isr
|
sync_clock(now());
|
||||||
|
|
||||||
|
const TickType_t t0 = xTaskGetTickCount(); // moment of start top of second
|
||||||
|
|
||||||
|
timepulse_start(); // start timepulse
|
||||||
|
|
||||||
|
xTaskNotifyWait(
|
||||||
|
0x00, // don't clear any bits on entry
|
||||||
|
ULONG_MAX, // clear all bits on exit
|
||||||
|
&wakeTime, // receives moment of call from isr
|
||||||
|
portMAX_DELAY); // wait forever (missing error handling here...)
|
||||||
|
|
||||||
|
const TickType_t tOffset = wakeTime - t0;
|
||||||
|
const TickType_t tShot =
|
||||||
|
(tOffset < tTx) ? (1000 - tOffset - tTx) : (tOffset - tTx);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "IF482 signal synced with precision %dms", 1000 - tOffset);
|
||||||
|
|
||||||
|
// phase 2: sync task on time pulse interrupt
|
||||||
for (;;) {
|
for (;;) {
|
||||||
xTaskNotifyWait(
|
xTaskNotifyWait(
|
||||||
0x00, // don't clear any bits on entry
|
0x00, // don't clear any bits on entry
|
||||||
@ -178,22 +192,25 @@ void if482_loop(void *pvParameters) {
|
|||||||
&wakeTime, // receives moment of call from isr
|
&wakeTime, // receives moment of call from isr
|
||||||
portMAX_DELAY); // wait forever (missing error handling here...)
|
portMAX_DELAY); // wait forever (missing error handling here...)
|
||||||
|
|
||||||
|
tOut = now() + 1; // next second after waketime
|
||||||
|
|
||||||
// select clock scale
|
// select clock scale
|
||||||
#if (PPS == IF482_PULSE_DURATION) // we don't need clock rescaling
|
#if (PPS == IF482_PULSE_DURATION) // we don't need clock rescaling
|
||||||
// wait until it's time to start transmit telegram for next second
|
// wait until it's time to start transmit telegram for next second
|
||||||
vTaskDelayUntil(&wakeTime, shotTime); // sets waketime to moment of shot
|
vTaskDelayUntil(&wakeTime, tShot); // sets waketime to moment of tShot
|
||||||
IF482.print(IF482_Out(now() + 1));
|
IF482.print(IF482_Out(tOut));
|
||||||
|
|
||||||
#elif (PPS > IF482_PULSE_DURATION) // we need upclocking
|
#elif (PPS > IF482_PULSE_DURATION) // we need upclocking
|
||||||
for (uint8_t i = 1; i <= PPS / IF482_PULSE_DURATION; i++) {
|
for (uint8_t i = 1; i <= PPS / IF482_PULSE_DURATION; i++) {
|
||||||
vTaskDelayUntil(&wakeTime, shotTime); // sets waketime to moment of shot
|
vTaskDelayUntil(&wakeTime, tShot); // sets waketime to moment of shot
|
||||||
IF482.print(IF482_Out(now() + 1));
|
IF482.print(IF482_Out(tOut));
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif (PPS < IF482_PULSE_DURATION) // we need downclocking, not yet implemented
|
#elif (PPS < IF482_PULSE_DURATION) // we need downclocking, not yet implemented
|
||||||
#error Timepulse is too low for IF482!
|
#error Timepulse is too low for IF482!
|
||||||
#endif
|
#endif
|
||||||
}
|
} // forever
|
||||||
|
|
||||||
} // if482_loop()
|
} // if482_loop()
|
||||||
|
|
||||||
// helper function to calculate IF482 telegram serial tx time from serial
|
// helper function to calculate IF482 telegram serial tx time from serial
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "rtctime.h"
|
#include "rtctime.h"
|
||||||
|
|
||||||
|
#define I2C_DELAY (12) // 12ms is i2c delay when saving time to RTC chip
|
||||||
|
|
||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
@ -60,10 +62,12 @@ error:
|
|||||||
|
|
||||||
} // rtc_init()
|
} // rtc_init()
|
||||||
|
|
||||||
int set_rtctime(time_t t) { // t is epoch time starting 1.1.1970
|
int set_rtctime(time_t t) { // t is seconds epoch time starting 1.1.1970
|
||||||
if (I2C_MUTEX_LOCK()) {
|
if (I2C_MUTEX_LOCK()) {
|
||||||
Rtc.SetDateTime(RtcDateTime(t));
|
time_t tt = sync_clock(t); // wait for top of second
|
||||||
|
Rtc.SetDateTime(RtcDateTime(tt));
|
||||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||||
|
ESP_LOGI(TAG, "RTC calibrated");
|
||||||
return 1; // success
|
return 1; // success
|
||||||
}
|
}
|
||||||
return 0; // failure
|
return 0; // failure
|
||||||
@ -176,15 +180,11 @@ void timepulse_start() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function to sync phase of DCF output signal to start of second t
|
// helper function to sync time_t of top of next second
|
||||||
uint8_t sync_clock(time_t t) {
|
time_t sync_clock(time_t t) {
|
||||||
time_t tt = t;
|
while (millis() % 1000)
|
||||||
// delay until start of next second
|
; // wait for milli seconds to be zero before setting new time
|
||||||
do {
|
return (now());
|
||||||
tt = now();
|
|
||||||
} while (t == tt);
|
|
||||||
ESP_LOGI(TAG, "Sync on Sec %d", second(tt));
|
|
||||||
return second(tt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// interrupt service routine triggered by either rtc pps or esp32 hardware
|
// interrupt service routine triggered by either rtc pps or esp32 hardware
|
||||||
|
Loading…
Reference in New Issue
Block a user