Adding adjtime() method to utime
Posted: Mon Dec 16, 2019 5:02 pm
The esp-idf used for the esp32 has a function adjtime(3) that can be used to gradually apply a correction value to the system clock. This keeps the clock monotonic (moving forward at all times) while the correction happens.
I was not able to find an equivalent function for the esp8266, so this is esp32 specific and therefore belongs into ports/esp32.
Since utime.localtime() is based on gettimeofday(3) declared in the same header as adjtime(3) (sys/time.h), I think it is appropriate to add it to ports/esp32/modutime.c.
This branch has the implementation. Here is the diff.
This function is a fundamental building block of an effort to provide DS3231, NEO-6M (gps module) and NTP based time synchronization. So it would be good to get this into the next official release. The other parts can probably all be built as pure Python modules based on uasyncio.
I tested it by syncing an esp32 every 10 seconds in a uasyncio based task to the time provided by a DS3231. The result is that (on this particular specimen) the clock on average is running ahead by about 37us per second, then is slewed back by 370us over the course of about 24ms. I didn't find a good way to actually adjust the speed of the clock more permanently. The only way seems to be to switch to the internal 150kHz oscillator and use the esp_clk_slowclk_cal_set() function. But that oscillator is so inaccurate and jumpy that it is almost useless. This sort of saw tooth pattern is certainly much better.
Another task running every 1000 milliseconds produced a square wave. Comparing the two square waves on the oscilloscope there is the occasional +/- 1ms jitter in the Python generated square wave, which is entirely expected. But the two square waves don't drift any more, and that was the goal for this test.
@pythoncoder: I did take a look at your DS3231 driver. Borrowed the bcd2dec and dec2bcd stuff from it. But I ended up writing my own that is using the PPS signal from the DS3231 to get the beginning of a second at microsecond precision. I might end up offering both methods, in case someone doesn't want to or cannot connect the SQW pin. Then the change of second is the only way to sync by. Anyhow, it is WIP and will be published when ready.
Comments and questions please.
Regards, Jan
I was not able to find an equivalent function for the esp8266, so this is esp32 specific and therefore belongs into ports/esp32.
Since utime.localtime() is based on gettimeofday(3) declared in the same header as adjtime(3) (sys/time.h), I think it is appropriate to add it to ports/esp32/modutime.c.
This branch has the implementation. Here is the diff.
This function is a fundamental building block of an effort to provide DS3231, NEO-6M (gps module) and NTP based time synchronization. So it would be good to get this into the next official release. The other parts can probably all be built as pure Python modules based on uasyncio.
I tested it by syncing an esp32 every 10 seconds in a uasyncio based task to the time provided by a DS3231. The result is that (on this particular specimen) the clock on average is running ahead by about 37us per second, then is slewed back by 370us over the course of about 24ms. I didn't find a good way to actually adjust the speed of the clock more permanently. The only way seems to be to switch to the internal 150kHz oscillator and use the esp_clk_slowclk_cal_set() function. But that oscillator is so inaccurate and jumpy that it is almost useless. This sort of saw tooth pattern is certainly much better.
Another task running every 1000 milliseconds produced a square wave. Comparing the two square waves on the oscilloscope there is the occasional +/- 1ms jitter in the Python generated square wave, which is entirely expected. But the two square waves don't drift any more, and that was the goal for this test.
@pythoncoder: I did take a look at your DS3231 driver. Borrowed the bcd2dec and dec2bcd stuff from it. But I ended up writing my own that is using the PPS signal from the DS3231 to get the beginning of a second at microsecond precision. I might end up offering both methods, in case someone doesn't want to or cannot connect the SQW pin. Then the change of second is the only way to sync by. Anyhow, it is WIP and will be published when ready.
Comments and questions please.
Regards, Jan