-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmcp9808.py
721 lines (614 loc) · 26.3 KB
/
mcp9808.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
"""MIT License
Copyright (c) 2024 Marco Miano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Microchip MCP9808 driver for MicroPython
THE MCP9808 IS A COMPLEX SENSOR WITH MANY FEATURES. IS IT ADVISABLE TO READ THE DATASHEET.
DO NOT ACCESS REGISTERS WITH ADDRESSES HIGHER THAN 0x08 AS THEY CONTAIN CALIBRATION CODES.
DOING SO MAY IRREPARABLY DAMAGE THE SENSOR.
This driver is a comprehensive implementation of the MCP9808 sensor's features. It is designed
to be easy to use and offers a high level of abstraction from the sensor's registers.
The driver includes built-in error checking (such as type validation and bounds checking
for register access) and a debug mode to assist with development.
Example usage:
from mcp9808 import MCP9808, HYST_15, RES_0_125
from machine import SoftI2C, Pin
i2c = SoftI2C(scl=Pin(17), sda=Pin(16), freq=400000)
t_sensor = MCP9808(i2c)
# Get temeperature with deafult settings
temperature: float = t_sensor.get_temperature()
# Various settings
t_sensor.set_hysteresis_mode(hyst_mode=HYST_15)
t_sensor.set_resolution(resolution=RES_0_125)
t_sensor.set_alert_crit_limit(crit_limit=65.0)
t_sensor.set_alert_upper_limit(upper_limit=50.0)
t_sensor.set_alert_lower_limit(lower_limit=-10.0)
t_sensor.enable_alert()
# Enable debug mode to get warnings
t_sensor._debug = True
# For more information, see the README file at
https://github.com/MarcoMiano/mip-mcp9808
"""
from machine import SoftI2C, I2C
# Handy Constants
HYST_00 = 0b00 # Hysteresis 0°C (power-up default)
HYST_15 = 0b01 # Hysteresis 1,5°C
HYST_30 = 0b10 # Hysteresis 3,0°C
HYST_60 = 0b11 # Hysteresis 6,0°C
RES_0_5 = 0b00 # Resolution 0.5°C
RES_0_25 = 0b01 # Resolution 0.25°C
RES_0_125 = 0b10 # Resolution 0.125°C
RES_0_0625 = 0b11 # Resolution 0.0625°C (power-up default)
class MCP9808(object):
"""A class to interface with the Microchip MCP9808 temperature sensor over I2C.
Attributes:
``BASE_ADDR`` (int): The base I2C address for the MCP9808 sensor.
``REG_CFG`` (int): Address of the configuration register.
``REG_ATU`` (int): Address of the alert temperature upper boundary trip register.
``REG_ATL`` (int): Address of the alert temperature lower boundary trip register.
``REG_ATC`` (int): Address of the critical temperature trip register.
``REG_TEM`` (int): Address of the temperature register.
``REG_MFR`` (int): Address of the manufacturer ID register.
``REG_DEV`` (int): Address of the device ID register.
``REG_RES`` (int): Address of the resolution register.
"""
BASE_ADDR = 0x18
#######################################################
# DON'T ACCESS REGISTER WITH ADDRESS HIGHER THAN 0X08 #
#######################################################
REG_CFG = 0x01 # Config register
REG_ATU = 0x02 # Alert Temperature Upper boundary trip register
REG_ATL = 0x03 # Alert Temperature Lower boundary trip register
REG_ATC = 0x04 # Critical Temperature Trip register
REG_TEM = 0x05 # Temperature register
REG_MFR = 0x06 # Manufacturer ID register
REG_DEV = 0x07 # Device ID register
REG_RES = 0x08 # Resolution register
def __init__(
self,
i2c: SoftI2C | I2C,
addr: int | None = None,
A0: bool = False,
A1: bool = False,
A2: bool = False,
debug: bool = False,
) -> None:
"""Initialize the sensor object instance.
Args:
``i2c`` (SoftI2C | I2C): The I2C bus instance to use for communication.
``addr`` (int | None, optional): The I2C address of the sensor. If not provided,
the address will be calculated based on A0, A1, and A2. Defaults to None.
``A0`` (bool, optional): The state of address pin A0. Defaults to False.
``A1`` (bool, optional): The state of address pin A1. Defaults to False.
``A2`` (bool, optional): The state of address pin A2. Defaults to False.
``debug`` (bool, optional): Enable or disable debug mode. Defaults to False.
Returns:
``None``
"""
self._i2c: SoftI2C | I2C = i2c
self._debug: bool = debug
if addr:
self._addr = addr
else:
self._addr: int = self.BASE_ADDR | (A2 << 2) | (A1 << 1) | A0
self._check_device()
self._get_config()
def _check_device(self) -> None:
"""Checks the device's manufacturer ID and device ID to ensure it is the correct device.
Raises:
``Exception``: If the manufacturer ID does not match the expected value.
``Exception``: If the device ID does not match the expected value.
Warns:
If the hardware revision does not match the expected value and debug mode is enabled.
Returns:
``None``
"""
self._mfr_id: bytes = self._i2c.readfrom_mem(self._addr, self.REG_MFR, 2)
if self._mfr_id != b"\x00\x54":
raise Exception(f"Invalid manufacturer ID {self._mfr_id}")
self._dev_id: bytes = self._i2c.readfrom_mem(self._addr, self.REG_DEV, 2)
if self._dev_id[0] != 4:
raise Exception(f"Invalid device ID {self._dev_id[0]}")
if self._dev_id[1] != 0 and self._debug:
print(
f"[WARN] Module written for HW revision 0 but got {self._dev_id[1]}.",
)
def _get_config(self) -> None:
"""Private method to read the configuration register from the sensor.
This method reads 2 bytes from the configuration register of the sensor.
It then parses the bytes to update the following instance attributes:
``_hyst_mode``: Hysteresis mode (int)
``_shdn``: Shutdown mode (bool)
``_crit_lock``: Critical temperature register lock (bool)
``_alerts_lock``: Alerts temperature registers lock (bool)
``_irq_clear_bit``: Interrupt clear bit (bool)
``_alert``: Alert output status (bool)
``_alert_ctrl``: Alert control (bool)
``_alert_sel``: Alert output select (bool)
``_alert_pol``: Alert output polarity (bool)
``_alert_mode``: Alert output mode (bool)
Returns:
``None``
"""
buf: bytes = self._i2c.readfrom_mem(self._addr, self.REG_CFG, 2)
self._hyst_mode: int = (buf[0] >> 1) & 0x03
self._shdn = bool(buf[0] & 0x01)
self._crit_lock = bool(buf[1] & 0x80)
self._alerts_lock = bool(buf[1] & 0x40)
self.irq_clear_bit = bool(buf[1] & 0x20)
self._alert = bool(buf[1] & 0x10)
self._alert_ctrl = bool(buf[1] & 0x08)
self._alert_sel = bool(buf[1] & 0x04)
self.alert_pol = bool(buf[1] & 0x02)
self._alert_mode = bool(buf[1] & 0x01)
def _set_config(
self,
hyst_mode: int | None = None,
shdn: bool | None = None,
crit_lock: bool | None = None,
alerts_lock: bool | None = None,
irq_clear_bit: bool = False,
alert_ctrl: bool | None = None,
alert_sel: bool | None = None,
alert_pol: bool | None = None,
alert_mode: bool | None = None,
) -> None:
"""Private method to set the configuration of the sensor.
Parameters:
``hyst_mode`` (int | None): Hysteresis mode. Valid values are HYST_00, HYST_15, HYST_30, HYST_60.
``shdn (bool`` | None): Shutdown mode.
``crit_lock`` (bool | None): Critical temperature register lock.
``alerts_lock`` (bool | None): Alerts temperature registers lock.
``irq_clear``_bit (bool): Interrupt clear bit.
``alert_ctrl`` (bool | None): Alert output control.
``alert_sel`` (bool | None): Alert output select.
``alert_pol`` (bool | None): Alert output polarity.
``alert_mode`` (bool | None): Alert output mode.
Raises:
``ValueError``: If hyst_mode is not one of the valid values.
``TypeError``: If any of the boolean parameters are not of type bool.
Returns:
``None``
"""
if hyst_mode is None:
hyst_mode = self._hyst_mode
if shdn is None:
shdn = self._shdn
if crit_lock is None:
crit_lock = self._crit_lock
if alerts_lock is None:
alerts_lock = self._alerts_lock
if alert_ctrl is None:
alert_ctrl = self._alert_ctrl
if alert_sel is None:
alert_sel = self._alert_sel
if alert_pol is None:
alert_pol = self.alert_pol
if alert_mode is None:
alert_mode = self._alert_mode
# Type/value check the parameters
if hyst_mode not in [HYST_00, HYST_15, HYST_30, HYST_60]:
raise ValueError(
f"hyst_mode: {hyst_mode}. Value should be between 0 and 3 inclusive."
)
if shdn.__class__ is not bool:
raise TypeError(
f"shdn: {shdn} {shdn.__class__}. Expecting a bool.",
)
if crit_lock.__class__ is not bool:
raise TypeError(
f"crit_lock: {crit_lock} {crit_lock.__class__}. Expecting a bool.",
)
if alerts_lock.__class__ is not bool:
raise TypeError(
f"alerts_lock: {alerts_lock} {alerts_lock.__class__}. Expecting a bool.",
)
if irq_clear_bit.__class__ is not bool:
raise TypeError(
f"irq_clear_bit: {irq_clear_bit} {irq_clear_bit.__class__}. Expecting a bool.",
)
if alert_ctrl.__class__ is not bool:
raise TypeError(
f"alert_ctrl: {alert_ctrl} {alert_ctrl.__class__}. Expecting a bool.",
)
if alert_sel.__class__ is not bool:
raise TypeError(
f"alert_sel: {alert_sel} {alert_sel.__class__}. Expecting a bool.",
)
if alert_pol.__class__ is not bool:
raise TypeError(
f"alert_pol: {alert_pol} {alert_pol.__class__}. Expecting a bool.",
)
if alert_mode.__class__ is not bool:
raise TypeError(
f"alert_mode: {alert_mode} {alert_mode.__class__}. Expecting a bool.",
)
# Build the send buffer
buf = bytearray(b"\x00\x00")
buf[0] = (hyst_mode << 1) | shdn
buf[1] = (
(crit_lock << 7)
| (alerts_lock << 6)
| (irq_clear_bit << 5)
| (alert_ctrl << 3)
| (alert_sel << 2)
| (alert_pol << 1)
| alert_mode
)
# Write the buffer to the sensor
self._i2c.writeto_mem(self._addr, self.REG_CFG, buf)
self._get_config()
# Check if the configuration was set correctly id debug mode is enabled
if self._debug:
if self._hyst_mode != hyst_mode:
print(
f"[WARN] Failed to set hyst_mode. Set {hyst_mode} got {self._hyst_mode}",
)
if self._shdn != shdn:
print(
f"[WARN] Failed to set shdn. Set {shdn} got {self._shdn}",
)
if self._crit_lock != crit_lock:
print(
f"[WARN] Failed to set crit_lock. Set {crit_lock} got {self._crit_lock}",
)
if self.irq_clear_bit:
print(
"[WARN] Something wrong with irq_clear_bit. Should always read False"
)
if self._alerts_lock != alerts_lock:
print(
f"[WARN] Failed to set alerts_lock. Set {alerts_lock} got {self._alerts_lock}",
)
if self._alert_ctrl != alert_ctrl:
print(
f"[WARN] Failed to set alert_ctrl. Set {alert_ctrl} got {self._alert_ctrl}.",
)
if self._alert_sel != alert_sel:
print(
f"[WARN] Failed to set alert_sel. Set {alert_sel} got {self._alert_sel}.",
)
if self.alert_pol != alert_pol:
print(
f"[WARN] Failed to set alert_pol. Set {alert_pol} got {self.alert_pol}.",
)
if self._alert_mode != alert_mode:
print(
f"[WARN] Failed to set alert_mode. Set {alert_mode} got {self._alert_mode}.",
)
def _set_alert_limit(self, limit: float, register: int) -> None:
"""Private method to set the alert limit register.
Inteded to be used by the set_alert_XXXXX_limit wrapper methods.
Args:
``limit`` (float | int): The temperature limit to set. Must be between -128 and 127.
``register`` (int): The register address to write the limit to.
Raises:
``TypeError``: If the limit is not a float or int.
``ValueError``: If the limit is out of the range [-128, 127].
``ValueError``: If the register address is not valid.
Debug:
- Issue a warning if the threshold is outside of the operational range.
- Issue a warning if the alert limit was not set correctly.
Returns:
``None``
"""
if limit.__class__ not in [float, int]:
raise TypeError(
f"limit: {limit} {limit.__class__}. Expecting float|int.",
)
if limit < -128 or limit > 127:
raise ValueError("Temperature out of range [-128, 127]")
if (limit < -40 or limit > 125) and self._debug:
print(
"[WARN] Temperature outside of operational range, limit won't be ever reached.",
)
if register not in [self.REG_ATU, self.REG_ATL, self.REG_ATC]:
raise ValueError(f"Invalid register address {register}")
buf = bytearray(b"\x00\x00")
# If limit is negative set sign fifth bit ON otherwise leave it OFF
if limit < 0:
sign = 0x10
else:
sign = 0x00
# If limit is between -1 and 0 (like -0.25) set integral to 0xFF (-0 in 2's complement)
if -1 < limit < 0:
integral: int = 0xFF
# Otherwise truncate limit to a int and keep only the rightmost byte
else:
integral: int = int(limit) & 0xFF
# Calculate the fractional part by keeping the 2 rightmost bits of the integer division
# of 0.25 (the sensitivity) and the remainder part of the decimal part of limit
frac_normal: int = int((limit - integral) / 0.25) & 0x03
# Build the send buffer highest byte combining (bitwise-or) sign and the integral
# right-shifted by 4
buf[0] = sign | (integral >> 4)
# Build the send buffer lowest byte combining (bitwise-or) the integral
# left-shifted by 4 and the fractional part left shifted by 2 (last 2 bit are 0)
buf[1] = (integral << 4) | (frac_normal << 2)
self._i2c.writeto_mem(self._addr, register, buf)
if self._debug:
check: bytes = self._i2c.readfrom_mem(self._addr, register, 2)
if check != buf:
print(
f"[WARN] Failed to set alert limit. Set {buf[0]:08b}-{buf[1]:08b}",
f"but got {check[0]:08b}-{check[1]:08b}",
)
def shutdown(self) -> None:
"""Put the sensor in low power mode.
Returns:
``None``
"""
self._set_config(shdn=True)
def wake(self) -> None:
"""Wake the sensor from low power mode.
Returns:
``None``
"""
self._set_config(shdn=False)
def lock_crit_limit(self) -> None:
"""Locks the critical temperature limit.
When the critical temperature limit is locked, it cannot be changed
until the sensor is power cycled.
Returns:
``None``
"""
self._set_config(crit_lock=True)
def lock_alerts_limit(self) -> None:
"""Locks the alerts limits.
When the alerts limits are locked, they cannot be changed
until the sensor is power cycled.
Returns:
``None``
"""
self._set_config(alerts_lock=True)
def irq_clear(self) -> None:
"""Clears the interrupt output.
This method clears the interrupt output.
Returns:
``None``
"""
self._set_config(irq_clear_bit=True)
def get_alert_status(self) -> bool:
"""Get the alert status.
This method reads the alert status from the sensor.
Returns:
``bool``: The alert status.
"""
self._get_config()
return self.alert
def enable_alert(self) -> None:
"""Enable the alert output.
Returns:
``None``
"""
self._set_config(alert_ctrl=True)
def disable_alert(self) -> None:
"""Disable the alert output.
Returns:
``None``
"""
self._set_config(alert_ctrl=False)
def set_alert_threshold(self, only_crit=False) -> None:
"""Set the alert output select.
Select if the alert output should be activated only by the critical limit or both critical
and upper/lower limits.
Args:
``only_crit`` (bool, optional): Set the alert output to only critical. Defaults to False.
Returns:
``None``
"""
self._set_config(alert_sel=only_crit)
def set_alert_polarity(self, active_high=False) -> None:
"""Set the alert output polarity.
Set the alert output polarity to active high or active low.
Args:
``active_high`` (bool, optional): Set the alert output polarity to active high.
Defaults to False.
Returns:
``None``
"""
self._set_config(alert_pol=active_high)
def set_alert_mode(self, irq=False) -> None:
"""Set the alert output mode.
Set the alert output mode to interrupt or comparator.
Args:
``irq`` (bool, optional): Set the alert output mode to interrupt. Defaults to False.
Returns:
``None``
"""
self._set_config(alert_mode=irq)
def set_alert_upper_limit(self, upper_limit: float) -> None:
"""Set the alert upper limit.
Args:
upper_limit (float | int): The upper limit to set.
It will rounded to the nearest 0.25°C.
Raises:
``TypeError``: If the limit is not a float or int.
``ValueError``: If the limit is out of the range [-128, 127].
Debug:
- Issue a warning if the threshold is outside of the operational range.
- Issue a warning if the alert limit was not set correctly.
Returns:
``None``
"""
self._set_alert_limit(upper_limit, self.REG_ATU)
def set_alert_lower_limit(self, lower_limit: float) -> None:
"""Set the alert lower limit.
Args:
lower_limit (float | int): The lower limit to set.
Raises:
``TypeError``: If the limit is not a float or int.
``ValueError``: If the limit is out of the range [-128, 127].
Debug:
- Issue a warning if the threshold is outside of the operational range.
- Issue a warning if the alert limit was not set correctly.
Returns:
``None``
"""
self._set_alert_limit(lower_limit, self.REG_ATL)
def set_alert_crit_limit(self, crit_limit: float) -> None:
"""Set the alert critical limit.
Args:
crit_limit (float | int): The critical limit to set.
Raises:
``TypeError``: If the limit is not a float or int.
``ValueError``: If the limit is out of the range [-128, 127].
Debug:
- Issue a warning if the threshold is outside of the operational range.
- Issue a warning if the alert limit was not set correctly.
Returns:
``None``
"""
self._set_alert_limit(crit_limit, self.REG_ATC)
def get_temperature(self) -> float:
"""Get the temperature from the sensor.
Returns:
``float``: The temperature in degrees Celsius.
"""
# Read temperature register from sensor
buf: bytes = self._i2c.readfrom_mem(self._addr, self.REG_TEM, 2)
# Extract the sign bit
sign: int = buf[0] & 0x10
# Calculate the 4 upper bit of the integral by left shifting the first byte by 4
upper: int = (buf[0] << 4) & 0xFF
# Calculate the 4 lower bit of the integral and the fractional part into a float
# dividing by 16 the second buf byte
lower: float = (buf[1] & 0xFF) / 16
# Calculate the temperature as a float, adding the upper byte (leftmost 4 bit of integral)
# and the lower byte (rightmost 4 bit of integral + fractional).
# In case of negative value subtract 256 from the sum to convert from 2's complement 8+4bit
# fractional value to negative float
temp: float = (upper + lower) - 256 if sign else upper + lower
return temp
def get_alert_triggers(self) -> tuple[bool, bool, bool]:
"""Get the alert triggers.
Trigger bits are not influenced by the alert output mode (compare or interrupt) or by the
alert polarity (active high or active low) or by the alert control (enable or disable).
Returns:
``tuple[bool, bool, bool]``: A tuple containing the alert triggers.
The first element is True if the temperature is greater or equal to the critical
limit.
The second element is True if the temperature is greater than the upper limit.
The third element is True if the temperature is less than the lower limit.
"""
# Read temperature register from sensor
buf: bytes = self._i2c.readfrom_mem(self._addr, self.REG_TEM, 2)
# Extract the 16th bit (last), Ta vs. Tcrit. False = Ta < Tcrit | True = Ta >= Tcrit
ta_tcrit = bool(buf[0] & 0x80)
# Extract the 15th bit, Ta vs. Tupper. False = Ta <= Tupper | True = Ta > Tupper
ta_tupper = bool(buf[0] & 0x40)
# Extract the 14th bit, Ta vs Tlower. False = Ta >= Tlower | True = Ta < Tlower
ta_tlower = bool(buf[0] & 0x20)
return ta_tcrit, ta_tupper, ta_tlower
def set_resolution(self, resolution=RES_0_0625) -> None:
"""Set the resolution of the sensor.
Args:
resolution (int, optional): The resolution to set.
Valid values are RES_0_5, RES_0_25, RES_0_125, RES_0_0625.
Defaults to RES_0_0625.
Raises:
ValueError: If the resolution is not a valid value.
Debug:
- Issue a warning if the resolution was not set correctly.
Returns:
``None``
"""
# Check if resolution is a compatible value
if resolution not in [RES_0_5, RES_0_25, RES_0_125, RES_0_0625]:
raise ValueError(
f"Invalid resolution: {resolution}. Value should be between 0 and 3 inclusive.",
)
buf = bytearray(b"\x00")
buf[0] |= resolution & 0x03
self._i2c.writeto_mem(self._addr, self.REG_RES, buf)
if self._debug:
check = self._i2c.readfrom_mem(self._addr, self.REG_RES, 1)
if check != buf:
print(
f"[WARN] Failed to set resolution. Set {resolution} got {check[0]}"
)
@property
def hyst_mode(self) -> int:
"""Get the hysteresis mode.
Returns:
``int``: The hysteresis mode.
"""
self._get_config()
return self._hyst_mode
@hyst_mode.setter
def hyst_mode(self, hyst_mode: int) -> None:
"""Set the hysteresis mode.
Args:
``hyst_mode`` (int): The hysteresis mode to set.
Valid values are HYST_00, HYST_15, HYST_30, HYST_60.
"""
self._set_config(hyst_mode=hyst_mode)
@property
def shdn(self) -> bool:
"""Get the shutdown mode.
Returns:
``bool``: The shutdown mode.
"""
self._get_config()
return self._shdn
@property
def crit_lock(self) -> bool:
"""Get the critical temperature register lock.
Returns:
``bool``: The critical temperature register lock.
"""
self._get_config()
return self._crit_lock
@property
def alerts_lock(self) -> bool:
"""Get the alerts temperature registers lock.
Returns:
``bool``: The alerts temperature registers lock.
"""
self._get_config()
return self._alerts_lock
@property
def alert(self) -> bool:
"""Get the alert control.
Returns:
``bool``: The alert control.
"""
self._get_config()
return self._alert
@property
def alert_ctrl(self) -> bool:
"""Get the alert control.
Returns:
``bool``: The alert control.
"""
self._get_config()
return self._alert_ctrl
@property
def alert_sel(self) -> bool:
"""Get the alert output select.
Returns:
``bool``: The alert output select.
"""
self._get_config()
return self._alert_sel
@property
def alert_mode(self) -> bool:
"""Get the alert output mode.
Returns:
``bool``: The alert output mode.
"""
self._get_config()
return self._alert_mode