Open DJDevon3 opened 2 years ago
Neradoc came up with a fix that includes a timezone variable. Sets the RTC and can offset easily with a timezone variable. This is much easier to hit the ground running at least with a GPS featherwing. Can confirm this code works great. To change DST all you have to do is change the timezone variable either manually (or append a DST script).
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# Simple script using GPS timestamps as RTC time source
# The GPS timestamps are available without a fix and keep the track of
# time while there is powersource (ie coin cell battery)
import time
import board
import busio
import rtc
import adafruit_gps
TIMEZONE = -4
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
# i2c = busio.I2C(board.SCL, board.SDA)
gps = adafruit_gps.GPS(uart, debug=False)
# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
gps.send_command(b"PMTK220,1000")
the_rtc = rtc.RTC()
def _format_datetime(datetime):
return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format(
datetime.tm_mon,
datetime.tm_mday,
datetime.tm_year,
datetime.tm_hour,
datetime.tm_min,
datetime.tm_sec,
)
had_a_fix = False
last_print = time.monotonic()
while True:
gps.update()
if gps.timestamp_utc and not had_a_fix:
print("Setting the time")
the_rtc.datetime = gps.datetime
the_rtc.datetime = time.localtime(time.time() + TIMEZONE * 3600)
had_a_fix = True
# Every second print out current time from GPS, RTC and time.localtime()
current = time.monotonic()
if current - last_print >= 1.0:
last_print = current
if not gps.timestamp_utc:
print("Connecting to GPS...")
continue
print("==========================")
# Time & date from GPS informations
print("GPS timestamp: {}".format(_format_datetime(gps.timestamp_utc)))
# Time & date from internal RTC
print("RTC timestamp: {}".format(_format_datetime(the_rtc.datetime)))
# Time & date from time.localtime() function
print("Local time: {}".format(_format_datetime(time.localtime())))
time.sleep(10)
I think the basic issue might be with using the GPS as a time source for the RTC. I don't know all the inner workings, but it looks like doing that causes the time functions to return time based on gps.datetime
. But that value is apparently only updated when the GPS gets a timestamp from the satellites (when receiving a GLL type "sentence").
import time
import board
import busio
import rtc
import adafruit_gps
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
gps = adafruit_gps.GPS(uart, debug=False)
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
gps.send_command(b"PMTK220,1000")
rtc.set_time_source(gps)
while not gps.timestamp_utc: gps.update()
print(time.time())
time.sleep(5)
print(time.time())
Result, which is quite unexpected when using the time
module.
code.py output:
2271171509
2271171509
So, a better use of it is to not use set_time_source
but instead use the local RTC and update the time reference when we get one (maybe not every time either, like we do with NTP to sync only every now and then). Even then there is no telling when the timestamp was received if the code spends a long time between reads of the uart buffer though.
Maybe clarify what the "time source" example is supposed to do ?
https://github.com/adafruit/Adafruit_CircuitPython_GPS/blob/583fbd01ef7a85859f8bde51a8e83a0c86fe52c0/examples/gps_simpletest.py#L74
Fix Timestamp isn't working for me. Always remains the same timestamp. Using this example with Ultimate GPS Featherwing on nrf52840 board on UART. Didn't change anything in the example, just ran it, everything else seems to work fine.
rtc.set_time_source(gps) doesn't seem to work correctly on the featherwing or at least it doesn't set the correct date. the current code seems to be a mashup of Fix + RTC to produce a UTC timestamp and still lacks timezone and DST offset capability. not as user friendly as it could be to hit the ground running with the gps featherwing.
The Fix timestamp time loads once and never updates. RTC timestamp is only initializing the date, not updated with GPS, fixed at 01/02/2000 (set at line 428 in adafruit_gps.py)
The code is cobbled together oddly and doesn't account for DST or timezone. Here's some code I worked on that does work in properly setting the GPS Featherwing RTC date & time.
Because struct_time is hooked into monotonic the RTC set begins when you save the file, not when code is executed in the script. It's a much better way to ensure the RTC time you want set is actually set when you hit ctrl+s. It then gets updated when it connects to GPS so the time keeping from file save to GPS handoff is seamless.
struct_time should be updated to keep the RTC as accurate as possible. Drift will occur but can be minimized from a lost power event by having GPS constantly updating and resetting struct_time.
RTC timestamp is now properly initialized and keeping time. That should be enough to start on whipping up an example that includes a DST and timezone offset.
_update_timestamp_utc on line 414 in adafruit_gps.py needs work, i don't think it's working like it should.