Page 1 of 1

Interrupt phase shift - how to?

Posted: Sat Feb 23, 2019 9:23 am
by cyberman54
For controlling a wall clock i need a precise pulse-per-second signal. While this is usually done with a pps fed by GPS, i want to implement a fallback pps by using the precise 1Hz squarewave signal of an RTC chip (DS3231). So there is the need to synchronize the RTC pps with the last pps received by the GPS. The phase of the RTC squarewave signal cannot be set, so i need a software solution for this.

Hardware setup is:

- PPS by GPS is connected to GPIO and triggers a pps interrupt
- Squarewave output by RTC is connected to another GPIO and triggers the pps interrupt as fallback, if no signal comes from GPS

How can i sync the fallback pps on the GPS pps, while the GPS pps is present?

Re: Interrupt phase shift - how to?

Posted: Mon Feb 25, 2019 6:38 pm
by idahowalker
You can get uSec resolution from the hardware timer and using a semaphore to sync the 1pps from the GPS with the hardware timer set up as a watchdog.

The ESP has a nano second clock you can use: https://www.instructables.com/id/625-Na ... icrocontr/, which works for the ESP32 as well.

Re: Interrupt phase shift - how to?

Posted: Thu Feb 28, 2019 8:58 pm
by cyberman54
idahowalker wrote:
Mon Feb 25, 2019 6:38 pm
You can get uSec resolution from the hardware timer and using a semaphore to sync the 1pps from the GPS with the hardware timer set up as a watchdog.
Thanks for the hints. My current code https://github.com/cyberman54/ESP32-Pax ... keeper.cpp feeds the GPS PPS in an interrupt which fires a semaphore to a routine which controls the clock. But how could i sync with a second fallback PPS from the RTC DS3231 chip? Both, GPS and RTC, are programmed to give 1 pulse per second. I am wondering how i can use the more precise PPS from GPS to dynamically (re-)calculate the phase shift / drift of the RTC pps, and then set the timeofday by time of RTC, regarding the phase shift.

Could this, maybe, done with hardware timers of ESP32? Or a routine in the ULP?

Re: Interrupt phase shift - how to?

Posted: Thu Feb 28, 2019 9:52 pm
by idahowalker
I figure your not going to get control of the ESP32 PLL to cause it to phase shift as per your desire.

The ESP32 has a built in RTC (real time clock), why not use the GPS clock to set the ESP32 clock? Once the ESP32 clock is set, measure the offset between the two clocks and update the ESP32's clock, including the offset your code finds. This can be done on a periodic basis and can be made into a fine tuning routine that just runs as a task.

Re: Interrupt phase shift - how to?

Posted: Fri Mar 01, 2019 3:55 pm
by cyberman54
Thanks again for the hints.
The concept of using a hardware watchdog timer in conjunction with the pps pulse sounds reasonable. I thought on it, but it is not yet fully clear to me what the role of the watchdog should be: should it be fed by the pps pulse? How can i synchronize the time of RTC this way?

Could you, please, explain your idea some further? Tx.

Re: Interrupt phase shift - how to?

Posted: Fri Mar 01, 2019 9:51 pm
by idahowalker
No need for a watchdog if the ESP32 internal RTC is used. Set the internal RTC to the GPS time, allow the internal RTC to run and keep track of the drift, periodic set the internal RCT to the to the GPS time and refine the drift, over time the drift can be used as an offset calibration for the ESP32

Re: Interrupt phase shift - how to?

Posted: Sat Jan 29, 2022 10:05 am
by dizcza
idahowalker wrote:
Fri Mar 01, 2019 9:51 pm
over time the drift can be used as an offset calibration for the ESP32
Apologies for bringing an old thread back, I'm curious: how an internal HW timer in ESP32 boards can be calibrated - do you mean adding the estimated time drift every elapsed minute or an hour? Something like

Code: Select all

#define DRIFT_MINUTE_US 15

tick = timer_get_tick();
tick += DRIFT_MINUTE_US
Or do you mean actually changing the timer AGEOFFSET register, if there is any, as it's in DS3231?

------

Update.

I think what was really meant is the

Code: Select all

/**
 * @brief Update the calibration value of RTC slow clock
 *
 * The value has to be in the same format as returned by rtc_clk_cal (microseconds,
 * in Q13.19 fixed-point format).
 * This value is used by timekeeping functions (such as gettimeofday) to
 * calculate current time based on RTC counter value.
 * @param value calibration value obtained using rtc_clk_cal
 */
void esp_clk_slowclk_cal_set(uint32_t value);
function defined in the "esp_clk.h". How precisely an internal RTC can be tuned with this function? Has anyone used it?

Re: Interrupt phase shift - how to?

Posted: Sun Jan 30, 2022 10:42 am
by pataga
Maybe i misunderstood what you are trying to do, but I would use the 32kHz square wave output from the DS3231.

You could keep a counter running at 32kHz interrupt on the ESP32 that is reset by the GPS pps signal.
If it goes above the 32kHz count => gps pps signal is lost, reset counter and fire the wall clock from the 32kHz interrupt.

Re: Interrupt phase shift - how to?

Posted: Tue Feb 01, 2022 7:31 am
by dizcza
pataga wrote:
Sun Jan 30, 2022 10:42 am
Maybe i misunderstood what you are trying to do
I was asking about how one could tune an internal RTC of ESP32 boards and then about the precision of this internal RTC standalone, once it's calibrated, without any external components - GPS, external RTCs like DS3231...
pataga wrote:
Sun Jan 30, 2022 10:42 am
You could keep a counter running at 32kHz interrupt on the ESP32...
Do you mean incrementing a counter variable inside a GPIO interrupts handler? I doubt that the GPIO substem of ESP32 could handle interrupts with such a high frequency without some interrupts getting lost. Especially in a typical scenario when other tasks, notably including WiFi/Bluetooth, are running aside, even when placed on a second core.