Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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_ct = ROBit(_MCP9808_REG__TEMP, 7, register_width=1)
"""True when the temperature is above than the currently
set critical temperature. False Otherwise"""

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

def __init__(self, i2c_bus, address=0x18):
below_lt = ROBit(_MCP9808_REG__TEMP, 5, register_width=1)
"""True when the temperature is below than 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