Last active
February 23, 2023 19:22
-
-
Save anecdata/1b09c992df194b9fa6033ad58c6e1e49 to your computer and use it in GitHub Desktop.
NTP: manual or automatic (for CircuitPython ports with native wifi) & alternative(s)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import rtc | |
import wifi | |
import socketpool | |
import adafruit_ntp | |
from secrets import secrets | |
pool = socketpool.SocketPool(wifi.radio) | |
ntp = adafruit_ntp.NTP(pool, tz_offset=0) | |
wifi.radio.connect(secrets["ssid"], secrets["password"]) | |
# manual - sync ntp to the internal rtc when it needs adjustment | |
rtci = rtc.RTC() | |
rtci.datetime = ntp.datetime | |
print(time.localtime()) | |
# automatic - use ntp as the source for all time calls | |
rtc.set_time_source(ntp) | |
print(time.localtime()) |
An alternative process for sub-second timestamps could be:
import time
import rtc
import random
# track rtc timestamps with monotonic (but not accurate) fractional seconds)
# rtc can be fed from any source of struct_time
current_s = 0
current_monotonic_ns = time.monotonic_ns()
while True:
event = True # some loggable activity happens
if event:
rtc_s = time.mktime(rtc.RTC().datetime)
if rtc_s != current_s:
print()
current_s = rtc_s
current_monotonic_ns = time.monotonic_ns()
new_s_indicator = "*"
else:
new_s_indicator = "-"
interval_ns = time.monotonic_ns() - current_monotonic_ns
bodged_float_str = f"{rtc_s}" + "." + f"{(interval_ns / 1_000_000_000):0.3f}".split("0.")[-1]
print(f"{new_s_indicator} {rtc_s} {bodged_float_str: 18}") # , end="\r")
time.sleep(random.random()) # simulate random event intervals
The fractional seconds are not accurate relative to real clock time, but the intervals between are reasonably accurate. The fractional seconds are strictly monotonic, so preserve the sequence of timestamps.
Sample output:
* 1664226131 1664226131.000
- 1664226131 1664226131.157
* 1664226132 1664226132.000
- 1664226132 1664226132.062
- 1664226132 1664226132.669
* 1664226133 1664226133.000
- 1664226133 1664226133.100
- 1664226133 1664226133.110
- 1664226133 1664226133.639
* 1664226134 1664226134.000
* 1664226135 1664226135.000
- 1664226135 1664226135.162
- 1664226135 1664226135.400
* 1664226136 1664226136.000
* 1664226137 1664226137.000
- 1664226137 1664226137.512
* 1664226138 1664226138.000
- 1664226138 1664226138.549
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's unfortunate that
datetime
means two different things in different libraries.In the
datetime
library,class datetime.datetime
has year, month, day, hour, minute, second, microsecond, and tzinfo.But
ntp.datetime
andrtc.datetime
and the.datetime
property of the libraries for the extertnal RTC modules return astruct_time
with some subset of year, month, mday, hour, min, sec, wday, yday, isdst, zone, and gmtoff (no fractional seconds).The NTP protocol, used by the
adafruit_NTP
library, potentially has extremely precise fractional seconds, but the library currently ignores the fractional part. The fraction can be obtained using:or
The latter gives enough precision for rough milliseconds, which is probably more than enough precision given the accuracy of NTP in a networked CircuitPython environment. It could be exposed with an additional property.