1515**Hardware:**
1616
1717* `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>`_
1819
1920**Software and Dependencies:**
2021
4647_1WIRE_WRITE_BYTE = const (0xA5 )
4748_1WIRE_READ_BYTE = const (0x96 )
4849_TRIPLET = const (0x78 )
50+ _CHANNEL_SELECT = const (0xC3 )
4951
5052# DS248x Register Definitions
5153_REG_STATUS = const (0xF0 )
6163
6264class Adafruit_DS248x :
6365 """
64- Driver for the DS2484 1-Wire to I2C Bus Adapter.
66+ Driver for the DS248x 1-Wire to I2C Bus Adapter.
6567 """
6668
6769 def __init__ (self , i2c : I2C , address : int = 0x18 ):
@@ -74,6 +76,7 @@ def __init__(self, i2c: I2C, address: int = 0x18):
7476 try :
7577 self .i2c_device = I2CDevice (i2c , address )
7678 self ._address = address
79+ self ._selected_channel = - 1
7780 self .rom_no : bytearray = bytearray (8 )
7881 self .last_discrepancy : int = 0
7982 self .last_device_flag : bool = False
@@ -87,7 +90,9 @@ def __init__(self, i2c: I2C, address: int = 0x18):
8790 raise RuntimeError ("\t No presence pulse" )
8891 time .sleep (1 )
8992 except RuntimeError as exception :
90- raise RuntimeError ("DS248x initialization failed." ) from exception
93+ raise RuntimeError (
94+ f"DS248x initialization failed: { exception } "
95+ ) from exception
9196
9297 def reset (self ) -> bool :
9398 """
@@ -374,37 +379,82 @@ def branch_dir_taken(self) -> bool:
374379 status = self .status
375380 return status != 0xFF and (status & 0x80 )
376381
377- def ds18b20_temperature (self , rom : bytearray ) -> float :
382+ def ds18b20_temperature (self , rom : bytearray = None ) -> float :
378383 """
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.
380386
381- :param rom: The ROM address of the DS18B20 sensor
387+ :param rom: The ROM address of the DS18B20 sensor (optional)
382388 :return: The temperature in Celsius
383389 """
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
393403 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
401413 data = bytearray (9 )
402414 for i in range (9 ):
403415 data [i ] = self .onewire_byte
404-
405416 raw = (data [1 ] << 8 ) | data [0 ]
406417 if raw & 0x8000 :
407418 raw -= 1 << 16
408419 celsius = raw / 16.0
409-
410420 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