Skip to content

Commit 132ca92

Browse files
authored
Merge pull request #6 from BlitzCityDIY/add_DS2482S-800
Add DS2482S-800 support
2 parents 1d76d6e + 424bd2f commit 132ca92

File tree

4 files changed

+105
-24
lines changed

4 files changed

+105
-24
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Introduction
33

44

55
.. image:: https://readthedocs.org/projects/adafruit-circuitpython-ds248x/badge/?version=latest
6-
:target: https://docs.circuitpython.org/projects/ds248x/en/latest/
6+
:target: https://adafruit-circuitpython-ds248x.readthedocs.io/en/latest/
77
:alt: Documentation Status
88

99

adafruit_ds248x.py

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
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
@@ -46,6 +47,7 @@
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)
@@ -61,7 +63,7 @@
6163

6264
class 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("\tNo 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

docs/examples.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,12 @@ Ensure your device works with this simple test.
66
.. literalinclude:: ../examples/ds248x_simpletest.py
77
:caption: examples/ds248x_simpletest.py
88
:linenos:
9+
10+
DS2482S-800 8-Channel example
11+
-----------------------------
12+
13+
Read all 8 channels from the DS2482S-800
14+
15+
.. literalinclude:: ../examples/ds2482s-800_8-channel_test.py
16+
:caption: examples/ds2482s-800_8-channel_test.py
17+
:linenos:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""Adafruit DS2482S-800 8-Channel DS18B20 Example"""
6+
7+
import time
8+
import board
9+
from adafruit_ds248x import Adafruit_DS248x
10+
11+
# Initialize I2C bus and DS248x
12+
i2c = board.STEMMA_I2C()
13+
ds248x = Adafruit_DS248x(i2c)
14+
15+
while True:
16+
for i in range(8):
17+
ds248x.channel = i
18+
print(f"Reading channel {ds248x.channel}")
19+
temperature = ds248x.ds18b20_temperature()
20+
print(f"Temperature: {temperature:.2f} °C")
21+
print()
22+
time.sleep(1)

0 commit comments

Comments
 (0)