Skip to content

adding methods to setup critical/upper and lower temperatures #29

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 13 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ Getting the temperature in Celsius is easy! First, import all of the pins from
the board, board.I2C() for native I2C communication and the thermometer library
itself.

.. code-block:: python
.. code-block:: python3

from board import *
import board
import adafruit_mcp9808

Next, initialize the I2C bus in a with statement so it always gets shut down ok.
Then, construct the thermometer class:

.. code-block:: python
.. code-block:: python3

# Do one reading
with i2c = board.I2C() as i2c:
Expand Down
178 changes: 159 additions & 19 deletions adafruit_mcp9808.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft for Adafruit Industries
#
# SPDX-FileCopyrightText: 2021 Jose David Montoya
# SPDX-License-Identifier: MIT

"""
Expand All @@ -8,38 +8,60 @@

CircuitPython library to support MCP9808 high accuracy temperature sensor.

* Author(s): Scott Shawcroft
* Author(s): Scott Shawcroft, Jose David M.

Implementation Notes
--------------------

**Hardware:**

* Adafruit `MCP9808 High Accuracy I2C Temperature Sensor Breakout
* `Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout
<https://www.adafruit.com/products/1782>`_ (Product ID: 1782)

**Software and Dependencies:**

* Adafruit CircuitPython firmware for the supported boards:
https://github.com/adafruit/circuitpython/releases
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice

* Adafruit's Bus Device library:
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice

* Adafruit's Register library:
https://github.com/adafruit/Adafruit_CircuitPython_Register


**Notes:**

#. Datasheet: http://www.adafruit.com/datasheets/MCP9808.pdf

"""

from micropython import const
from adafruit_bus_device.i2c_device import I2CDevice
from adafruit_register.i2c_bits import RWBits
from adafruit_register.i2c_bit import ROBit

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP9808.git"

from adafruit_bus_device.i2c_device import I2CDevice

_MCP9808_DEFAULT_ADDRESS = const(0x18)
_MCP9808_DEVICE_ID = const(0x54)
_MCP9808_REG_CONFIGURATION = const(0x01)
_MCP9808_REG_UPPER_TEMP = const(0x02)
_MCP9808_REG_LOWER_TEMP = const(0x03)
_MCP9808_REG_CRITICAL_TEMP = const(0x04)
_MCP9808_REG__TEMP = const(0x05)
_MCP9808_REG_MANUFACTURER_ID = const(0x06)
_MCP9808_REG_DEVICE_ID = const(0x07)
_MCP9808_REG_RESOLUTION = const(0x08)

# Resolution settings
HALF_C = 0x0
QUARTER_C = 0x1
EIGHTH_C = 0x2
SIXTEENTH_C = 0x3

_MCP9808_RESOLUTION_HALF_C = const(0x0)
_MCP9808_RESOLUTION_QUARTER_C = const(0x1)
_MCP9808_RESOLUTION_EIGHTH_C = const(0x2)
_MCP9808_RESOLUTION_SIXTEENTH_C = const(0x3)


class MCP9808:
Expand All @@ -48,6 +70,17 @@ class MCP9808:
:param ~busio.I2C i2c_bus: The I2C bus the MCP9808 is connected to.
:param int address: The I2C address of the device. Defaults to :const:`0x18`

**MCP9808 Settings**
You could set the MCP9808 with different temperature limits and compare them with the
ambient temperature Ta

- above_ct this value will be set to `True` when Ta is above this limit
- above_ut: this value will be set to `True` when Ta is above this limit
- below_lt: this value will be set to `True` when Ta is below this limit

To get this value, you will need to read the temperature, and then access the attribute


**Quickstart: Importing and using the MCP9808**

Here is an example of using the :class:`MCP9808` class.
Expand All @@ -74,26 +107,33 @@ class MCP9808:

"""

# alert_lower_temperature_bound
# alert_upper_temperature_bound
# critical_temperature
# temperature
# temperature_resolution
_MCP9808_REG_RESOLUTION_SET = RWBits(2, 0x08, 0, register_width=2)
above_critical = ROBit(_MCP9808_REG__TEMP, 7, register_width=1)
"""True when the temperature is above the currently
set critical temperature. False Otherwise"""

above_upper = ROBit(_MCP9808_REG__TEMP, 6, register_width=1)
"""True when the temperature is above the currently
set high temperature. False Otherwise"""

def __init__(self, i2c_bus, address=0x18):
below_lower = ROBit(_MCP9808_REG__TEMP, 5, register_width=1)
"""True when the temperature is below the currently
set lower temperature. False Otherwise"""

def __init__(self, i2c_bus, address=_MCP9808_DEFAULT_ADDRESS):
self.i2c_device = I2CDevice(i2c_bus, address)

# Verify the manufacturer and device ids to ensure we are talking to
# what we expect.
self.buf = bytearray(3)
self.buf[0] = 0x06
self.buf[0] = _MCP9808_REG_MANUFACTURER_ID
with self.i2c_device as i2c:
i2c.write_then_readinto(self.buf, self.buf, out_end=1, in_start=1)

ok = self.buf[2] == 0x54 and self.buf[1] == 0
ok = self.buf[2] == _MCP9808_DEVICE_ID and self.buf[1] == 0

# Check device id.
self.buf[0] = 0x07
self.buf[0] = _MCP9808_REG_DEVICE_ID
with self.i2c_device as i2c:
i2c.write_then_readinto(self.buf, self.buf, out_end=1, in_start=1)

Expand All @@ -105,13 +145,113 @@ def __init__(self, i2c_bus, address=0x18):
@property
def temperature(self):
"""Temperature in Celsius. Read-only."""
self.buf[0] = 0x05
self.buf[0] = _MCP9808_REG__TEMP
with self.i2c_device as i2c:
i2c.write_then_readinto(self.buf, self.buf, out_end=1, in_start=1)

return self._temp_conv()

def _temp_conv(self):
"""Internal function to convert temperature given by the sensor"""
# Clear flags from the value
self.buf[1] = self.buf[1] & 0x1F
if self.buf[1] & 0x10 == 0x10:
self.buf[1] = self.buf[1] & 0x0F
return (self.buf[1] * 16 + self.buf[2] / 16.0) - 256
return self.buf[1] * 16 + self.buf[2] / 16.0

def _limit_temperatures(self, temp, t_address=0x02):
"""Internal function to setup limit temperature

