1
1
# The MIT License (MIT)
2
2
#
3
3
# Copyright (c) 2019 Dan Cogliano for Adafruit Industries
4
+ # Copyright (c) 2019 Kattni Rembor for Adafruit Industries
4
5
#
5
6
# Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
# of this software and associated documentation files (the "Software"), to deal
26
27
CircuitPython driver for the MCP9600 thermocouple I2C amplifier
27
28
28
29
29
- * Author(s): Dan Cogliano
30
+ * Author(s): Dan Cogliano, Kattni Rembor
30
31
31
32
Implementation Notes
32
33
--------------------
44
45
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
45
46
"""
46
47
47
- # imports
48
-
49
- __version__ = "0.0.0-auto.0"
50
- __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_MCP9600.git"
51
-
52
48
from struct import unpack
53
49
from micropython import const
54
50
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"
55
57
56
58
_DEFAULT_ADDRESS = const (0x67 )
57
59
61
63
_REGISTER_THERM_CFG = const (0x05 )
62
64
_REGISTER_VERSION = const (0x20 )
63
65
64
- class MCP9600 ():
66
+
67
+ class MCP9600 :
65
68
"""Interface to the MCP9600 thermocouple amplifier breakout"""
66
69
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
+
67
178
types = ("K" , "J" , "T" , "N" , "S" , "E" , "B" , "R" )
68
179
69
180
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):
82
193
self .buf [1 ] = tcfilter | (ttype << 4 )
83
194
with self .i2c_device as tci2c :
84
195
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 )
85
285
86
286
@property
87
287
def version (self ):
@@ -98,7 +298,6 @@ def ambient_temperature(self):
98
298
value -= 4096
99
299
return value
100
300
101
-
102
301
@property
103
302
def temperature (self ):
104
303
""" Hot junction temperature in Celsius """
0 commit comments