diff --git a/DS3231/ds3231_pb.py b/DS3231/ds3231_pb.py index f03d3cc..c98e43e 100644 --- a/DS3231/ds3231_pb.py +++ b/DS3231/ds3231_pb.py @@ -1,6 +1,7 @@ # Pyboard driver for DS3231 precison real time clock. # Adapted from WiPy driver at https://github.com/scudderfish/uDS3231 # Includes routine to calibrate the Pyboard's RTC from the DS3231 +# delta method now operates to 1mS precision # Adapted by Peter Hinch, Jan 2016 import utime, pyb @@ -24,9 +25,8 @@ def bcd2dec(bcd): return (((bcd & 0xf0) >> 4) * 10 + (bcd & 0x0f)) def dec2bcd(dec): - t = dec // 10 - o = dec - t * 10 - return (t << 4) + o + tens, units = divmod(dec, 10) + return (tens << 4) + units class DS3231: def __init__(self, side = 'X'): @@ -43,7 +43,7 @@ class DS3231: def get_time(self, set_rtc = False): if set_rtc: - data = self.await_transition() # For accuracy set RTC immediately after a seconds transition + data = self.await_transition() # For accuracy set RTC immediately after a seconds transition else: data = self.ds3231.mem_read(7, DS3231_I2C_ADDR, 0) # don't wait ss = bcd2dec(data[0]) @@ -80,38 +80,46 @@ class DS3231: self.ds3231.mem_write(dec2bcd(MM), DS3231_I2C_ADDR, 5) self.ds3231.mem_write(dec2bcd(YY-1900), DS3231_I2C_ADDR, 6) - def delta(self): - return utime.time() - utime.mktime(self.get_time()) # No. of secs RTC leads DS3231 + def delta(self): # Return no. of mS RTC leads DS3231 + self.await_transition() + rtc_time = now() + rtc_ms = rtc_time[0] * 1000 + rtc_time[1] + t_ds3231 = utime.mktime(self.get_time()) # To second precision, still in same sec as transition + return rtc_ms - 1000 * t_ds3231 - def await_transition(self): + def await_transition(self): # Wait until DS3231 seconds value changes data = self.ds3231.mem_read(7, DS3231_I2C_ADDR, 0) ss = data[0] while ss == data[0]: - data = self.ds3231.mem_read(7, DS3231_I2C_ADDR, 0) # Await a seconds transition + data = self.ds3231.mem_read(7, DS3231_I2C_ADDR, 0) return data # Get calibration factor for Pyboard RTC. Note that the DS3231 doesn't have millisecond resolution so we # wait for a seconds transition to emulate it. # This function returns the required calibration factor for the RTC (approximately the no. of ppm the # RTC lags the DS3231). -# For accurate results the delay should be at least 120 seconds. Longer is better. +# For accurate results the delay should be at least two minutes. Longer is better. # Note calibration factor is not saved on power down unless an RTC backup battery is used. An option is # to store the calibration factor on disk and issue rtc.calibration(factor) on boot. - def getcal(self, seconds): + def getcal(self, minutes=5): rtc.calibration(0) # Clear existing cal self.save_time() # Set DS3231 from RTC self.await_transition() rtcstart = now() dsstart = utime.mktime(self.get_time()) - pyb.delay(seconds * 1000) + pyb.delay(minutes * 60000) self.await_transition() rtcend = now() dsend = utime.mktime(self.get_time()) dsdelta = (dsend - dsstart) *1000 rtcdelta = rtcend[0] * 1000 + rtcend[1] - rtcstart[0] * 1000 - rtcstart[1] ppm = (1000000* (rtcdelta - dsdelta))/dsdelta - return -ppm/0.954 + return int(-ppm/0.954) - def calibrate(self, seconds): - rtc.calibration(self.getcal(seconds)) + def calibrate(self, minutes=5): + print('Waiting {} minutes to acquire calibration factor...'.format(minutes)) + cal = self.getcal(minutes) + rtc.calibration(cal) + print('Pyboard RTC is calibrated. Factor is {}.'.format(cal)) + return cal