:param int temp: temperature limit
:param int t_address: register address for the temperature limit
0x02 : Upper Limit
0x03 : Lower Limit
0x04 : Critical Limit
"""

if temp < 0:
negative = True
temp = abs(temp)
else:
negative = False

self.buf[0] = t_address

self.buf[1] = temp >> 4
if negative:
self.buf[1] = self.buf[1] | 0x10

self.buf[2] = (temp & 0x0F) << 4

with self.i2c_device as i2c:
i2c.write(self.buf)

def _get_temperature(self, address):
self.buf[0] = address
with self.i2c_device as i2c:
i2c.write_then_readinto(self.buf, self.buf, out_end=1, in_start=1)

return self._temp_conv()

def _set_temperature(self, temp, address):
self._limit_temperatures(temp, address)

@property
def upper_temperature(self):
"""Upper alarm temperature in Celsius"""

return self._get_temperature(_MCP9808_REG_UPPER_TEMP)

@upper_temperature.setter
def upper_temperature(self, temp):
"""Setup Upper temperature"""

self._limit_temperatures(temp, _MCP9808_REG_UPPER_TEMP)

@property
def lower_temperature(self):
"""Lower alarm temperature in Celsius"""

return self._get_temperature(_MCP9808_REG_LOWER_TEMP)

@lower_temperature.setter
def lower_temperature(self, temp):
"""Setup Lower temperature"""

self._limit_temperatures(temp, _MCP9808_REG_LOWER_TEMP)

@property
def critical_temperature(self):
"""Critical alarm temperature in Celsius"""

return self._get_temperature(_MCP9808_REG_CRITICAL_TEMP)

@critical_temperature.setter
def critical_temperature(self, temp):
"""Setup Critical temperature"""

self._limit_temperatures(temp, _MCP9808_REG_CRITICAL_TEMP)

@property
def resolution(self):
"""Temperature Resolution in Celsius

======= ============ ==============
Value Resolution Reading Time
======= ============ ==============
0 0.5°C 30 ms
1 0.25°C 65 ms
2 0.125°C 130 ms
3 0.0625°C 250 ms
======= ============ ==============

"""

return self._MCP9808_REG_RESOLUTION_SET

@resolution.setter
def resolution(self, resol_value=3):
""" Setup Critical temperature"""

self._MCP9808_REG_RESOLUTION_SET = resol_value # pylint: disable=invalid-name
4 changes: 4 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
"https://circuitpython.readthedocs.io/projects/busdevice/en/latest/",
None,
),
"Register": (
"https://circuitpython.readthedocs.io/projects/register/en/latest/",
None,
),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}

Expand Down
10 changes: 10 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ Ensure your device works with this simple test.
.. literalinclude:: ../examples/mcp9808_simpletest.py
:caption: examples/mcp9808_simpletest.py
:linenos:


Temperature Limit test
----------------------

Show the MCP9808 to setup different temperature values

.. literalinclude:: ../examples/mcp9808_temperature_limits.py
:caption: examples/mcp9808_temperature_limits.py
:linenos:
1 change: 0 additions & 1 deletion examples/mcp9808_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# Necessary when, for example, connecting A0 to VDD to make address=0x19
# mcp = adafruit_mcp9808.MCP9808(i2c_bus, address=0x19)


while True:
tempC = mcp.temperature
tempF = tempC * 9 / 5 + 32
Expand Down
32 changes: 32 additions & 0 deletions examples/mcp9808_temperature_limits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SPDX-FileCopyrightText: 2021 Jose David M.
# SPDX-License-Identifier: MIT

"""
Show the MCP9808 to setup different temperature values
"""

import time
import board
import adafruit_mcp9808

i2c = board.I2C() # uses board.SCL and board.SDA
mcp = adafruit_mcp9808.MCP9808(i2c)

# Change the values according to the desired values
print("Setting Temperature Limits")
mcp.upper_temperature = 23
mcp.lower_temperature = 10
mcp.critical_temperature = 100

# To verify the limits we need to read the temperature value
print(mcp.temperature)
time.sleep(0.3) # This is the time temperature conversion at maximum resolution

# Showing temperature Limits
while True:
if mcp.below_lt:
print("too cold!")
if mcp.above_ut:
print("getting hot!")
if mcp.above_ct:
print("Above critical temp!")
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
#
# SPDX-License-Identifier: Unlicense

Adafruit-Blinka
adafruit-circuitpython-busdevice
adafruit-circuitpython-register