15
15
**Hardware:**
16
16
17
17
* `Adafruit DS2484 I2C to 1-Wire Bus Adapter Breakout <https://www.adafruit.com/product/5976>`_
18
+ * `Adafruit DS2482S-800 8 Channel I2C to 1-Wire Breakout <https://www.adafruit.com/product/6027>`_
18
19
19
20
**Software and Dependencies:**
20
21
46
47
_1WIRE_WRITE_BYTE = const (0xA5 )
47
48
_1WIRE_READ_BYTE = const (0x96 )
48
49
_TRIPLET = const (0x78 )
50
+ _CHANNEL_SELECT = const (0xC3 )
49
51
50
52
# DS248x Register Definitions
51
53
_REG_STATUS = const (0xF0 )
61
63
62
64
class Adafruit_DS248x :
63
65
"""
64
- Driver for the DS2484 1-Wire to I2C Bus Adapter.
66
+ Driver for the DS248x 1-Wire to I2C Bus Adapter.
65
67
"""
66
68
67
69
def __init__ (self , i2c : I2C , address : int = 0x18 ):
@@ -74,6 +76,7 @@ def __init__(self, i2c: I2C, address: int = 0x18):
74
76
try :
75
77
self .i2c_device = I2CDevice (i2c , address )
76
78
self ._address = address
79
+ self ._selected_channel = - 1
77
80
self .rom_no : bytearray = bytearray (8 )
78
81
self .last_discrepancy : int = 0
79
82
self .last_device_flag : bool = False
@@ -87,7 +90,9 @@ def __init__(self, i2c: I2C, address: int = 0x18):
87
90
raise RuntimeError ("\t No presence pulse" )
88
91
time .sleep (1 )
89
92
except RuntimeError as exception :
90
- raise RuntimeError ("DS248x initialization failed." ) from exception
93
+ raise RuntimeError (
94
+ f"DS248x initialization failed: { exception } "
95
+ ) from exception
91
96
92
97
def reset (self ) -> bool :
93
98
"""
@@ -374,37 +379,82 @@ def branch_dir_taken(self) -> bool:
374
379
status = self .status
375
380
return status != 0xFF and (status & 0x80 )
376
381
377
- def ds18b20_temperature (self , rom : bytearray ) -> float :
382
+ def ds18b20_temperature (self , rom : bytearray = None ) -> float :
378
383
"""
379
- Reads the temperature from a DS18B20 sensor.
384
+ Reads the temperature from a DS18B20 sensor. If no ROM address is provided,
385
+ then a channel is read (0-7) from the DS2482S-800.
380
386
381
- :param rom: The ROM address of the DS18B20 sensor
387
+ :param rom: The ROM address of the DS18B20 sensor (optional)
382
388
:return: The temperature in Celsius
383
389
"""
384
- if rom [0 ] != _DS18B20_FAMILY :
385
- raise ValueError ("Device attached is not a DS18B20" )
386
-
387
- self .onewire_reset ()
388
- self .onewire_byte = 0x55 # Match ROM command
389
- for byte in rom :
390
- self .onewire_byte = byte
391
-
392
- self .onewire_byte = 0x44 # Convert T command
390
+ if rom :
391
+ if rom [0 ] != _DS18B20_FAMILY :
392
+ raise ValueError ("Device attached is not a DS18B20" )
393
+ # Match ROM if a ROM address is provided
394
+ self .onewire_reset ()
395
+ self .onewire_byte = 0x55
396
+ for byte in rom :
397
+ self .onewire_byte = byte
398
+ else :
399
+ # Skip ROM if no ROM address is provided
400
+ self .onewire_reset ()
401
+ self .onewire_byte = 0xCC
402
+ self .onewire_byte = 0x44
393
403
time .sleep (0.75 )
394
-
395
- self .onewire_reset ()
396
- self .onewire_byte = 0x55
397
- for byte in rom :
398
- self .onewire_byte = byte
399
- self .onewire_byte = 0xBE # Read Scratchpad command
400
-
404
+ if rom :
405
+ self .onewire_reset ()
406
+ self .onewire_byte = 0x55
407
+ for byte in rom :
408
+ self .onewire_byte = byte
409
+ else :
410
+ self .onewire_reset ()
411
+ self .onewire_byte = 0xCC
412
+ self .onewire_byte = 0xBE
401
413
data = bytearray (9 )
402
414
for i in range (9 ):
403
415
data [i ] = self .onewire_byte
404
-
405
416
raw = (data [1 ] << 8 ) | data [0 ]
406
417
if raw & 0x8000 :
407
418
raw -= 1 << 16
408
419
celsius = raw / 16.0
409
-
410
420
return celsius
421
+
422
+ @property
423
+ def channel (self ) -> int :
424
+ """
425
+ Gets the current selected channel on the DS2482-800 by querying the device.
426
+
427
+ :return: The currenctly selected channel.
428
+ """
429
+ if self ._selected_channel is None :
430
+ raise ValueError ("No channel has been selected yet" )
431
+ channel_code = self ._selected_channel + (~ self ._selected_channel << 4 ) & 0xFF
432
+ cmd = bytearray ([_CHANNEL_SELECT , channel_code ])
433
+ reply = bytearray (1 )
434
+ with self .i2c_device as i2c :
435
+ i2c .write (cmd )
436
+ i2c .readinto (reply )
437
+ return_codes = [0xB8 , 0xB1 , 0xAA , 0xA3 , 0x9C , 0x95 , 0x8E , 0x87 ]
438
+ if reply [0 ] in return_codes :
439
+ return return_codes .index (reply [0 ])
440
+ raise ValueError ("Unknown channel code returned from the device" )
441
+
442
+ @channel .setter
443
+ def channel (self , chan : int ) -> None :
444
+ """
445
+ Sets the channel on the DS2482-800.
446
+
447
+ :param chan: Channel to use, from 0 to 7 inclusive
448
+ """
449
+ if chan > 7 :
450
+ raise ValueError ("Channel must be between 0 and 7" )
451
+ channel_code = chan + (~ chan << 4 ) & 0xFF
452
+ cmd = bytearray ([_CHANNEL_SELECT , channel_code ])
453
+ reply = bytearray (1 )
454
+ with self .i2c_device as i2c :
455
+ i2c .write (cmd )
456
+ i2c .readinto (reply )
457
+ return_codes = [0xB8 , 0xB1 , 0xAA , 0xA3 , 0x9C , 0x95 , 0x8E , 0x87 ]
458
+ if return_codes [chan ] != reply [0 ]:
459
+ raise RuntimeError ("Failed to set the channel" )
460
+ self ._selected_channel = chan
0 commit comments