Skip to content

DS3231: Add calibration, temperature, and force_conversion #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 20, 2020
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions adafruit_ds3231.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand All @@ -107,3 +117,32 @@ 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"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conversion seems a bit vague. Is there a more detailed way of describing it? I expected it to be force_temperature_conversion but then calibration calls it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rework this a bit and rename it. (the checking for conversion-completed is wrong too) It is forcing a temperature conversion, which is necessary for the new oscillator calibration to become effective.

Datasheet says:

Bit 5: Convert Temperature (CONV).
Setting this bit to 1 forces the temperature sensor to convert the temperature into digital code and execute the TCXO algorithm to update the capacitance array to the oscillator.
This can only happen when a conversion is not already in progress. The user should check the status bit BSY before forcing the controller to start a new TCXO execution.
A user-initiated temperature conversion does not affect the internal 64-second update cycle.
A user-initiated temperature conversion does not affect the BSY bit for approximately 2ms.
The CONV bit remains at a 1 from the time it is written until the conversion is finished, at which time both CONV and BSY go to 0. The CONV bit should be used when monitoring the status of a user-initiated conversion

and explains why triggering a conversion after setting the calibration value ("aging offset") is useful:

The offset register is added to the capacitance array during a normal temperature conversion, if the temperature changes from the previous conversion, or during a manual user conversion (setting the CONV bit). To see the effects of the aging register on the 32kHz output frequency immediately, a manual conversion should be started after each aging register change.

`

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()