From 95844ac5fb866b911949288ff5f71e2e50f501f0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 16 Jul 2020 08:27:05 -0500 Subject: [PATCH 1/3] DS3231: Add calibration, temperature, and force_conversion This device has a temperature sensor with 0.25C precision, and an "aging offset" which can be used to calibrate the crystal frequency for increased timekeeping accuracy. Expose these as properties. This requires https://github.com/adafruit/Adafruit_CircuitPython_Register/pull/39 as the temperature and calibration registers hold signed values. --- adafruit_ds3231.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/adafruit_ds3231.py b/adafruit_ds3231.py index 97d9788..a9cefb9 100644 --- a/adafruit_ds3231.py +++ b/adafruit_ds3231.py @@ -56,6 +56,7 @@ """ from adafruit_bus_device.i2c_device import I2CDevice from adafruit_register import i2c_bit +from adafruit_register import i2c_bits from adafruit_register import i2c_bcd_alarm from adafruit_register import i2c_bcd_datetime @@ -93,6 +94,15 @@ class DS3231: alarm2_status = i2c_bit.RWBit(0x0F, 1) """True if alarm2 is alarming. Set to False to reset.""" + _calibration = i2c_bits.RWBits(8, 0x10, 0, 8, signed=True) + + _temperature = i2c_bits.RWBits( + 10, 0x11, 6, register_width=2, lsb_first=False, signed=True + ) + + _busy = i2c_bit.ROBit(0x0F, 2) + _conv = i2c_bit.RWBit(0x0E, 5) + def __init__(self, i2c): self.i2c_device = I2CDevice(i2c, 0x68) @@ -107,3 +117,27 @@ def datetime(self, value): self.datetime_register = value self.disable_oscillator = False self.lost_power = False + + @property + def temperature(self): + """Returns the last temperature measurement. Temperature is updated only every 64 seconds, or when a conversion is forced.""" + return self._temperature / 4 + + def force_conversion(self): + """Forces a conversion and returns the new temperature""" + while self._busy: + pass + self._conv = True + while self._busy: + pass + return self.temperature + + @property + def calibration(self): + """Calibration values range from -128 to 127; each step is approximately 0.1ppm, and positive values decrease the frequency (increase the period). When set, a temperature conversion is forced so the result of calibration can be seen directly at the 32kHz pin after the next temperature conversion.""" + return self._calibration + + @calibration.setter + def calibration(self, value): + self._calibration = value + self.force_conversion() From 069c9c7e4af16f33137515676b1c429be916789c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 16 Jul 2020 13:27:33 -0500 Subject: [PATCH 2/3] pylint --- adafruit_ds3231.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/adafruit_ds3231.py b/adafruit_ds3231.py index a9cefb9..c757ac1 100644 --- a/adafruit_ds3231.py +++ b/adafruit_ds3231.py @@ -120,7 +120,8 @@ def datetime(self, value): @property def temperature(self): - """Returns the last temperature measurement. Temperature is updated only every 64 seconds, or when a conversion is forced.""" + """Returns the last temperature measurement. Temperature is updated + only every 64 seconds, or when a conversion is forced.""" return self._temperature / 4 def force_conversion(self): @@ -134,7 +135,11 @@ def force_conversion(self): @property def calibration(self): - """Calibration values range from -128 to 127; each step is approximately 0.1ppm, and positive values decrease the frequency (increase the period). When set, a temperature conversion is forced so the result of calibration can be seen directly at the 32kHz pin after the next temperature conversion.""" + """Calibration values range from -128 to 127; each step is + approximately 0.1ppm, and positive values decrease the frequency + (increase the period). When set, a temperature conversion is forced so + the result of calibration can be seen directly at the 32kHz pin after + the next temperature conversion.""" return self._calibration @calibration.setter From a7e535a9fb1fba0fc8d7b02d75057b8f27190246 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 19 Jul 2020 11:24:31 -0500 Subject: [PATCH 3/3] Improvements based on review --- adafruit_ds3231.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/adafruit_ds3231.py b/adafruit_ds3231.py index c757ac1..9c56307 100644 --- a/adafruit_ds3231.py +++ b/adafruit_ds3231.py @@ -124,25 +124,26 @@ def temperature(self): only every 64 seconds, or when a conversion is forced.""" return self._temperature / 4 - def force_conversion(self): + def force_temperature_conversion(self): """Forces a conversion and returns the new temperature""" while self._busy: - pass + pass # Wait for any normal in-progress conversion to complete self._conv = True - while self._busy: - pass + while self._conv: + pass # Wait for manual conversion request to complete return self.temperature @property def calibration(self): - """Calibration values range from -128 to 127; each step is - approximately 0.1ppm, and positive values decrease the frequency - (increase the period). When set, a temperature conversion is forced so - the result of calibration can be seen directly at the 32kHz pin after - the next temperature conversion.""" + """Calibrate the frequency of the crystal oscillator by adding or + removing capacitance. The datasheet calls this the Aging Offset. + Calibration values range from -128 to 127; each step is approximately + 0.1ppm, and positive values decrease the frequency (increase the + period). When set, a temperature conversion is forced so the result of + calibration can be seen directly at the 32kHz pin immediately""" return self._calibration @calibration.setter def calibration(self, value): self._calibration = value - self.force_conversion() + self.force_temperature_conversion()