Skip to content

Commit 032c135

Browse files
authored
Merge pull request #3 from kattni/implement-features
Implements advanced features.
2 parents 679821e + 95e59d4 commit 032c135

File tree

2 files changed

+208
-9
lines changed

2 files changed

+208
-9
lines changed

adafruit_mcp9600.py

Lines changed: 207 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# The MIT License (MIT)
22
#
33
# Copyright (c) 2019 Dan Cogliano for Adafruit Industries
4+
# Copyright (c) 2019 Kattni Rembor for Adafruit Industries
45
#
56
# Permission is hereby granted, free of charge, to any person obtaining a copy
67
# of this software and associated documentation files (the "Software"), to deal
@@ -26,7 +27,7 @@
2627
CircuitPython driver for the MCP9600 thermocouple I2C amplifier
2728
2829
29-
* Author(s): Dan Cogliano
30+
* Author(s): Dan Cogliano, Kattni Rembor
3031
3132
Implementation Notes
3233
--------------------
@@ -44,14 +45,15 @@
4445
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
4546
"""
4647

47-
# imports
48-
49-
__version__ = "0.0.0-auto.0"
50-
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP9600.git"
51-
5248
from struct import unpack
5349
from micropython import const
5450
from adafruit_bus_device.i2c_device import I2CDevice
51+
from adafruit_register.i2c_struct import UnaryStruct
52+
from adafruit_register.i2c_bits import RWBits, ROBits
53+
from adafruit_register.i2c_bit import RWBit, ROBit
54+
55+
__version__ = "0.0.0-auto.0"
56+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP9600.git"
5557

5658
_DEFAULT_ADDRESS = const(0x67)
5759

@@ -61,9 +63,118 @@
6163
_REGISTER_THERM_CFG = const(0x05)
6264
_REGISTER_VERSION = const(0x20)
6365

64-
class MCP9600():
66+
67+
class MCP9600:
6568
"""Interface to the MCP9600 thermocouple amplifier breakout"""
6669

70+
# Shutdown mode options
71+
NORMAL = 0b00
72+
SHUTDOWN = 0b01
73+
BURST = 0b10
74+
75+
# Burst mode sample options
76+
BURST_SAMPLES_1 = 0b000
77+
BURST_SAMPLES_2 = 0b001
78+
BURST_SAMPLES_4 = 0b010
79+
BURST_SAMPLES_8 = 0b011
80+
BURST_SAMPLES_16 = 0b100
81+
BURST_SAMPLES_32 = 0b101
82+
BURST_SAMPLES_64 = 0b110
83+
BURST_SAMPLES_128 = 0b111
84+
85+
# Alert temperature monitor options
86+
AMBIENT = 1
87+
THERMOCOUPLE = 0
88+
89+
# Temperature change type to trigger alert. Rising is heating up. Falling is cooling down.
90+
RISING = 1
91+
FALLING = 0
92+
93+
# Alert output options
94+
ACTIVE_HIGH = 1
95+
ACTIVE_LOW = 0
96+
97+
# Alert mode options
98+
INTERRUPT = 1 # Interrupt clear option must be set when using this mode!
99+
COMPARATOR = 0
100+
101+
# Ambient (cold-junction) temperature sensor resolution options
102+
AMBIENT_RESOLUTION_0_0625 = 0 # 0.0625 degrees Celsius
103+
AMBIENT_RESOLUTION_0_25 = 1 # 0.25 degrees Celsius
104+
105+
# STATUS - 0x4
106+
burst_complete = RWBit(0x4, 7)
107+
"""Burst complete."""
108+
temperature_update = RWBit(0x4, 6)
109+
"""Temperature update."""
110+
input_range = ROBit(0x4, 4)
111+
"""Input range."""
112+
alert_1 = ROBit(0x4, 0)
113+
"""Alert 1 status."""
114+
alert_2 = ROBit(0x4, 1)
115+
"""Alert 2 status."""
116+
alert_3 = ROBit(0x4, 2)
117+
"""Alert 3 status."""
118+
alert_4 = ROBit(0x4, 3)
119+
"""Alert 4 status."""
120+
# Device Configuration - 0x6
121+
ambient_resolution = RWBit(0x6, 7)
122+
"""Ambient (cold-junction) temperature resolution. Options are ``AMBIENT_RESOLUTION_0_0625``
123+
(0.0625 degrees Celsius) or ``AMBIENT_RESOLUTION_0_25`` (0.25 degrees Celsius)."""
124+
burst_mode_samples = RWBits(3, 0x6, 2)
125+
"""The number of samples taken during a burst in burst mode. Options are ``BURST_SAMPLES_1``,
126+
``BURST_SAMPLES_2``, ``BURST_SAMPLES_4``, ``BURST_SAMPLES_8``, ``BURST_SAMPLES_16``,
127+
``BURST_SAMPLES_32``, ``BURST_SAMPLES_64``, ``BURST_SAMPLES_128``."""
128+
shutdown_mode = RWBits(2, 0x6, 0)
129+
"""Shutdown modes. Options are ``NORMAL``, ``SHUTDOWN``, and ``BURST``."""
130+
# Alert 1 Configuration - 0x8
131+
_alert_1_interrupt_clear = RWBit(0x8, 7)
132+
_alert_1_monitor = RWBit(0x8, 4)
133+
_alert_1_temp_direction = RWBit(0x8, 3)
134+
_alert_1_state = RWBit(0x8, 2)
135+
_alert_1_mode = RWBit(0x8, 1)
136+
_alert_1_enable = RWBit(0x8, 0)
137+
# Alert 2 Configuration - 0x9
138+
_alert_2_interrupt_clear = RWBit(0x9, 7)
139+
_alert_2_monitor = RWBit(0x9, 4)
140+
_alert_2_temp_direction = RWBit(0x9, 3)
141+
_alert_2_state = RWBit(0x9, 2)
142+
_alert_2_mode = RWBit(0x9, 1)
143+
_alert_2_enable = RWBit(0x9, 0)
144+
# Alert 3 Configuration - 0xa
145+
_alert_3_interrupt_clear = RWBit(0xa, 7)
146+
_alert_3_monitor = RWBit(0xa, 4)
147+
_alert_3_temp_direction = RWBit(0xa, 3)
148+
_alert_3_state = RWBit(0xa, 2)
149+
_alert_3_mode = RWBit(0xa, 1)
150+
_alert_3_enable = RWBit(0xa, 0)
151+
# Alert 4 Configuration - 0xb
152+
_alert_4_interrupt_clear = RWBit(0xb, 7)
153+
_alert_4_monitor = RWBit(0xb, 4)
154+
_alert_4_temp_direction = RWBit(0xb, 3)
155+
_alert_4_state = RWBit(0xb, 2)
156+
_alert_4_mode = RWBit(0xb, 1)
157+
_alert_4_enable = RWBit(0xb, 0)
158+
# Alert 1 Hysteresis - 0xc
159+
_alert_1_hysteresis = UnaryStruct(0xc, ">H")
160+
# Alert 2 Hysteresis - 0xd
161+
_alert_2_hysteresis = UnaryStruct(0xd, ">H")
162+
# Alert 3 Hysteresis - 0xe
163+
_alert_3_hysteresis = UnaryStruct(0xe, ">H")
164+
# Alert 4 Hysteresis - 0xf
165+
_alert_4_hysteresis = UnaryStruct(0xf, ">H")
166+
# Alert 1 Limit - 0x10
167+
_alert_1_temperature_limit = UnaryStruct(0x10, ">H")
168+
# Alert 2 Limit - 0x11
169+
_alert_2_limit = UnaryStruct(0x11, ">H")
170+
# Alert 3 Limit - 0x12
171+
_alert_3_limit = UnaryStruct(0x12, ">H")
172+
# Alert 4 Limit - 0x13
173+
_alert_4_limit = UnaryStruct(0x13, ">H")
174+
# Device ID/Revision - 0x20
175+
_device_id = ROBits(8, 0x20, 8, register_width=2, lsb_first=False)
176+
_revision_id = ROBits(8, 0x20, 0, register_width=2)
177+
67178
types = ("K", "J", "T", "N", "S", "E", "B", "R")
68179

69180
def __init__(self, i2c, address=_DEFAULT_ADDRESS, tctype="K", tcfilter=0):
@@ -82,6 +193,95 @@ def __init__(self, i2c, address=_DEFAULT_ADDRESS, tctype="K", tcfilter=0):
82193
self.buf[1] = tcfilter | (ttype << 4)
83194
with self.i2c_device as tci2c:
84195
tci2c.write(self.buf, end=2)
196+
if self._device_id != 0x40:
197+
raise RuntimeError("Failed to find MCP9600 - check wiring!")
198+
199+
def alert_config(self, *, alert_number, alert_temp_source, alert_temp_limit, alert_hysteresis,
200+
alert_temp_direction, alert_mode, alert_state):
201+
"""Configure a specified alert pin. Alert is enabled by default when alert is configured.
202+
To disable an alert pin, use ``alert_disable``.
203+
204+
:param int alert_number: The alert pin number. Must be 1-4.
205+
:param alert_temp_source: The temperature source to monitor for the alert. Options are:
206+
``THERMOCOUPLE`` (hot-junction) or ``AMBIENT`` (cold-junction).
207+
Temperatures are in Celsius.
208+
:param float alert_temp_limit: The temperature in degrees Celsius at which the alert should
209+
trigger. For rising temperatures, the alert will trigger when
210+
the temperature rises above this limit. For falling
211+
temperatures, the alert will trigger when the temperature
212+
falls below this limit.
213+
:param float alert_hysteresis: The alert hysteresis range. Must be 0-255 degrees Celsius.
214+
For rising temperatures, the hysteresis is below alert limit.
215+
For falling temperatures, the hysteresis is above alert
216+
limit. See data-sheet for further information.
217+
:param alert_temp_direction: The direction the temperature must change to trigger the alert.
218+
Options are ``RISING`` (heating up) or ``FALLING`` (cooling
219+
down).
220+
:param alert_mode: The alert mode. Options are ``COMPARATOR`` or ``INTERRUPT``. In
221+
comparator mode, the pin will follow the alert, so if the temperature
222+
drops, for example, the alert pin will go back low. In interrupt mode,
223+
by comparison, once the alert goes off, you must manually clear it. If
224+
setting mode to ``INTERRUPT``, use ``alert_interrupt_clear`` to clear the
225+
interrupt flag.
226+
:param alert_state: Alert pin output state. Options are ``ACTIVE_HIGH`` or ``ACTIVE_LOW``.
227+
228+
229+
For example, to configure alert 1:
230+
231+
.. code-block:: python
232+
233+
import board
234+
import busio
235+
import digitalio
236+
import adafruit_mcp9600
237+
238+
i2c = busio.I2C(board.SCL, board.SDA, frequency=100000)
239+
mcp = adafruit_mcp9600.MCP9600(i2c)
240+
alert_1 = digitalio.DigitalInOut(board.D5)
241+
alert_1.switch_to_input()
242+
243+
mcp.burst_mode_samples = mcp.BURST_SAMPLES_1
244+
mcp.ambient_resolution = mcp.AMBIENT_RESOLUTION_0_25
245+
mcp.alert_config(alert_number=1, alert_temp_source=mcp.THERMOCOUPLE,
246+
alert_temp_limit=25, alert_hysteresis=0,
247+
alert_temp_direction=mcp.RISING, alert_mode=mcp.COMPARATOR,
248+
alert_state=mcp.ACTIVE_LOW)
249+
250+
"""
251+
if alert_number not in (1, 2, 3, 4):
252+
raise ValueError("Alert pin number must be 1-4.")
253+
if not 0 <= alert_hysteresis < 256:
254+
raise ValueError("Hysteresis value must be 0-255.")
255+
setattr(self, '_alert_%d_monitor' % alert_number, alert_temp_source)
256+
setattr(self, '_alert_%d_temperature_limit' % alert_number, int(alert_temp_limit / 0.0625))
257+
setattr(self, '_alert_%d_hysteresis' % alert_number, alert_hysteresis)
258+
setattr(self, '_alert_%d_temp_direction' % alert_number, alert_temp_direction)
259+
setattr(self, '_alert_%d_mode' % alert_number, alert_mode)
260+
setattr(self, '_alert_%d_state' % alert_number, alert_state)
261+
setattr(self, '_alert_%d_enable' % alert_number, True)
262+
263+
def alert_disable(self, alert_number):
264+
"""Configuring an alert using ``alert_config()`` enables the specified alert by default.
265+
Use ``alert_disable`` to disable an alert pin.
266+
267+
:param int alert_number: The alert pin number. Must be 1-4.
268+
269+
"""
270+
if alert_number not in (1, 2, 3, 4):
271+
raise ValueError("Alert pin number must be 1-4.")
272+
setattr(self, '_alert_%d_enable' % alert_number, False)
273+
274+
def alert_interrupt_clear(self, alert_number, interrupt_clear=True):
275+
"""Turns off the alert flag in the MCP9600, and clears the pin state (not used if the alert
276+
is in comparator mode). Required when ``alert_mode`` is ``INTERRUPT``.
277+
278+
:param int alert_number: The alert pin number. Must be 1-4.
279+
:param bool interrupt_clear: The bit to write the interrupt state flag
280+
281+
"""
282+
if alert_number not in (1, 2, 3, 4):
283+
raise ValueError("Alert pin number must be 1-4.")
284+
setattr(self, '_alert_%d_interrupt_clear' % alert_number, interrupt_clear)
85285

86286
@property
87287
def version(self):
@@ -98,7 +298,6 @@ def ambient_temperature(self):
98298
value -= 4096
99299
return value
100300

101-
102301
@property
103302
def temperature(self):
104303
""" Hot junction temperature in Celsius """

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# Uncomment the below if you use native CircuitPython modules such as
2121
# digitalio, micropython and busio. List the modules you use. Without it, the
2222
# autodoc module docs will fail to generate with a warning.
23-
# autodoc_mock_imports = ["digitalio", "busio"]
23+
autodoc_mock_imports = ["adafruit_register"]
2424

2525

2626
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}

0 commit comments

Comments
 (0)