Skip to content

Commit c0e29d3

Browse files
committed
Improve efficiency of I2C scanning
1 parent e298ebb commit c0e29d3

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

src/modulino/modulino.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class Modulino:
133133
This class variable needs to be overridden in derived classes.
134134
"""
135135

136-
def __init__(self, i2c_bus: I2C = None, address: int = None, name: str = None):
136+
def __init__(self, i2c_bus: I2C = None, address: int = None, name: str = None, check_connection: bool = True) -> None:
137137
"""
138138
Initializes the Modulino object with the given i2c bus and address.
139139
If the address is not provided, the device will try to auto discover it.
@@ -145,6 +145,7 @@ def __init__(self, i2c_bus: I2C = None, address: int = None, name: str = None):
145145
i2c_bus (I2C): The I2C bus to use. If not provided, the default I2C bus will be used.
146146
address (int): The address of the device. If not provided, the device will try to auto discover it.
147147
name (str): The name of the device.
148+
check_connection (bool): Whether to check if the device is connected to the bus.
148149
"""
149150

150151
if i2c_bus is None:
@@ -168,7 +169,7 @@ def __init__(self, i2c_bus: I2C = None, address: int = None, name: str = None):
168169

169170
if self.address is None:
170171
raise RuntimeError(f"Couldn't find the {self.name} device on the bus. Try resetting the board.")
171-
elif not self.connected:
172+
elif check_connection and not self.connected:
172173
raise RuntimeError(f"Couldn't find a {self.name} device with address {hex(self.address)} on the bus. Try resetting the board.")
173174

174175
def discover(self, default_addresses: list[int]) -> int | None:
@@ -183,11 +184,9 @@ def discover(self, default_addresses: list[int]) -> int | None:
183184
if len(default_addresses) == 0:
184185
return None
185186

186-
devices_on_bus = Modulino.scan(self.i2c_bus)
187-
for addr in default_addresses:
188-
if addr in devices_on_bus:
189-
return addr
190-
187+
devices_on_bus = Modulino.scan(self.i2c_bus, default_addresses)
188+
if len(devices_on_bus) > 0:
189+
return devices_on_bus[0]
191190
return None
192191

193192
def __bool__(self) -> bool:
@@ -207,7 +206,12 @@ def connected(self) -> bool:
207206
"""
208207
if not bool(self):
209208
return False
210-
return self.address in Modulino.scan(self.i2c_bus)
209+
210+
try:
211+
self.i2c_bus.writeto(self.address, b'')
212+
return True
213+
except OSError:
214+
return False
211215

212216
@property
213217
def pin_strap_address(self) -> int | None:
@@ -315,10 +319,12 @@ def has_default_address(self) -> bool:
315319
return self.address in self.default_addresses
316320

317321
@staticmethod
318-
def scan(bus: I2C) -> list[int]:
322+
def scan(bus: I2C, target_addresses = None) -> list[int]:
319323
addresses = bytearray() # Use 8bit data type
320-
# Skip general call address (0x00)
321-
for address in range(1,128):
324+
# General call address (0x00) is skipped in default range
325+
candidates = target_addresses if target_addresses is not None else range(1,128)
326+
327+
for address in candidates:
322328
try:
323329
bus.writeto(address, b'')
324330
addresses.append(address)
@@ -345,7 +351,7 @@ def available_devices(bus: I2C = None) -> list[Modulino]:
345351
if address == _BOOTLOADER_ADDRESS:
346352
# Skip bootloader address
347353
continue
348-
device = Modulino(i2c_bus=bus, address=address)
354+
device = Modulino(i2c_bus=bus, address=address, check_connection=False)
349355
devices.append(device)
350356
return devices
351357

0 commit comments

Comments
 (0)